diff --git a/dist-git-client/dist_git_client.py b/dist-git-client/dist_git_client.py index bcfb7ca..d9beda9 100644 --- a/dist-git-client/dist_git_client.py +++ b/dist-git-client/dist_git_client.py @@ -3,6 +3,7 @@ """ import argparse +from collections import namedtuple import configparser import errno import glob @@ -169,6 +170,28 @@ def _detect_clone_url(): return git_conf_reader['remote "origin"']["url"] +def parse_clone_url(url): + """ + Given Git clone url, return a named tuple with "hostname" and "path" + parameters. + """ + Parsed = namedtuple('_ParsedUrl', ['hostname', 'path']) + + autoparsed = urlparse(url) + if autoparsed.scheme: + hostname = autoparsed.hostname or "localhost" + return Parsed(hostname, autoparsed.path) + + if ':' in url and '@' in url: + # user@hostname:/path format + no_user = url.split("@", 1)[1] + host, path = no_user.split(":", 1) + return Parsed(host, path) + + # local pathname, like /home/tester/test.git + return Parsed("localhost", url) + + def get_distgit_config(config, forked_from=None): """ Given the '.git/config' file from current directory, return the @@ -178,13 +201,18 @@ def get_distgit_config(config, forked_from=None): url = forked_from if not url: url = _detect_clone_url() - parsed_url = urlparse(url) + parsed_url = parse_clone_url(url) if parsed_url.hostname is None: hostname = "localhost" else: hostname = parsed_url.hostname - prefixes = config["clone_host_map"][hostname] + try: + prefixes = config["clone_host_map"][hostname] + except KeyError as err: + raise RuntimeError(f"{hostname} (detected from clone URL) not " + "found in dist-git-client configuration") from err + prefix_found = None for prefix in prefixes.keys(): if not parsed_url.path.startswith(prefix): diff --git a/dist-git-client/tests/test_url_parser.py b/dist-git-client/tests/test_url_parser.py new file mode 100644 index 0000000..54f4af6 --- /dev/null +++ b/dist-git-client/tests/test_url_parser.py @@ -0,0 +1,29 @@ +""" test clone url parser """ + +from dist_git_client import parse_clone_url + + +def _checker(url, hostname, path): + parsed = parse_clone_url(url) + assert parsed.hostname == hostname + assert parsed.path == path + + +def test_parse_clone_urls(): + """ Basic clone url formats """ + _checker("git@github.com:example/example-project.git", + "github.com", "example/example-project.git") + _checker("https://github.com/example/example-project.git", + "github.com", "/example/example-project.git") + _checker("https://github.com/example/example-project", + "github.com", "/example/example-project") + _checker("ssh://jdoe@pkgs.fedoraproject.org/rpms/example.git", + "pkgs.fedoraproject.org", "/rpms/example.git") + _checker("https://copr-dist-git.fedorainfracloud.org/git" + "/@abrt/retrace-server-devel/retrace-server.git", + "copr-dist-git.fedorainfracloud.org", + "/git/@abrt/retrace-server-devel/retrace-server.git") + _checker("file:///home/foo.git", + "localhost", "/home/foo.git") + _checker("/home/foo.git", + "localhost", "/home/foo.git")