summaryrefslogtreecommitdiff
path: root/easy_install.py
diff options
context:
space:
mode:
authorpje <pje@6015fed2-1504-0410-9fe1-9d1591cc4771>2005-05-29 22:08:46 +0000
committerpje <pje@6015fed2-1504-0410-9fe1-9d1591cc4771>2005-05-29 22:08:46 +0000
commit78e3c7fda9726d98ed481c8c795642dd36d9ee81 (patch)
tree1de2feee9178d036b762d7d9a2b631d86f84d19d /easy_install.py
parent8432a6463473f25dfddf39ea88ea0a06a3ed1a33 (diff)
downloadpython-setuptools-78e3c7fda9726d98ed481c8c795642dd36d9ee81.tar.gz
Add subversion support, loosely based on an implementation by Ian Bicking.
EasyInstall now recognizes both 'svn' URLs (including 'svn+ssh' et al), and notices when it connects to an HTTP server that's actually a subversion repository. In either case it does a subversion checkout of the package. Also, fixed a bug on platforms with os.samefile(). git-svn-id: http://svn.python.org/projects/sandbox/trunk/setuptools@41025 6015fed2-1504-0410-9fe1-9d1591cc4771
Diffstat (limited to 'easy_install.py')
-rwxr-xr-xeasy_install.py111
1 files changed, 76 insertions, 35 deletions
diff --git a/easy_install.py b/easy_install.py
index eb294d0..960cfe7 100755
--- a/easy_install.py
+++ b/easy_install.py
@@ -153,23 +153,21 @@ Options
need.
"""
-import sys, os.path, pkg_resources, re, zipimport
+import sys, os.path, pkg_resources, re, zipimport, zipfile, tarfile, shutil
+from distutils.sysconfig import get_python_lib
+from shutil import rmtree # must have, because it can be called from __del__
from pkg_resources import *
-
-
class Installer:
"""Manage a download/build/install process"""
pth_file = None
def __init__(self, instdir=None, zip_ok=False, multi=None, tmpdir=None):
- from distutils.sysconfig import get_python_lib
- site_packages = get_python_lib()
if tmpdir is None:
from tempfile import mkdtemp
@@ -177,6 +175,7 @@ class Installer:
self.tmpdir = tmpdir
+ site_packages = get_python_lib()
if instdir is None or self.samefile(site_packages,instdir):
instdir = site_packages
self.pth_file = PthDistributions(
@@ -197,22 +196,23 @@ class Installer:
def close(self):
if os.path.isdir(self.tmpdir):
- from shutil import rmtree
rmtree(self.tmpdir,True)
def __del__(self):
self.close()
+
+
def samefile(self,p1,p2):
- try:
- os.path.samefile
- except AttributeError:
- return (
- os.path.normpath(os.path.normcase(p1)) ==
- os.path.normpath(os.path.normcase(p2))
- )
- else:
+ if hasattr(os.path,'samefile') and (
+ os.path.exists(p1) and os.path.exists(p2)
+ ):
return os.path.samefile(p1,p2)
+ return (
+ os.path.normpath(os.path.normcase(p1)) ==
+ os.path.normpath(os.path.normcase(p2))
+ )
+
def download(self, spec):
"""Locate and/or download or `spec`, returning a local filename"""
@@ -222,7 +222,7 @@ class Installer:
scheme = URL_SCHEME(spec)
if scheme:
# It's a url, download it to self.tmpdir
- return self._download_url(scheme, spec)
+ return self._download_url(scheme.group(1), spec)
elif os.path.exists(spec):
# Existing file or directory, just return it
@@ -250,19 +250,8 @@ class Installer:
return self.install_egg(dist_filename,True)
# Anything else, try to extract and build
- import zipfile, tarfile
- if zipfile.is_zipfile(dist_filename):
- self._extract_zip(dist_filename, self.tmpdir)
- else:
- import tarfile
- try:
- tar = tarfile.open(dist_filename)
- except tarfile.TarError:
- raise RuntimeError(
- "Not a valid tar or zip archive: %s" % dist_filename
- )
- else:
- self._extract_tar(tar)
+ if os.path.isfile(dist_filename):
+ self._extract_file(dist_filename)
# Find the setup.py file
from glob import glob
@@ -285,6 +274,17 @@ class Installer:
):
self.install_egg(egg, self.zip_ok)
+
+
+
+
+
+
+
+
+
+
+
def _extract_zip(self,zipname,extract_dir):
import zipfile
z = zipfile.ZipFile(zipname)
@@ -351,7 +351,7 @@ class Installer:
sys.argv[:] = save_argv
- def _find_package(self, req):
+ def _find_package(self, req):
# TODO: search here for a distro to download, matching Requirement
# 'req' and return the package URL or filename
raise DistributionNotFound(spec)
@@ -412,16 +412,24 @@ class Installer:
# Determine download filename
from urlparse import urlparse
name = filter(None,urlparse(url)[2].split('/'))[-1]
+
while '..' in name:
name = name.replace('..','.').replace('\\','_')
+ filename = os.path.join(self.tmpdir,name)
+
+ if scheme=='svn' or scheme.startswith('svn+'):
+ return self._download_svn(url, filename)
+
# Download the file
from urllib import FancyURLopener, URLopener
- class opener(FancyURLopener):
+
+ class _opener(FancyURLopener):
http_error_default = URLopener.http_error_default
+
try:
- filename,headers = opener().retrieve(
- url,os.path.join(self.tmpdir,name)
+ filename,headers = _opener().retrieve(
+ url,filename
)
except IOError,v:
if v.args and v.args[0]=='http error':
@@ -430,6 +438,10 @@ class Installer:
)
else:
raise
+
+ if headers['content-type'].lower().startswith('text/html'):
+ return self._download_html(url, headers, filename)
+
# and return its filename
return filename
@@ -437,9 +449,38 @@ class Installer:
+ def _extract_file(self, dist_filename):
+ if zipfile.is_zipfile(dist_filename):
+ self._extract_zip(dist_filename, self.tmpdir)
+ else:
+ try:
+ tar = tarfile.open(dist_filename)
+ except tarfile.TarError:
+ raise RuntimeError(
+ "Not a valid tar or zip archive: %s" % dist_filename
+ )
+ else:
+ self._extract_tar(tar)
+
+ def _download_html(self, url, headers, filename):
+ # Check if it is a subversion index page:
+ file = open(filename)
+ for line in file:
+ if line.strip():
+ if re.search(r'<title>Revision \d+:', line):
+ file.close()
+ os.unlink(filename)
+ return self._download_svn(url, filename)
+ else:
+ break # not an index page
+ file.close()
+ raise RuntimeError("Unexpected HTML page found at "+url)
+ def _download_svn(self, url, filename):
+ os.system("svn checkout -q %s %s" % (url, filename))
+ return filename
@@ -511,7 +552,7 @@ def main(argv, factory=Installer):
try:
if not args:
- raise RuntimeError("No urls, filenames, or requirements specified")
+ parser.error("No urls, filenames, or requirements specified")
for spec in args:
inst = factory(options.instdir, options.zip_ok, options.multi)
@@ -523,11 +564,11 @@ def main(argv, factory=Installer):
finally:
inst.close()
except RuntimeError, v:
- parser.error(str(v))
+ print >>sys.stderr,"error:",v
+ sys.exit(1)
if __name__ == '__main__':
main(sys.argv[1:])
-