From 690ecf9c6672c20310d04a55538c5bd67227237f Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Fri, 8 Nov 2019 18:16:34 +0300 Subject: [PATCH] Add support for ip git repo urls (#827) * Add support for ip v4 git repo urls * Add tests for git urls --- .travis.yml | 2 +- .vscode/launch.json | 2 +- CHANGELOG.md | 1 + cvat/apps/git/git.py | 17 +++++++++----- cvat/apps/git/tests.py | 52 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index c75681e0da6b..f600822d28d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,5 +12,5 @@ before_script: - docker-compose -f docker-compose.yml -f docker-compose.ci.yml up --build -d script: - - docker exec -it cvat /bin/bash -c 'python3 manage.py test cvat/apps/engine utils/cli' + - docker exec -it cvat /bin/bash -c 'python3 manage.py test cvat/apps utils/cli' - docker exec -it cvat /bin/bash -c 'cd cvat-core && npm install && npm run test && npm run coveralls' diff --git a/.vscode/launch.json b/.vscode/launch.json index 069fe74d5891..de8015b16b89 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -134,7 +134,7 @@ "test", "--settings", "cvat.settings.testing", - "cvat/apps/engine", + "cvat/apps", "utils/cli" ], "django": true, diff --git a/CHANGELOG.md b/CHANGELOG.md index cfcfb7c53e6f..9d13010ccc65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ https://github.com/opencv/cvat/issues/750). ### Fixed - [Mask problem on coco json style](https://github.com/opencv/cvat/issues/718) +- [Exception in Git plugin](https://github.com/opencv/cvat/issues/826) ### Security - diff --git a/cvat/apps/git/git.py b/cvat/apps/git/git.py index b9ef5136f953..5edb721421fa 100644 --- a/cvat/apps/git/git.py +++ b/cvat/apps/git/git.py @@ -76,8 +76,13 @@ def __init__(self, db_git, tid, user): # HTTP/HTTPS: [http://]github.com/proj/repos[.git] def _parse_url(self): try: - http_pattern = "([https|http]+)*[://]*([a-zA-Z0-9._-]+.[a-zA-Z]+)/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)" - ssh_pattern = "([a-zA-Z0-9._-]+)@([a-zA-Z0-9._-]+):([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)" + # Almost STD66 (RFC3986), but schema can include a leading digit + # Reference on URL formats accepted by Git: + # https://github.com/git/git/blob/77bd3ea9f54f1584147b594abc04c26ca516d987/url.c + + host_pattern = r"((?:(?:(?:\d{1,3}\.){3}\d{1,3})|(?:[a-zA-Z0-9._-]+.[a-zA-Z]+))(?::\d+)?)" + http_pattern = r"(?:http[s]?://)?" + host_pattern + r"((?:/[a-zA-Z0-9._-]+){2})" + ssh_pattern = r"([a-zA-Z0-9._-]+)@" + host_pattern + r":([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)" http_match = re.match(http_pattern, self._url) ssh_match = re.match(ssh_pattern, self._url) @@ -87,21 +92,21 @@ def _parse_url(self): repos = None if http_match: - host = http_match.group(2) - repos = "{}/{}".format(http_match.group(3), http_match.group(4)) + host = http_match.group(1) + repos = http_match.group(2)[1:] elif ssh_match: user = ssh_match.group(1) host = ssh_match.group(2) repos = "{}/{}".format(ssh_match.group(3), ssh_match.group(4)) else: - raise Exception("Got URL doesn't sutisfy for regular expression") + raise Exception("Git repository URL does not satisfy pattern") if not repos.endswith(".git"): repos += ".git" return user, host, repos except Exception as ex: - slogger.glob.exception('URL parsing errors occured', exc_info = True) + slogger.glob.exception('URL parsing errors occurred', exc_info = True) raise ex diff --git a/cvat/apps/git/tests.py b/cvat/apps/git/tests.py index 3517aa28fb20..5d4d2c116fd3 100644 --- a/cvat/apps/git/tests.py +++ b/cvat/apps/git/tests.py @@ -2,6 +2,58 @@ # # SPDX-License-Identifier: MIT +from itertools import product + from django.test import TestCase # Create your tests here. + +from cvat.apps.git.git import Git + + +class GitUrlTest(TestCase): + class FakeGit: + def __init__(self, url): + self._url = url + + def _check_correct_urls(self, samples): + for i, (expected, url) in enumerate(samples): + git = GitUrlTest.FakeGit(url) + try: + actual = Git._parse_url(git) + self.assertEqual(expected, actual, "URL #%s: '%s'" % (i, url)) + except Exception: + self.assertFalse(True, "URL #%s: '%s'" % (i, url)) + + def test_correct_urls_can_be_parsed(self): + hosts = ['host.zone', '1.2.3.4'] + ports = ['', ':42'] + repo_groups = ['repo', 'r4p0'] + repo_repos = ['nkjl23', 'hewj'] + git_suffixes = ['', '.git'] + + samples = [] + + # http samples + protocols = ['', 'http://', 'https://'] + for protocol, host, port, repo_group, repo, git in product( + protocols, hosts, ports, repo_groups, repo_repos, git_suffixes): + url = '{protocol}{host}{port}/{repo_group}/{repo}{git}'.format( + protocol=protocol, host=host, port=port, + repo_group=repo_group, repo=repo, git=git + ) + expected = ('git', host + port, '%s/%s.git' % (repo_group, repo)) + samples.append((expected, url)) + + # git samples + users = ['user', 'u123_.'] + for user, host, port, repo_group, repo, git in product( + users, hosts, ports, repo_groups, repo_repos, git_suffixes): + url = '{user}@{host}{port}:{repo_group}/{repo}{git}'.format( + user=user, host=host, port=port, + repo_group=repo_group, repo=repo, git=git + ) + expected = (user, host + port, '%s/%s.git' % (repo_group, repo)) + samples.append((expected, url)) + + self._check_correct_urls(samples) \ No newline at end of file