summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Bicking <ianb@colorstudy.com>2009-10-07 14:55:50 -0500
committerIan Bicking <ianb@colorstudy.com>2009-10-07 14:55:50 -0500
commit055456b0192ee129935a14acb74cd7861249b2da (patch)
tree89920a9a99e0b5c205f4109d6caf0d631027dd04
parent1a297af7c6dbc7989cc5811fcf0b364b0c8f0bab (diff)
parentcbb4b19e00448764dc1ea8868b8a73050dc05207 (diff)
downloadpip-055456b0192ee129935a14acb74cd7861249b2da.tar.gz
merge
-rw-r--r--docs/news.txt11
-rw-r--r--pip.py432
-rw-r--r--tests/test_basic.txt13
-rw-r--r--tests/test_freeze.txt16
4 files changed, 222 insertions, 250 deletions
diff --git a/docs/news.txt b/docs/news.txt
index 1846f2307..076f129b2 100644
--- a/docs/news.txt
+++ b/docs/news.txt
@@ -40,10 +40,21 @@ tip
* Fixed handling read-only attributes of build files, e.g. of Subversion and
Bazaar on Windows.
+<<<<<<< /home/ianb/src/pip/docs/news.txt
* When downloading a file from a redirect, use the redirected
location's extension to guess the compression (happens specifically
when redirecting to a bitbucket.org tip.gz file).
+* Editable freeze URLs now always use revision hash/id rather than tip or
+ branch names which could move.
+
+* Fixed comparison of repo URLs so incidental differences such as
+ presence/absence of final slashes or quoted/unquoted special
+ characters don't trigger "ignore/switch/wipe/backup" choice.
+
+* Fixed handling of attempt to checkout editable install to a
+ non-empty, non-repo directory.
+
0.4
---
diff --git a/pip.py b/pip.py
index a4ae60a4c..dedcba5d2 100644
--- a/pip.py
+++ b/pip.py
@@ -2687,6 +2687,8 @@ class FrozenRequirement(object):
req = '-e %s' % req
return '\n'.join(list(self.comments)+[str(req)])+'\n'
+(_CAN_SWITCH, _NO_SWITCH) = (1, 2)
+
class VersionControl(object):
name = ''
dirname = ''
@@ -2718,6 +2720,18 @@ class VersionControl(object):
assert not location.rstrip('/').endswith(self.dirname), 'Bad directory: %s' % location
return self.get_url(location), self.get_revision(location)
+ def normalize_url(self, url):
+ """
+ Normalize a URL for comparison by unquoting it and removing any trailing slash.
+ """
+ return urllib.unquote(url).rstrip('/')
+
+ def compare_urls(self, url1, url2):
+ """
+ Compare two repo URLs for identity, ignoring incidental differences.
+ """
+ return (self.normalize_url(url1) == self.normalize_url(url2))
+
def parse_vcs_bundle_file(self, content):
"""
Takes the contents of the bundled text file that explains how to revert
@@ -2733,6 +2747,69 @@ class VersionControl(object):
"""
raise NotImplementedError
+ def switch(self, dest, url, rev_options):
+ """
+ Switch the repo at ``dest`` to point to ``URL``.
+ """
+ raise NotImplemented
+
+ def update(self, dest, rev_options):
+ """
+ Update an already-existing repo to the given ``rev_options``.
+ """
+ raise NotImplementedError
+
+ def check_destination(self, dest, url, rev_options, rev_display):
+ """
+ Prepare a location to receive a checkout/clone.
+
+ Return True if the location is ready for (and requires) a
+ checkout/clone, False otherwise.
+ """
+ checkout = True
+ prompt = False
+ if os.path.exists(dest):
+ checkout = False
+ if os.path.exists(os.path.join(dest, self.dirname)):
+ existing_url = self.get_url(dest)
+ if self.compare_urls(existing_url, url):
+ logger.info('%s in %s exists, and has correct URL (%s)'
+ % (self.repo_name.title(), display_path(dest), url))
+ logger.notify('Updating %s %s%s'
+ % (display_path(dest), self.repo_name, rev_display))
+ self.update(dest, rev_options)
+ else:
+ logger.warn('%s %s in %s exists with URL %s'
+ % (self.name, self.repo_name, display_path(dest), existing_url))
+ prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
+ else:
+ logger.warn('Directory %s already exists, and is not a %s %s.'
+ % (dest, self.name, self.repo_name))
+ prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))
+ if prompt:
+ logger.warn('The plan is to install the %s repository %s'
+ % (self.name, url))
+ response = ask('What to do? %s' % prompt[0], prompt[1])
+
+ if response == 's':
+ logger.notify('Switching %s %s to %s%s'
+ % (self.repo_name, display_path(dest), url, rev_display))
+ self.switch(dest, url, rev_options)
+ elif response == 'i':
+ # do nothing
+ pass
+ elif response == 'w':
+ logger.warn('Deleting %s' % display_path(dest))
+ shutil.rmtree(dest)
+ checkout = True
+ elif response == 'b':
+ dest_dir = backup_dir(dest)
+ logger.warn('Backing up %s to %s'
+ % (display_path(dest), dest_dir))
+ shutil.move(dest, dest_dir)
+ checkout = True
+ return checkout
+
def unpack(self, location):
raise NotImplementedError
@@ -2747,6 +2824,7 @@ _svn_revision_re = re.compile(r'Revision: (.+)')
class Subversion(VersionControl):
name = 'svn'
dirname = '.svn'
+ repo_name = 'checkout'
schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https')
bundle_file = 'svn-checkout.txt'
guide = ('# This was an svn checkout; to make it a checkout again run:\n'
@@ -2761,15 +2839,21 @@ class Subversion(VersionControl):
if not match:
logger.warn('Cannot determine URL of svn checkout %s' % display_path(location))
logger.info('Output that cannot be parsed: \n%s' % output)
- return 'unknown', 'unknown'
+ return None, None
url = match.group(1).strip()
match = _svn_revision_re.search(output)
if not match:
logger.warn('Cannot determine revision of svn checkout %s' % display_path(location))
logger.info('Output that cannot be parsed: \n%s' % output)
- return url, 'unknown'
+ return url, None
return url, match.group(1)
+ def get_url(self, location):
+ return self.get_info(location)[0]
+
+ def get_revision(self, location):
+ return self.get_info(location)[1]
+
def parse_vcs_bundle_file(self, content):
for line in content.splitlines():
if not line.strip() or line.strip().startswith('#'):
@@ -2814,6 +2898,14 @@ class Subversion(VersionControl):
finally:
logger.indent -= 2
+ def switch(self, dest, url, rev_options):
+ call_subprocess(
+ ['svn', 'switch'] + rev_options + [url, dest])
+
+ def update(self, dest, rev_options):
+ call_subprocess(
+ ['svn', 'update'] + rev_options + [dest])
+
def obtain(self, dest):
url, rev = self.get_url_rev()
if rev:
@@ -2822,42 +2914,7 @@ class Subversion(VersionControl):
else:
rev_options = []
rev_display = ''
- checkout = True
- if os.path.exists(os.path.join(dest, self.dirname)):
- existing_url = self.get_info(dest)[0]
- checkout = False
- if existing_url == url:
- logger.info('Checkout in %s exists, and has correct URL (%s)'
- % (display_path(dest), url))
- logger.notify('Updating checkout %s%s'
- % (display_path(dest), rev_display))
- call_subprocess(
- ['svn', 'update'] + rev_options + [dest])
- else:
- logger.warn('svn checkout in %s exists with URL %s'
- % (display_path(dest), existing_url))
- logger.warn('The plan is to install the svn repository %s'
- % url)
- response = ask('What to do? (s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
- if response == 's':
- logger.notify('Switching checkout %s to %s%s'
- % (display_path(dest), url, rev_display))
- call_subprocess(
- ['svn', 'switch'] + rev_options + [url, dest])
- elif response == 'i':
- # do nothing
- pass
- elif response == 'w':
- logger.warn('Deleting %s' % display_path(dest))
- shutil.rmtree(dest)
- checkout = True
- elif response == 'b':
- dest_dir = backup_dir(dest)
- logger.warn('Backing up %s to %s'
- % (display_path(dest), dest_dir))
- shutil.move(dest, dest_dir)
- checkout = True
- if checkout:
+ if self.check_destination(dest, url, rev_options, rev_display):
logger.notify('Checking out %s%s to %s'
% (url, rev_display, display_path(dest)))
call_subprocess(
@@ -2985,29 +3042,29 @@ class Subversion(VersionControl):
parts = repo.split('/')
## FIXME: why not project name?
egg_project_name = dist.egg_name().split('-', 1)[0]
+ rev = self.get_revision(location)
if parts[-2] in ('tags', 'tag'):
# It's a tag, perfect!
- return 'svn+%s#egg=%s-%s' % (repo, egg_project_name, parts[-1])
+ full_egg_name = '%s-%s' % (egg_project_name, parts[-1])
elif parts[-2] in ('branches', 'branch'):
# It's a branch :(
- rev = self.get_revision(location)
- return 'svn+%s@%s#egg=%s%s-r%s' % (repo, rev, dist.egg_name(), parts[-1], rev)
+ full_egg_name = '%s-%s-r%s' % (dist.egg_name(), parts[-1], rev)
elif parts[-1] == 'trunk':
# Trunk :-/
- rev = self.get_revision(location)
+ full_egg_name = '%s-dev_r%s' % (dist.egg_name(), rev)
if find_tags:
tag_url = '/'.join(parts[:-1]) + '/tags'
tag_revs = self.get_tag_revs(tag_url)
match = self.find_tag_match(rev, tag_revs)
if match:
logger.notify('trunk checkout %s seems to be equivalent to tag %s' % match)
- return 'svn+%s/%s#egg=%s-%s' % (tag_url, match, egg_project_name, match)
- return 'svn+%s@%s#egg=%s-dev' % (repo, rev, dist.egg_name())
+ repo = '%s/%s' % (tag_url, match)
+ full_egg_name = '%s-%s' % (egg_project_name, match)
else:
# Don't know what it is
logger.warn('svn URL does not fit normal structure (tags/branches/trunk): %s' % repo)
- rev = self.get_revision(location)
- return 'svn+%s@%s#egg=%s-dev' % (repo, rev, egg_project_name)
+ full_egg_name = '%s-dev_r%s' % (egg_project_name, rev)
+ return 'svn+%s@%s#egg=%s' % (repo, rev, full_egg_name)
vcs.register(Subversion)
@@ -3015,6 +3072,7 @@ vcs.register(Subversion)
class Git(VersionControl):
name = 'git'
dirname = '.git'
+ repo_name = 'clone'
schemes = ('git', 'git+http', 'git+ssh', 'git+git')
bundle_file = 'git-clone.txt'
guide = ('# This was a Git repo; to make it a repo again run:\n'
@@ -3083,6 +3141,18 @@ class Git(VersionControl):
% (rev, display_path(dest)))
return [rev]
+ def switch(self, dest, url, rev_options):
+ remote_name = self.get_remote_name(location)
+ call_subprocess(
+ [GIT_CMD, 'config', 'remote.%s.url' % remote_name, url], cwd=dest)
+ call_subprocess(
+ [GIT_CMD, 'checkout', '-q'] + rev_options, cwd=dest)
+
+ def update(self, dest, rev_options):
+ call_subprocess([GIT_CMD, 'fetch', '-q'], cwd=dest)
+ call_subprocess(
+ [GIT_CMD, 'checkout', '-q', '-f'] + rev_options, cwd=dest)
+
def obtain(self, dest):
url, rev = self.get_url_rev()
if rev:
@@ -3091,45 +3161,7 @@ class Git(VersionControl):
else:
rev_options = ['origin/master']
rev_display = ''
- clone = True
- if os.path.exists(os.path.join(dest, self.dirname)):
- existing_url = self.get_url(dest)
- rev_options = self.check_rev_options(rev, dest, rev_options)
- clone = False
- if existing_url == url:
- logger.info('Clone in %s exists, and has correct URL (%s)'
- % (display_path(dest), url))
- logger.notify('Updating clone %s%s'
- % (display_path(dest), rev_display))
- call_subprocess([GIT_CMD, 'fetch', '-q'], cwd=dest)
- call_subprocess(
- [GIT_CMD, 'checkout', '-q', '-f'] + rev_options, cwd=dest)
- else:
- logger.warn('Git clone in %s exists with URL %s'
- % (display_path(dest), existing_url))
- logger.warn('The plan is to install the Git repository %s'
- % url)
- response = ask('What to do? (s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
- if response == 's':
- logger.notify('Switching clone %s to %s%s'
- % (display_path(dest), url, rev_display))
- call_subprocess(
- [GIT_CMD, 'config', 'remote.origin.url', url], cwd=dest)
- call_subprocess(
- [GIT_CMD, 'checkout', '-q'] + rev_options, cwd=dest)
- elif response == 'i':
- # do nothing
- pass
- elif response == 'w':
- logger.warn('Deleting %s' % display_path(dest))
- shutil.rmtree(dest)
- clone = True
- elif response == 'b':
- dest_dir = backup_dir(dest)
- logger.warn('Backing up %s to %s' % (display_path(dest), dest_dir))
- shutil.move(dest, dest_dir)
- clone = True
- if clone:
+ if self.check_destination(dest, url, rev_options, rev_display):
logger.notify('Cloning %s%s to %s' % (url, rev_display, display_path(dest)))
call_subprocess(
[GIT_CMD, 'clone', '-q', url, dest])
@@ -3137,9 +3169,22 @@ class Git(VersionControl):
call_subprocess(
[GIT_CMD, 'checkout', '-q'] + rev_options, cwd=dest)
+ def get_remote_name(self, location):
+ """First gets the name of the current HEAD, e.g. master. Then returns
+ the name of the remote which the head is tracking."""
+ head_ref = call_subprocess(
+ [GIT_CMD, 'symbolic-ref', '-q', 'HEAD'],
+ show_stdout=False, cwd=location).strip()
+ head_ref = head_ref.split('refs/heads/', 1)[-1]
+ remote_name = call_subprocess(
+ [GIT_CMD, 'config', 'branch.%s.remote' % head_ref],
+ show_stdout=False, cwd=location).strip()
+ return remote_name
+
def get_url(self, location):
+ remote_name = self.get_remote_name(location)
url = call_subprocess(
- [GIT_CMD, 'config', 'remote.origin.url'],
+ [GIT_CMD, 'config', 'remote.%s.url' % remote_name],
show_stdout=False, cwd=location)
return url.strip()
@@ -3148,11 +3193,6 @@ class Git(VersionControl):
[GIT_CMD, 'rev-parse', 'HEAD'], show_stdout=False, cwd=location)
return current_rev.strip()
- def get_master_revision(self, location):
- master_rev = call_subprocess(
- [GIT_CMD, 'rev-parse', 'master'], show_stdout=False, cwd=location)
- return master_rev.strip()
-
def get_tag_revs(self, location):
tags = call_subprocess(
[GIT_CMD, 'tag'], show_stdout=False, cwd=location)
@@ -3187,28 +3227,21 @@ class Git(VersionControl):
return None
current_rev = self.get_revision(location)
tag_revs = self.get_tag_revs(location)
- master_rev = self.get_master_revision(location)
branch_revs = self.get_branch_revs(location)
+ remote_name = self.get_remote_name(location)
if current_rev in tag_revs:
- # It's a tag, perfect!
- tag = tag_revs.get(current_rev, current_rev)
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
- elif current_rev in branch_revs:
- # It's the head of a branch, nice too.
- branch = branch_revs.get(current_rev, current_rev)
- return '%s@%s#egg=%s-%s' % (repo, current_rev, dist.egg_name(), current_rev)
- elif current_rev == master_rev:
- if find_tags:
- if current_rev in tag_revs:
- tag = tag_revs.get(current_rev, current_rev)
- logger.notify('Revision %s seems to be equivalent to tag %s' % (current_rev, tag))
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
- return '%s@%s#egg=%s-dev' % (repo, master_rev, dist.egg_name())
+ # It's a tag
+ full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
+ elif (current_rev in branch_revs and
+ branch_revs[current_rev] != '%s/master' % remote_name):
+ # It's the head of a branch
+ full_egg_name = '%s-%s' % (dist.egg_name(),
+ branch_revs[current_rev].replace('%s/' % remote_name, ''))
else:
- # Don't know what it is
- logger.warn('Git URL does not fit normal structure: %s' % repo)
- return '%s@%s#egg=%s-dev' % (repo, current_rev, egg_project_name)
+ full_egg_name = '%s-dev' % dist.egg_name()
+
+ return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
def get_url_rev(self):
"""
@@ -3229,6 +3262,7 @@ vcs.register(Git)
class Mercurial(VersionControl):
name = 'hg'
dirname = '.hg'
+ repo_name = 'clone'
schemes = ('hg', 'hg+http', 'hg+ssh')
bundle_file = 'hg-clone.txt'
guide = ('# This was a Mercurial repo; to make it a repo again run:\n'
@@ -3274,6 +3308,27 @@ class Mercurial(VersionControl):
finally:
shutil.rmtree(temp_dir)
+ def switch(self, dest, url, rev_options):
+ repo_config = os.path.join(dest, self.dirname, 'hgrc')
+ config = ConfigParser.SafeConfigParser()
+ try:
+ config.read(repo_config)
+ config.set('paths', 'default', url)
+ config_file = open(repo_config, 'w')
+ config.write(config_file)
+ config_file.close()
+ except (OSError, ConfigParser.NoSectionError), e:
+ logger.warn(
+ 'Could not switch Mercurial repository to %s: %s'
+ % (url, e))
+ else:
+ call_subprocess(['hg', 'update', '-q'] + rev_options, cwd=dest)
+
+ def update(self, dest, rev_options):
+ call_subprocess(['hg', 'pull', '-q'], cwd=dest)
+ call_subprocess(
+ ['hg', 'update', '-q'] + rev_options, cwd=dest)
+
def obtain(self, dest):
url, rev = self.get_url_rev()
if rev:
@@ -3282,54 +3337,7 @@ class Mercurial(VersionControl):
else:
rev_options = []
rev_display = ''
- clone = True
- if os.path.exists(os.path.join(dest, '.hg')):
- existing_url = self.get_url(dest)
- clone = False
- if existing_url == url:
- logger.info('Clone in %s exists, and has correct URL (%s)'
- % (display_path(dest), url))
- logger.notify('Updating clone %s%s'
- % (display_path(dest), rev_display))
- call_subprocess(['hg', 'pull', '-q'], cwd=dest)
- call_subprocess(
- ['hg', 'update', '-q'] + rev_options, cwd=dest)
- else:
- logger.warn('Mercurial clone in %s exists with URL %s'
- % (display_path(dest), existing_url))
- logger.warn('The plan is to install the Mercurial repository %s'
- % url)
- response = ask('What to do? (s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
- if response == 's':
- logger.notify('Switching clone %s to %s%s'
- % (display_path(dest), url, rev_display))
- repo_config = os.path.join(dest, '.hg/hgrc')
- config = ConfigParser.SafeConfigParser()
- try:
- config_file = open(repo_config, 'wb')
- config.readfp(config_file)
- config.set('paths', ''.join(rev_options), url)
- config.write(config_file)
- except (OSError, ConfigParser.NoSectionError):
- logger.warn(
- 'Could not switch Mercurial repository to %s: %s'
- % (url, e))
- else:
- call_subprocess(
- ['hg', 'update', '-q'] + rev_options, cwd=dest)
- elif response == 'i':
- # do nothing
- pass
- elif response == 'w':
- logger.warn('Deleting %s' % display_path(dest))
- shutil.rmtree(dest)
- clone = True
- elif response == 'b':
- dest_dir = backup_dir(dest)
- logger.warn('Backing up %s to %s' % (display_path(dest), dest_dir))
- shutil.move(dest, dest_dir)
- clone = True
- if clone:
+ if self.check_destination(dest, url, rev_options, rev_display):
logger.notify('Cloning hg %s%s to %s'
% (url, rev_display, display_path(dest)))
call_subprocess(['hg', 'clone', '-q', url, dest])
@@ -3343,11 +3351,6 @@ class Mercurial(VersionControl):
url = filename_to_url(url)
return url.strip()
- def get_tip_revision(self, location):
- current_rev = call_subprocess(
- ['hg', 'tip', '--template={rev}'], show_stdout=False, cwd=location)
- return current_rev.strip()
-
def get_tag_revs(self, location):
tags = call_subprocess(
['hg', 'tags'], show_stdout=False, cwd=location)
@@ -3378,6 +3381,12 @@ class Mercurial(VersionControl):
show_stdout=False, cwd=location).strip()
return current_revision
+ def get_revision_hash(self, location):
+ current_rev_hash = call_subprocess(
+ ['hg', 'parents', '--template={node}'],
+ show_stdout=False, cwd=location).strip()
+ return current_rev_hash
+
def get_src_requirement(self, dist, location, find_tags):
repo = self.get_url(location)
if not repo.lower().startswith('hg:'):
@@ -3386,28 +3395,18 @@ class Mercurial(VersionControl):
if not repo:
return None
current_rev = self.get_revision(location)
+ current_rev_hash = self.get_revision_hash(location)
tag_revs = self.get_tag_revs(location)
branch_revs = self.get_branch_revs(location)
- tip_rev = self.get_tip_revision(location)
if current_rev in tag_revs:
- # It's a tag, perfect!
- tag = tag_revs.get(current_rev, current_rev)
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
+ # It's a tag
+ full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
elif current_rev in branch_revs:
- # It's the tip of a branch, nice too.
- branch = branch_revs.get(current_rev, current_rev)
- return '%s@%s#egg=%s-%s' % (repo, branch, dist.egg_name(), current_rev)
- elif current_rev == tip_rev:
- if find_tags:
- if current_rev in tag_revs:
- tag = tag_revs.get(current_rev, current_rev)
- logger.notify('Revision %s seems to be equivalent to tag %s' % (current_rev, tag))
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
- return '%s@%s#egg=%s-dev' % (repo, tip_rev, dist.egg_name())
+ # It's the tip of a branch
+ full_egg_name = '%s-%s' % (dist.egg_name(), branch_revs[current_rev])
else:
- # Don't know what it is
- logger.warn('Mercurial URL does not fit normal structure: %s' % repo)
- return '%s@%s#egg=%s-dev' % (repo, current_rev, egg_project_name)
+ full_egg_name = '%s-dev' % dist.egg_name()
+ return '%s@%s#egg=%s' % (repo, current_rev_hash, full_egg_name)
vcs.register(Mercurial)
@@ -3415,6 +3414,7 @@ vcs.register(Mercurial)
class Bazaar(VersionControl):
name = 'bzr'
dirname = '.bzr'
+ repo_name = 'branch'
bundle_file = 'bzr-branch.txt'
schemes = ('bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp')
guide = ('# This was a Bazaar branch; to make it a branch again run:\n'
@@ -3460,6 +3460,13 @@ class Bazaar(VersionControl):
finally:
shutil.rmtree(temp_dir)
+ def switch(self, dest, url, rev_options):
+ call_subprocess([BZR_CMD, 'switch', url], cwd=dest)
+
+ def update(self, dest, rev_options):
+ call_subprocess(
+ [BZR_CMD, 'pull', '-q'] + rev_options, cwd=dest)
+
def obtain(self, dest):
url, rev = self.get_url_rev()
if rev:
@@ -3468,48 +3475,11 @@ class Bazaar(VersionControl):
else:
rev_options = []
rev_display = ''
- branch = True
- update = False
- if os.path.exists(os.path.join(dest, '.bzr')):
- existing_url = self.get_url(dest)
- branch = False
- if existing_url == url:
- logger.info('Checkout in %s exists, and has correct URL (%s)'
- % (display_path(dest), url))
- logger.notify('Updating branch %s%s'
- % (display_path(dest), rev_display))
- branch = update = True
- else:
- logger.warn('Bazaar branch in %s exists with URL %s'
- % (display_path(dest), existing_url))
- logger.warn('The plan is to install the Bazaar repository %s'
- % url)
- response = ask('What to do? (s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
- if response == 's':
- logger.notify('Switching branch %s to %s%s'
- % (display_path(dest), url, rev_display))
- call_subprocess([BZR_CMD, 'switch', url], cwd=dest)
- elif response == 'i':
- # do nothing
- pass
- elif response == 'w':
- logger.warn('Deleting %s' % display_path(dest))
- shutil.rmtree(dest)
- branch = True
- elif response == 'b':
- dest_dir = backup_dir(dest)
- logger.warn('Backing up %s to %s' % (display_path(dest), dest_dir))
- shutil.move(dest, dest_dir)
- branch = True
- if branch:
+ if self.check_destination(dest, url, rev_options, rev_display):
logger.notify('Checking out %s%s to %s'
% (url, rev_display, display_path(dest)))
- if update:
- call_subprocess(
- [BZR_CMD, 'pull', '-q'] + rev_options + [url], cwd=dest)
- else:
- call_subprocess(
- [BZR_CMD, 'branch', '-q'] + rev_options + [url, dest])
+ call_subprocess(
+ [BZR_CMD, 'branch', '-q'] + rev_options + [url, dest])
def get_url_rev(self):
# hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it
@@ -3534,12 +3504,6 @@ class Bazaar(VersionControl):
[BZR_CMD, 'revno'], show_stdout=False, cwd=location)
return revision.splitlines()[-1]
- def get_newest_revision(self, location):
- url = self.get_url(location)
- revision = call_subprocess(
- [BZR_CMD, 'revno', url], show_stdout=False, cwd=location)
- return revision.splitlines()[-1]
-
def get_tag_revs(self, location):
tags = call_subprocess(
[BZR_CMD, 'tags'], show_stdout=False, cwd=location)
@@ -3561,22 +3525,14 @@ class Bazaar(VersionControl):
return None
current_rev = self.get_revision(location)
tag_revs = self.get_tag_revs(location)
- newest_rev = self.get_newest_revision(location)
+
if current_rev in tag_revs:
- # It's a tag, perfect!
+ # It's a tag
tag = tag_revs.get(current_rev, current_rev)
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
- elif current_rev == newest_rev:
- if find_tags:
- if current_rev in tag_revs:
- tag = tag_revs.get(current_rev, current_rev)
- logger.notify('Revision %s seems to be equivalent to tag %s' % (current_rev, tag))
- return '%s@%s#egg=%s-%s' % (repo, tag, egg_project_name, tag)
- return '%s@%s#egg=%s-dev' % (repo, newest_rev, dist.egg_name())
+ full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
else:
- # Don't know what it is
- logger.warn('Bazaar URL does not fit normal structure: %s' % repo)
- return '%s@%s#egg=%s-dev' % (repo, current_rev, egg_project_name)
+ full_egg_name = '%s-dev_r%s' % (dist.egg_name(), current_rev)
+ return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
vcs.register(Bazaar)
diff --git a/tests/test_basic.txt b/tests/test_basic.txt
index 6d81d5310..c05bb49e8 100644
--- a/tests/test_basic.txt
+++ b/tests/test_basic.txt
@@ -64,10 +64,15 @@ Cloning from Mercurial::
>>> assert 'src/django-registration' in result.files_created
>>> assert 'src/django-registration/.hg' in result.files_created
+Presence or absence of final slash is also normalized::
+
+ >>> result = run_pip('install', '-e', 'hg+http://bitbucket.org/ubernostrum/django-registration#egg=django-registration', expect_error=True)
+ >>> assert 'pip-log.txt' not in result.files_created, result.files_created['pip-log.txt'].bytes
+
Checking out from Bazaar::
>>> reset_env()
- >>> result = run_pip('install', '-e', 'bzr+http://bazaar.launchpad.net/%7Ejezdez/pip-test/test/#egg=pip-test', expect_error=True)
+ >>> result = run_pip('install', '-e', 'bzr+http://bazaar.launchpad.net/%7Ejezdez/pip-test/test/@1#egg=pip-test', expect_error=True)
>>> egg_link = result.files_created[lib_py + 'site-packages/pip-test.egg-link']
>>> # FIXME: I don't understand why there's a trailing . here:
>>> egg_link.bytes
@@ -75,3 +80,9 @@ Checking out from Bazaar::
>>> assert (lib_py + 'site-packages/easy-install.pth') in result.files_updated
>>> assert 'src/pip-test' in result.files_created
>>> assert 'src/pip-test/.bzr' in result.files_created
+
+Urlquoted characters are normalized for repo URL comparison::
+
+ >>> result = run_pip('install', '-e', 'bzr+http://bazaar.launchpad.net/~jezdez/pip-test/test#egg=pip-test', expect_error=True)
+ >>> assert 'pip-log.txt' not in result.files_created, result.files_created['pip-log.txt'].bytes
+
diff --git a/tests/test_freeze.txt b/tests/test_freeze.txt
index 22beb815e..61c7425fa 100644
--- a/tests/test_freeze.txt
+++ b/tests/test_freeze.txt
@@ -34,7 +34,7 @@ Now lets try it with an svn checkout::
>>> print result
Script result: ...ython... ../../pip.py -E .../test-scratch freeze
-- stdout: --------------------
- -e svn+http://svn.colorstudy.com/INITools/trunk@3472#egg=INITools-0.2.1dev_r3472-py2...-dev
+ -e svn+http://svn.colorstudy.com/INITools/trunk@3472#egg=INITools-0.2.1dev_r3472-py2...-dev_r3472
simplejson==1.7.4...
<BLANKLINE>
@@ -77,23 +77,17 @@ What about a Git clone?::
>>> result = run_pip('freeze', expect_stderr=True)
>>> print result
Script result: ...ython... ../../pip.py -E .../test-scratch freeze
- -- stderr: --------------------
- Git URL does not fit normal structure: git://github.com/jezdez/django-pagination.git
- <BLANKLINE>
-- stdout: --------------------
-e git://github.com/jezdez/django-pagination.git@...#egg=django_pagination-...
...
<BLANKLINE>
- >>> result = run_pip('freeze', '-f', 'git://github.com/jezdez/django-pagination.git#egg=django_pagination-dev', expect_stderr=True)
+ >>> result = run_pip('freeze', '-f', 'git://github.com/jezdez/django-pagination.git#egg=django_pagination', expect_stderr=True)
>>> print result
- Script result: ...ython... ../../pip.py -E .../test-scratch freeze -f git://github.com/jezdez/django-pagination.git#egg=django_pagination-dev
- -- stderr: --------------------
- Git URL does not fit normal structure: git://github.com/jezdez/django-pagination.git
- <BLANKLINE>
+ Script result: ...ython... ../../pip.py -E .../test-scratch freeze -f git://github.com/jezdez/django-pagination.git#egg=django_pagination
-- stdout: --------------------
- -f git://github.com/jezdez/django-pagination.git#egg=django_pagination-dev
- -e git://github.com/jezdez/django-pagination.git@...#egg=django_pagination-dev
+ -f git://github.com/jezdez/django-pagination.git#egg=django_pagination
+ -e git://github.com/jezdez/django-pagination.git@...#egg=django_pagination-...-dev
...
<BLANKLINE>