Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compare revisions for remote git branches/tags #4386

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions news/4386.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Adds a simple check if the local revision is the same as the remote revision, even if the ref is a tag or branch name.

Until now branches or tags would always try to update the repository.
4 changes: 2 additions & 2 deletions pip/vcs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def update(self, dest, rev_options):
"""
raise NotImplementedError

def check_version(self, dest, rev_options):
def check_version(self, dest, rev_options, url=None):
"""
Return True if the version is identical to what exists and
doesn't need to be updated.
Expand All @@ -211,7 +211,7 @@ def check_destination(self, dest, url, rev_options, rev_display):
display_path(dest),
url,
)
if not self.check_version(dest, rev_options):
if not self.check_version(dest, rev_options, url=url):
logger.info(
'Updating %s %s%s',
display_path(dest),
Expand Down
2 changes: 1 addition & 1 deletion pip/vcs/bazaar.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def get_src_requirement(self, dist, location):
current_rev = self.get_revision(location)
return '%s@%s#egg=%s' % (repo, current_rev, egg_project_name)

def check_version(self, dest, rev_options):
def check_version(self, dest, rev_options, url=None):
"""Always assume the versions don't match"""
return False

Expand Down
24 changes: 19 additions & 5 deletions pip/vcs/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,22 @@ def check_rev_options(self, rev, dest, rev_options):
)
return rev_options

def check_version(self, dest, rev_options):
def check_version(self, dest, rev_options, url=None):
"""
Compare the current sha to the ref. ref may be a branch or tag name,
but current rev will always point to a sha. This means that a branch
or tag will never compare as True. So this ultimately only matches
against exact shas.
but current rev will always point to a sha.
This means that if ref is a branch or tag name,
we will fetch the ref's sha using ls-remote
"""
return self.get_revision(dest).startswith(rev_options[0])

local_revision = self.get_revision(dest)

if url is not None:
remote_revision = self._get_remote_revision(url, rev_options[0])
else:
remote_revision = rev_options[0]

return local_revision.startswith(remote_revision)

def switch(self, dest, url, rev_options):
self.run_command(['config', 'remote.origin.url', url], cwd=dest)
Expand Down Expand Up @@ -171,6 +179,12 @@ def get_revision(self, location):
['rev-parse', 'HEAD'], show_stdout=False, cwd=location)
return current_rev.strip()

def _get_remote_revision(self, url, ref):
remote_rev = self.run_command(
['ls-remote', url, ref], show_stdout=False)

return remote_rev.split()[0].strip()

def get_full_refs(self, location):
"""Yields tuples of (commit, ref) for branches and tags"""
output = self.run_command(['show-ref'],
Expand Down
2 changes: 1 addition & 1 deletion pip/vcs/mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def get_src_requirement(self, dist, location):
current_rev_hash = self.get_revision_hash(location)
return '%s@%s#egg=%s' % (repo, current_rev_hash, egg_project_name)

def check_version(self, dest, rev_options):
def check_version(self, dest, rev_options, url=None):
"""Always assume the versions don't match"""
return False

Expand Down
2 changes: 1 addition & 1 deletion pip/vcs/subversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def get_src_requirement(self, dist, location):
rev = self.get_revision(location)
return 'svn+%s@%s#egg=%s' % (repo, rev, egg_project_name)

def check_version(self, dest, rev_options):
def check_version(self, dest, rev_options, url=None):
"""Always assume the versions don't match"""
return False

Expand Down
10 changes: 10 additions & 0 deletions tests/functional/test_install_vcs_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ def test_check_version(script):
assert not git.check_version(version_pkg_path, ['branch0.1'])
assert not git.check_version(version_pkg_path, ['abc123'])

# Make sure check_version compares remote urls correctly
assert git.check_version(version_pkg_path, ['master'], url='file://%s' % version_pkg_path)

script.run(
'git', 'commit', '--allow-empty', '-m ""',
cwd=version_pkg_path
)

assert not git.check_version(version_pkg_path, ['branch0.1'], url='file://%s' % version_pkg_path)


@patch('pip.vcs.git.Git.get_short_refs')
def test_check_rev_options_should_handle_branch_name(get_refs_mock):
Expand Down