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

Re-implement Git version parsing with regex #10117

Merged
merged 1 commit into from Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions news/10117.removal.rst
@@ -0,0 +1,2 @@
Git version parsing is now done with regular expression to prepare for the
pending upstream removal of non-PEP-440 version parsing logic.
30 changes: 14 additions & 16 deletions src/pip/_internal/vcs/git.py
Expand Up @@ -6,9 +6,6 @@
import urllib.request
from typing import List, Optional, Tuple

from pip._vendor.packaging.version import _BaseVersion
from pip._vendor.packaging.version import parse as parse_version

from pip._internal.exceptions import BadCommand, InstallationError
from pip._internal.utils.misc import HiddenText, display_path, hide_url
from pip._internal.utils.subprocess import make_command
Expand All @@ -29,6 +26,14 @@
logger = logging.getLogger(__name__)


GIT_VERSION_REGEX = re.compile(
r"^git version " # Prefix.
r"(\d+)" # Major.
r"\.(\d+)" # Dot, minor.
r"(?:\.(\d+))?" # Optional dot, patch.
r".*$" # Suffix, including any pre- and post-release segments we don't care about.
)

HASH_REGEX = re.compile('^[a-fA-F0-9]{40}$')

# SCP (Secure copy protocol) shorthand. e.g. 'git@example.com:foo/bar.git'
Expand Down Expand Up @@ -83,21 +88,14 @@ def is_immutable_rev_checkout(self, url, dest):
)
return not is_tag_or_branch

def get_git_version(self):
# type: () -> _BaseVersion
VERSION_PFX = 'git version '
def get_git_version(self) -> Tuple[int, ...]:
version = self.run_command(
['version'], show_stdout=False, stdout_only=True
)
if version.startswith(VERSION_PFX):
version = version[len(VERSION_PFX):].split()[0]
else:
version = ''
# get first 3 positions of the git version because
# on windows it is x.y.z.windows.t, and this parses as
# LegacyVersion which always smaller than a Version.
version = '.'.join(version.split('.')[:3])
return parse_version(version)
match = GIT_VERSION_REGEX.match(version)
if not match:
pradyunsg marked this conversation as resolved.
Show resolved Hide resolved
return ()
return tuple(int(c) for c in match.groups())

@classmethod
def get_current_branch(cls, location):
Expand Down Expand Up @@ -301,7 +299,7 @@ def switch(self, dest, url, rev_options):
def update(self, dest, url, rev_options):
# type: (str, HiddenText, RevOptions) -> None
# First fetch changes from the default remote
if self.get_git_version() >= parse_version('1.9.0'):
if self.get_git_version() >= (1, 9):
# fetch tags in addition to everything else
self.run_command(['fetch', '-q', '--tags'], cwd=dest)
else:
Expand Down
3 changes: 1 addition & 2 deletions tests/unit/test_vcs.py
Expand Up @@ -4,7 +4,6 @@
from unittest.mock import patch

import pytest
from pip._vendor.packaging.version import parse as parse_version

from pip._internal.exceptions import BadCommand, InstallationError
from pip._internal.utils.misc import hide_url, hide_value
Expand Down Expand Up @@ -483,7 +482,7 @@ def test_subversion__get_url_rev_options():

def test_get_git_version():
git_version = Git().get_git_version()
assert git_version >= parse_version('1.0.0')
assert git_version >= (1, 0, 0)


@pytest.mark.parametrize('use_interactive,is_atty,expected', [
Expand Down