diff --git a/src/packageurl/contrib/purl2url.py b/src/packageurl/contrib/purl2url.py index 5806251..9e46f02 100644 --- a/src/packageurl/contrib/purl2url.py +++ b/src/packageurl/contrib/purl2url.py @@ -24,6 +24,8 @@ # Visit https://github.com/package-url/packageurl-python for support and # download. +import re + from packageurl import PackageURL from packageurl.contrib.route import NoRouteAvailable from packageurl.contrib.route import Router @@ -51,6 +53,8 @@ def get_repo_download_url_by_package_type( repo_router = Router() download_router = Router() +commit_router = Router() +patch_router = Router() def _get_url_from_router(router, purl): @@ -68,6 +72,30 @@ def get_repo_url(purl): return _get_url_from_router(repo_router, purl) +def get_commit_url(purl): + """ + Return a Commit URL inferred from the `purl` string. + """ + commit_url = _get_url_from_router(commit_router, purl) + if commit_url: + return commit_url + + purl_data = PackageURL.from_string(purl) + return purl_data.qualifiers.get("commit_url", None) + + +def get_patch_url(purl): + """ + Return a Patch URL inferred from the `purl` string. + """ + patch_url = _get_url_from_router(patch_router, purl) + if patch_url: + return patch_url + + purl_data = PackageURL.from_string(purl) + return purl_data.qualifiers.get("patch_url", None) + + def get_download_url(purl): """ Return a download URL inferred from the `purl` string. @@ -158,18 +186,203 @@ def build_github_repo_url(purl): return repo_url +SUB_GITLAB_DOMAINS = [r"^git\.codelinaro\.org", r"^salsa\.debian\.org", r"^gitlab\.(?!com\b)[^/]+"] + + @repo_router.route("pkg:gitlab/.*") def build_gitlab_repo_url(purl): """ Return a gitlab repo URL from the `purl` string. """ purl_data = PackageURL.from_string(purl) + namespace = purl_data.namespace + name = purl_data.name + qualifiers = purl_data.qualifiers + repository_url = qualifiers.get("repository_url") + if not (namespace and name): + return + if repository_url: + clean_url = re.sub(r"^https?://", "", repository_url) + for pattern in SUB_GITLAB_DOMAINS: + if re.match(pattern, clean_url): + return f"https://{namespace}/{name}" + + return f"https://gitlab.com/{namespace}/{name}" + + +GIT_REPO_GENERIC = { + # cgit + ( + r"git\.kernel\.org", + r"gitweb\.gentoo\.org", + "cgit\.git\.savannah\.gnu\.org", + "web\.git\.kernel\.org", + ): { + "repo_url": "https://{namespace}/{name}.git", + "commit_url": "https://{namespace}/{name}.git/commit/?id={version}", + "patch_url": "https://{namespace}/{name}.git/patch/?id={version}", + }, + # gitiles + ( + r"android\.googlesource\.com", + r"aomedia\.googlesource\.com", + r"chromium\.googlesource\.com", + r"gerrit\.googlesource\.com", + ): { + "repo_url": "https://{namespace}/{name}", + "commit_url": "https://{namespace}/{name}/+/{version}", + "patch_url": "https://{namespace}/{name}/+/{version}^!?format=TEXT", # base64 encoded + }, + # allura + (r"sourceforge\.net", r"forge-allura\.apache\.org"): { + "repo_url": "https://{namespace}/{name}", + "commit_url": "https://{namespace}/{name}/ci/{version}", + "patch_url": None, # Can't find a direct patch URL + }, + # gitweb + ( + r"gcc\.gnu\.org/git", + r"git\.postgresql\.org", + "sourceware\.org", + "git\.openssl\.org", + "gitbox\.apache\.org", + ): { + "commit_url": "https://{namespace}/?p={name}.git;a=commit;h={version}", + "repo_url": "https://{namespace}/?p={name}.git", + "patch_url": "https://{namespace}/?p={name}.git;a=patch;h={version}", + }, + # gitea / forgejo + ( + r"codeberg\.org", + r"gitea\.com", + r"forge\.fedoraproject\.org", + ): { + "commit_url": "https://{namespace}/{name}/commit/{version}", + "repo_url": "https://{namespace}/{name}", + "patch_url": "https://{namespace}/{name}/commit/{version}.patch", + }, +} + + +@repo_router.route("pkg:generic/.*") +def build_generic_repo_url(purl): + """ + Return a Repo URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) + name = purl_data.name namespace = purl_data.namespace + + if not (namespace and name): + return + + for patterns, template_url in GIT_REPO_GENERIC.items(): + for pattern in patterns: + if not re.match(pattern, namespace): + continue + + return template_url["repo_url"].format(namespace=namespace, name=name) + return + + +@commit_router.route("pkg:generic/.*") +def build_generic_commit_url(purl): + """ + Return a Commit URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) name = purl_data.name + namespace = purl_data.namespace + version = purl_data.version - if name and namespace: - return f"https://gitlab.com/{namespace}/{name}" + if not (namespace and name and version): + return + + for patterns, template_url in GIT_REPO_GENERIC.items(): + for pattern in patterns: + if not re.match(pattern, namespace): + continue + + return template_url["commit_url"].format( + namespace=namespace, name=name, version=version + ) + + +@patch_router.route("pkg:generic/.*") +def build_generic_patch_url(purl): + """ + Return a Patch URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) + name = purl_data.name + namespace = purl_data.namespace + version = purl_data.version + + if not (namespace and name and version): + return + + for patterns, template_url in GIT_REPO_GENERIC.items(): + for pattern in patterns: + if not re.match(pattern, namespace): + continue + + patch_template = template_url.get("patch_url") + if patch_template: + return patch_template.format(namespace=namespace, name=name, version=version) + + +@commit_router.route("pkg:gitlab/.*", "pkg:bitbucket/.*", "pkg:github/.*") +def build_main_commit_url(purl): + """ + Return a github/gitlab/bitbucket Commit URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) + purl_type = purl_data.type + name = purl_data.name + namespace = purl_data.namespace + version = purl_data.version + if not (namespace and name and version): + return + + commit_url_template = { + "github": f"https://github.com/{namespace}/{name}/commit/{version}", + "gitlab": f"https://gitlab.com/{namespace}/{name}/-/commit/{version}", + "sub-gitlab": f"https://{namespace}/{name}/-/commit/{version}", + "bitbucket": f"https://bitbucket.org/{namespace}/{name}/commits/{version}", + } + + if purl_type == "gitlab" and purl_data.qualifiers.get("repository_url"): + purl_type = "sub-gitlab" + + return commit_url_template[purl_type].format(namespace=namespace, name=name, version=version) + + +@patch_router.route("pkg:gitlab/.*", "pkg:bitbucket/.*", "pkg:github/.*") +def build_main_patch_url(purl): + """ + Return a github/gitlab/bitbucket Patch URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) + purl_type = purl_data.type + name = purl_data.name + namespace = purl_data.namespace + version = purl_data.version + + if not (namespace and name and version): + return + + patch_url_templates = { + "github": f"https://github.com/{namespace}/{name}/commit/{version}.patch", + "gitlab": f"https://gitlab.com/{namespace}/{name}/-/commit/{version}.patch", + "sub-gitlab": f"https://{namespace}/{name}/-/commit/{version}.patch", + "bitbucket": f"https://bitbucket.org/{namespace}/{name}/commits/{version}/raw", + } + + if purl_type == "gitlab" and purl_data.qualifiers.get("repository_url"): + purl_type = "sub-gitlab" + + return patch_url_templates[purl_type].format(namespace=namespace, name=name, version=version) @repo_router.route("pkg:(gem|rubygems)/.*") diff --git a/src/packageurl/contrib/url2purl.py b/src/packageurl/contrib/url2purl.py index 2353b0b..2630ace 100644 --- a/src/packageurl/contrib/url2purl.py +++ b/src/packageurl/contrib/url2purl.py @@ -667,6 +667,281 @@ def build_bitbucket_purl(url): ) +def build_route_regex(domain_patterns, path_suffix="/.*"): + """ + Build a route regex from a list of domains + """ + domain_pattern = "|".join(domain_patterns) + return rf"https?://({domain_pattern}){path_suffix}" + + +SUB_GITLAB_DOMAINS = [r"git\.codelinaro\.org", r"salsa\.debian\.org", r"gitlab\.(?!com\b)[^/]+"] +SUB_GITLAB_ROUTE_REGEX = build_route_regex(SUB_GITLAB_DOMAINS) + + +@purl_router.route(SUB_GITLAB_ROUTE_REGEX) +def build_gitlab_sub_purl(url): + """ + Return a PackageURL object from a GitLab Sub domains commit URL + For example: + https://gitlab.gnome.org/GNOME/gimp + https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm + https://gitlab.eclipse.org/eclipse/asciidoc-lang/asciidoc-lang + https://gitlab.gnome.org/GNOME/gimp/-/commit/112a5e038f0646eae5ae314988ec074433d2b365 + https://git.codelinaro.org/linaro/qcom/project/-/commit/a40a9732c840e5a324fba78b0ff7980b497c3831 + """ + archive_pattern = ( + r"^https?://" r"(?P[^/]+)/" r".+?/-/archive/[^/]+/" r"(?P[^/]+)$" + ) + + commit_pattern = ( + r"^https?://" + r"(?P.+?)/" + r"(?P[^/]+)" + r"(?:/-/commit/(?P[0-9a-fA-F]{7,64}))?" + r"/?$" + ) + + archive_match = re.search(archive_pattern, url) + if archive_match: + namespace = archive_match.group("namespace") + name = archive_match.group("name") + return PackageURL( + type="gitlab", namespace=namespace, name=name, qualifiers={"download_url": url} + ) + + commit_match = re.search(commit_pattern, url) + if commit_match: + namespace = commit_match.group("namespace") + name = commit_match.group("name") + version = commit_match.group("version") + + return PackageURL( + type="gitlab", + namespace=namespace, + name=name, + version=version, + qualifiers={"repository_url": f"https://{namespace}/{name}"}, + ) + + +GITEA_DOMAINS = [r"codeberg\.org", r"gitea\.com", r"forge\.fedoraproject\.org"] +GITEA_ROUTE_REGEX = build_route_regex(GITEA_DOMAINS) + + +@purl_router.route(GITEA_ROUTE_REGEX) +def build_gitea_purl(url): + """ + Return a PackageURL object from a gitea/forgejo url + For example: + https://gitea.com/htc47/entur + https://codeberg.org/alpinelinux/aports + https://codeberg.org/alpinelinux/aports/commit/a40a9732c840e5a324fba78b0ff7980b497c3831 + https://gitea.com/htc47/entur/commit/271b852cfb761a1fe257aa0f0a12ff38bd8bfd1c + """ + gitea_commit_pattern = ( + r"^https?://" + r"(?P.+?)/" + r"(?P[^/]+)" + r"(?:/commit/(?P[0-9a-fA-F]{7,64}))?" + r"/?$" + ) + + commit_match = re.search(gitea_commit_pattern, url) + if commit_match: + return PackageURL( + type="generic", + namespace=commit_match.group("namespace"), + name=commit_match.group("name"), + version=commit_match.group("version"), + ) + + +CGIT_DOMAINS = [ + r"git\.kernel\.org", + r"gitweb\.gentoo\.org", + "cgit\.git\.savannah\.gnu\.org", + "web\.git\.kernel\.org", +] +CGIT_ROUTE_REGEX = build_route_regex(CGIT_DOMAINS) + + +@purl_router.route(CGIT_ROUTE_REGEX) +def build_cgit_purl(url): + """ + Return a PackageURL object from a cgit url + For example: + https://git.kernel.org/pub/scm/utils/b4/b4.git + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + https://cgit.git.savannah.gnu.org/cgit/uddf.git + https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git + https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git + https://gitweb.gentoo.org/dev/darkside.git + https://gitweb.gentoo.org/repo/gentoo.git + https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=74770b1fd2be612f9c2cf807db81fcdcc35e6560 + https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git/commit/?h=for-next&id=bd771cf5c4254511cc4abb88f3dab3bd58bdf8e8 + https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/fs/smb?id=db363b0a1d9e6b9dc556296f1b1007aeb496a8cf + https://cgit.git.savannah.gnu.org/cgit/uddf.git/commit/?id=98c41e131dc952aee43d4ec392b80ca4c426be8d + https://gitweb.gentoo.org/dev/darkside.git/commit/?id=8d4b0836f3b6ab7075212926d9aad0b50246d825 + https://git.kernel.org/stable/c/9a9a8fe26751334b7739193a94eba741073b8a55 + """ + + # https://git.kernel.org/stable/c/ + kernel_shorthand = r"^https?://git\.kernel\.org/stable/c/(?P[0-9a-fA-F]{7,64})/?$" + + cgit_project_pattern = ( + r"^https?://" + r"(?P.+?)/" + r"(?P[^/]+?)" + r"(?:\.git)?" + r"(?:/commit/(?:[^?]+)?\?.*?\bid=(?P[0-9a-fA-F]{7,64})(?:&.*)?)?" + r"/?$" + ) + + if match := re.search(kernel_shorthand, url): + res = match.groupdict() + namespace = "git.kernel.org/pub/scm/linux/kernel/git/stable/" + name = "linux" + elif match := re.search(cgit_project_pattern, url): + res = match.groupdict() + name = res["name"] + namespace = res["namespace"] + else: + return None + + return PackageURL( + type="generic", + namespace=namespace, + name=name, + version=res["version"], + qualifiers={}, + subpath="", + ) + + +GITILES_DOMAINS = [ + r"android\.googlesource\.com", + r"aomedia\.googlesource\.com", + r"chromium\.googlesource\.com", + r"gerrit\.googlesource\.com", +] +GITILES_ROUTE_REGEX = build_route_regex(GITILES_DOMAINS) + + +@purl_router.route(GITILES_ROUTE_REGEX) +def build_gitiles_purl(url): + """ + Return a PackageURL object from Gitiles url + For example: + https://android.googlesource.com/platform/frameworks/base + https://android.googlesource.com/device/generic/vulkan-cereal + https://android.googlesource.com/platform/packages/apps/Settings/+/2968ccc911956fa5813a9a6a5e5c8970e383a60f + https://aomedia.googlesource.com/libavifinfo/+/43716e9c34d3389b4882fbd1a81c04543ed04fe3 + """ + + gitiles_project_pattern = ( + r"^https?://" + r"(?P(?:(?!/\+/).)+)/" + r"(?P[^/]+)" + r"(?:/\+/(?P[0-9a-fA-F]{7,64}))?" + r"/?$" + ) + + match = re.search(gitiles_project_pattern, url) + if match: + return PackageURL( + type="generic", + namespace=match.group("namespace"), + name=match.group("name"), + version=match.group("version"), + qualifiers={}, + subpath="", + ) + + +ALLURA_DOMAINS = [r"sourceforge\.net", r"forge-allura\.apache\.org"] +ALLURA_ROUTE_REGEX = build_route_regex(ALLURA_DOMAINS, "/p/.*") + + +@purl_router.route(ALLURA_ROUTE_REGEX) +def build_allura_purl(url): + """ + Return a PackageURL object from an Apache Allura url (e.g., SourceForge). + For example: + https://sourceforge.net/p/djvu/djvulibre-git + https://sourceforge.net/p/expat/code_git + https://forge-allura.apache.org/p/allura/git + https://sourceforge.net/p/djvu/djvulibre-git/ci/e15d51510048927f172f1bf1f27ede65907d940d + https://sourceforge.net/p/infrarecorder/code/ci/9361b6f267e7b1c1576c48f6dac6dec18d8a93e0/ + https://forge-allura.apache.org/p/allura/git/ci/674e070e5ca7db7c75cf61d8efd2a3e3e49bd946/ + """ + + allura_pattern = ( + r"^https?://" + r"(?P.+?)/" + r"(?P[^/]+?)" + r"(?:/ci/(?P[0-9a-fA-F]{7,64}))?" + r"/?$" + ) + + commit_match = re.search(allura_pattern, url) + if commit_match: + return PackageURL( + type="generic", + namespace=commit_match.group("namespace"), + name=commit_match.group("name"), + version=commit_match.group("version"), + qualifiers={}, + subpath="", + ) + + +GITWEB_DOMAINS = [ + r"gcc\.gnu\.org/git", + r"git\.postgresql\.org/gitweb", + "sourceware\.org/git", + "git\.openssl\.org/gitweb", + "gitbox\.apache\.org", +] +GITWEB_ROUTE_REGEX = build_route_regex(GITWEB_DOMAINS) + + +@purl_router.route(GITWEB_ROUTE_REGEX) +def build_gitweb_purl(url): + """ + Return a PackageURL object from a Gitweb url. + For example: + https://gcc.gnu.org/git/?p=gcc.git + https://git.postgresql.org/gitweb/?p=hamn.git + https://sourceware.org/git/?p=glibc.git + https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=82cc94e5fb69d1c45a386f83798251de5bff9339 + https://git.postgresql.org/gitweb/?p=hamn.git;a=commit;h=a796b71a5b3fe7f751f1086a08cb114b9877dea2 + https://sourceware.org/git/?p=glibc.git;a=commit;h=dedebed24f77762eea7d3c5ed2739a90a4d60461 + https://gitbox.apache.org/repos/asf?p=xalan-java.git;a=commit;h=da3e0d06b467247643ce04e88d3346739d119f21 + """ + + gitweb_pattern = ( + r"^https?://" + r"(?P[^?]+?)" + r"/?(?=\?)" + r"(?=.*[?;&]p=(?P[^;&]+?)(?:\.git)?(?:[;&]|$))" + r"(?:(?=.*[?;&]h=(?P[0-9a-fA-F]{7,64}))|)" + ) + + commit_match = re.search(gitweb_pattern, url) + if commit_match: + namespace = commit_match.group("namespace") + name = commit_match.group("name") + return PackageURL( + type="generic", + namespace=namespace, + name=name, + version=commit_match.group("version"), + qualifiers={}, + subpath="", + ) + + @purl_router.route("https?://gitlab\\.com/(?!.*/archive/).*") def build_gitlab_purl(url): """ diff --git a/tests/contrib/data/url2purl.json b/tests/contrib/data/url2purl.json index 3a99dd2..4fcbe8d 100644 --- a/tests/contrib/data/url2purl.json +++ b/tests/contrib/data/url2purl.json @@ -269,7 +269,7 @@ "https://hackage.haskell.org/package/3d-graphics-examples-0.0.0.2/3d-graphics-examples-0.0.0.2.tar.gz": "pkg:hackage/3d-graphics-examples@0.0.0.2", "https://hackage.haskell.org/package/cli-extras-0.2.0.0": "pkg:hackage/cli-extras@0.2.0.0", "https://hackage.haskell.org/package/cli-extras-0.2.0.0/": "pkg:hackage/cli-extras@0.2.0.0", - "https://salsa.debian.org/lxc-team/lxc/-/archive/master/lxc-master.tar.gz": "pkg:generic/lxc-master.tar.gz?download_url=https://salsa.debian.org/lxc-team/lxc/-/archive/master/lxc-master.tar.gz", + "https://salsa.debian.org/lxc-team/lxc/-/archive/master/lxc-master.tar.gz": "pkg:gitlab/salsa.debian.org/lxc-master.tar.gz?download_url=https://salsa.debian.org/lxc-team/lxc/-/archive/master/lxc-master.tar.gz", "http://apt-rpm.org/": null, "": null, "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/android-notifier/android-notifier-desktop-0.5.1-1.i386.rpm": "pkg:generic/code.google.com/android-notifier?download_url=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/android-notifier/android-notifier-desktop-0.5.1-1.i386.rpm", @@ -277,5 +277,56 @@ "https://packagemanager.rstudio.com/cran/2022-06-23/src/contrib/curl_4.3.2.tar.gz": "pkg:cran/curl@4.3.2?download_url=https://packagemanager.rstudio.com/cran/2022-06-23/src/contrib/curl_4.3.2.tar.gz", "https://github.com/TG1999/first_repo/commit/98e516011d6e096e25247b82fc5f196bbeecff10": "pkg:github/tg1999/first_repo@98e516011d6e096e25247b82fc5f196bbeecff10", "https://gitlab.com/TG1999/first_repo/-/commit/bf04e5f289885cf2f20a92b387bcc6df33e30809": "pkg:gitlab/tg1999/first_repo@bf04e5f289885cf2f20a92b387bcc6df33e30809", - "https://bitbucket.org/TG1999/first_repo/commits/16a60c4a74ef477cd8c16ca82442eaab2fbe8c86": "pkg:bitbucket/tg1999/first_repo@16a60c4a74ef477cd8c16ca82442eaab2fbe8c86" -} + "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm/-/commit/a5f07894058c4198f61e533d727b343c5be879b0": "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm@a5f07894058c4198f61e533d727b343c5be879b0?repository_url=https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm", + "https://gitlab.gnome.org/GNOME/gimp/-/commit/112a5e038f0646eae5ae314988ec074433d2b365": "pkg:gitlab/gitlab.gnome.org/gnome/gimp@112a5e038f0646eae5ae314988ec074433d2b365?repository_url=https://gitlab.gnome.org/GNOME/gimp", + "https://gitlab.freedesktop.org/poppler/poppler/-/commit/8677500399fc2548fa816b619580c2c07915a98c": "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler@8677500399fc2548fa816b619580c2c07915a98c?repository_url=https://gitlab.freedesktop.org/poppler/poppler", + "https://salsa.debian.org/apt-team/apt/-/commit/dceb1e49e4b8e4dadaf056be34088b415939cda6": "pkg:gitlab/salsa.debian.org/apt-team/apt@dceb1e49e4b8e4dadaf056be34088b415939cda6?repository_url=https://salsa.debian.org/apt-team/apt", + "https://gitea.com/htc47/entur/commit/271b852cfb761a1fe257aa0f0a12ff38bd8bfd1c": "pkg:generic/gitea.com/htc47/entur@271b852cfb761a1fe257aa0f0a12ff38bd8bfd1c", + "https://codeberg.org/alpinelinux/aports/commit/a40a9732c840e5a324fba78b0ff7980b497c3831": "pkg:generic/codeberg.org/alpinelinux/aports@a40a9732c840e5a324fba78b0ff7980b497c3831", + "https://git.kernel.org/pub/scm/utils/b4/b4.git/commit/?id=477734000555ffc24bf873952e40367deee26f17": "pkg:generic/git.kernel.org/pub/scm/utils/b4/b4@477734000555ffc24bf873952e40367deee26f17", + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/core/sock.c?id=9d538fa60bad4f7b23193c89e843797a1cf71ef3": "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux@9d538fa60bad4f7b23193c89e843797a1cf71ef3", + "https://cgit.git.savannah.gnu.org/cgit/uddf.git/commit/?id=98c41e131dc952aee43d4ec392b80ca4c426be8d": "pkg:generic/cgit.git.savannah.gnu.org/cgit/uddf@98c41e131dc952aee43d4ec392b80ca4c426be8d", + "https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git/commit/?id=7457fe9541b5162f285454947448d553a5d5a531": "pkg:generic/git.kernel.org/pub/scm/virt/kvm/mst/qemu@7457fe9541b5162f285454947448d553a5d5a531", + "https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git/commit/?h=for-next&id=bd771cf5c4254511cc4abb88f3dab3bd58bdf8e8": "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev@bd771cf5c4254511cc4abb88f3dab3bd58bdf8e8", + "https://git.kernel.org/stable/c/9a9a8fe26751334b7739193a94eba741073b8a55": "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/stable/linux@9a9a8fe26751334b7739193a94eba741073b8a55", + "https://gitweb.gentoo.org/dev/darkside.git/commit/?id=8d4b0836f3b6ab7075212926d9aad0b50246d825": "pkg:generic/gitweb.gentoo.org/dev/darkside@8d4b0836f3b6ab7075212926d9aad0b50246d825", + "https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f73ae47c5e48010f504f3f55567152258f3013ae": "pkg:generic/gitweb.gentoo.org/repo/gentoo@f73ae47c5e48010f504f3f55567152258f3013ae", + "https://android.googlesource.com/platform/frameworks/base/+/b4da73a935a8c906ff5df562155824d63ac849ab": "pkg:generic/android.googlesource.com/platform/frameworks/base@b4da73a935a8c906ff5df562155824d63ac849ab", + "https://android.googlesource.com/device/generic/vulkan-cereal/+/240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0": "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal@240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0", + "https://chromium.googlesource.com/aosp/platform/external/dbus-binding-generator/+/7574c671c7c64aab957dc507fffff3c8c38dc7cb": "pkg:generic/chromium.googlesource.com/aosp/platform/external/dbus-binding-generator@7574c671c7c64aab957dc507fffff3c8c38dc7cb", + "https://aomedia.googlesource.com/libavifinfo/+/43716e9c34d3389b4882fbd1a81c04543ed04fe3": "pkg:generic/aomedia.googlesource.com/libavifinfo@43716e9c34d3389b4882fbd1a81c04543ed04fe3", + "https://gerrit.googlesource.com/gerrit/+/45071d6977932bca5a1427c8abad24710fed2e33": "pkg:generic/gerrit.googlesource.com/gerrit@45071d6977932bca5a1427c8abad24710fed2e33", + "https://sourceforge.net/p/djvu/djvulibre-git/ci/e15d51510048927f172f1bf1f27ede65907d940d": "pkg:generic/sourceforge.net/p/djvu/djvulibre-git@e15d51510048927f172f1bf1f27ede65907d940d", + "https://sourceforge.net/p/expat/code_git/ci/f0bec73b018caa07d3e75ec8dd967f3785d71bde": "pkg:generic/sourceforge.net/p/expat/code_git@f0bec73b018caa07d3e75ec8dd967f3785d71bde", + "https://forge-allura.apache.org/p/allura/git/ci/674e070e5ca7db7c75cf61d8efd2a3e3e49bd946": "pkg:generic/forge-allura.apache.org/p/allura/git@674e070e5ca7db7c75cf61d8efd2a3e3e49bd946", + "https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=82cc94e5fb69d1c45a386f83798251de5bff9339": "pkg:generic/gcc.gnu.org/git/gcc@82cc94e5fb69d1c45a386f83798251de5bff9339", + "https://git.postgresql.org/gitweb/?p=hamn.git;a=commit;h=a796b71a5b3fe7f751f1086a08cb114b9877dea2": "pkg:generic/git.postgresql.org/gitweb/hamn@a796b71a5b3fe7f751f1086a08cb114b9877dea2", + "https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=1ad73b4d27bd8c1b369a3cd453681d3a4f1bb9b2": "pkg:generic/git.openssl.org/gitweb/openssl@1ad73b4d27bd8c1b369a3cd453681d3a4f1bb9b2", + "https://sourceware.org/git/?p=bunsen.git;a=commit;h=6c55933f37099517e050c923527b0b2267e1deed": "pkg:generic/sourceware.org/git/bunsen@6c55933f37099517e050c923527b0b2267e1deed", + "https://gitbox.apache.org/repos/asf?p=xalan-java.git;a=commit;h=da3e0d06b467247643ce04e88d3346739d119f21": "pkg:generic/gitbox.apache.org/repos/asf/xalan-java@da3e0d06b467247643ce04e88d3346739d119f21", + "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm": "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm?repository_url=https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm", + "https://gitlab.gnome.org/GNOME/gimp": "pkg:gitlab/gitlab.gnome.org/gnome/gimp?repository_url=https://gitlab.gnome.org/GNOME/gimp", + "https://gitlab.freedesktop.org/poppler/poppler": "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler?repository_url=https://gitlab.freedesktop.org/poppler/poppler", + "https://gitea.com/htc47/entur": "pkg:generic/gitea.com/htc47/entur", + "https://codeberg.org/alpinelinux/aports": "pkg:generic/codeberg.org/alpinelinux/aports", + "https://git.kernel.org/pub/scm/utils/b4/b4.git": "pkg:generic/git.kernel.org/pub/scm/utils/b4/b4", + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git": "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux", + "https://cgit.git.savannah.gnu.org/cgit/uddf.git": "pkg:generic/cgit.git.savannah.gnu.org/cgit/uddf", + "https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git": "pkg:generic/git.kernel.org/pub/scm/virt/kvm/mst/qemu", + "https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git": "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev", + "https://gitweb.gentoo.org/dev/darkside.git": "pkg:generic/gitweb.gentoo.org/dev/darkside", + "https://gitweb.gentoo.org/repo/gentoo.git": "pkg:generic/gitweb.gentoo.org/repo/gentoo", + "https://android.googlesource.com/platform/frameworks/base": "pkg:generic/android.googlesource.com/platform/frameworks/base", + "https://android.googlesource.com/device/generic/vulkan-cereal": "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal", + "https://chromium.googlesource.com/aosp/platform/external/dbus-binding-generator": "pkg:generic/chromium.googlesource.com/aosp/platform/external/dbus-binding-generator", + "https://aomedia.googlesource.com/libavifinfo": "pkg:generic/aomedia.googlesource.com/libavifinfo", + "https://gerrit.googlesource.com/gerrit": "pkg:generic/gerrit.googlesource.com/gerrit", + "https://sourceforge.net/p/djvu/djvulibre-git": "pkg:generic/sourceforge.net/p/djvu/djvulibre-git", + "https://sourceforge.net/p/expat/code_git": "pkg:generic/sourceforge.net/p/expat/code_git", + "https://forge-allura.apache.org/p/allura/git": "pkg:generic/forge-allura.apache.org/p/allura/git", + "https://gcc.gnu.org/git/?p=gcc.git": "pkg:generic/gcc.gnu.org/git/gcc", + "https://git.postgresql.org/gitweb/?p=hamn.git": "pkg:generic/git.postgresql.org/gitweb/hamn", + "https://git.openssl.org/gitweb/?p=openssl.git": "pkg:generic/git.openssl.org/gitweb/openssl", + "https://sourceware.org/git/?p=bunsen.git": "pkg:generic/sourceware.org/git/bunsen", + "https://gitbox.apache.org/repos/asf?p=xalan-java.git": "pkg:generic/gitbox.apache.org/repos/asf/xalan-java" +} \ No newline at end of file diff --git a/tests/contrib/test_purl2url.py b/tests/contrib/test_purl2url.py index b34348c..82cdb8e 100644 --- a/tests/contrib/test_purl2url.py +++ b/tests/contrib/test_purl2url.py @@ -70,6 +70,42 @@ def test_purl2url_get_repo_url(): "pkg:cocoapods/MapsIndoors@3.24.0": "https://cocoapods.org/pods/MapsIndoors", "pkg:maven/org.apache.commons/commons-io@1.3.2": "https://repo.maven.apache.org/maven2/org/apache/commons/commons-io/1.3.2", "pkg:maven/org.apache.commons/commons-io@1.3.2?repository_url=https://repo1.maven.org/maven2": "https://repo1.maven.org/maven2/org/apache/commons/commons-io/1.3.2", + "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm@a5f07894058c4198f61e533d727b343c5be879b0?repository_url=https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm": "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm", + "pkg:gitlab/gitlab.gnome.org/gnome/gimp@112a5e038f0646eae5ae314988ec074433d2b365?repository_url=https://gitlab.gnome.org/gnome/gimp": "https://gitlab.gnome.org/gnome/gimp", + "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler@8677500399fc2548fa816b619580c2c07915a98c?repository_url=https://gitlab.freedesktop.org/poppler/poppler": "https://gitlab.freedesktop.org/poppler/poppler", + "pkg:gitlab/salsa.debian.org/apt-team/apt@df81895bce764dd02fbb4d67b92d28a730b5281f?repository_url=https://salsa.debian.org/apt-team/apt": "https://salsa.debian.org/apt-team/apt", + "pkg:generic/git.kernel.org/pub/scm/libs/liba2i/liba2i@4fc8196d7811c26abefaf3a3ae6b5c67c4c9cbc9": "https://git.kernel.org/pub/scm/libs/liba2i/liba2i.git", + "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs@bc3372351d0c8b2726b7d4229b878342e3e6b0e8": "https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git", + "pkg:generic/gitweb.gentoo.org/dev/darkside@8d4b0836f3b6ab7075212926d9aad0b50246d825": "https://gitweb.gentoo.org/dev/darkside.git", + "pkg:generic/gitweb.gentoo.org/repo/gentoo@f73ae47c5e48010f504f3f55567152258f3013ae": "https://gitweb.gentoo.org/repo/gentoo.git", + "pkg:generic/android.googlesource.com/accessories/manifest@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://android.googlesource.com/accessories/manifest", + "pkg:generic/aomedia.googlesource.com/libavifinfo@43716e9c34d3389b4882fbd1a81c04543ed04fe3": "https://aomedia.googlesource.com/libavifinfo", + "pkg:generic/chromium.googlesource.com/infra/infra@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://chromium.googlesource.com/infra/infra", + "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal@240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0": "https://android.googlesource.com/device/generic/vulkan-cereal", + "pkg:generic/sourceforge.net/p/infrarecorder/code@8fab704119ff23691f075f6a281521b6c7d7e55f": "https://sourceforge.net/p/infrarecorder/code", + "pkg:generic/sourceforge.net/p/expat/code_git@f0bec73b018caa07d3e75ec8dd967f3785d71bde": "https://sourceforge.net/p/expat/code_git", + "pkg:generic/forge-allura.apache.org/p/allura/git@674e070e5ca7db7c75cf61d8efd2a3e3e49bd946": "https://forge-allura.apache.org/p/allura/git", + "pkg:generic/gcc.gnu.org/git/gcc@82cc94e5fb69d1c45a386f83798251de5bff9339": "https://gcc.gnu.org/git/?p=gcc.git", + "pkg:generic/git.postgresql.org/gitweb/p/infrarecorder/hamn@4f4fed18770ff15da3c7ab1e81854b75181ab5d0": "https://git.postgresql.org/gitweb/p/infrarecorder/?p=hamn.git", + "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm?repository_url=https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm": "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm", + "pkg:gitlab/gitlab.gnome.org/GNOME/gimp?repository_url=https://gitlab.gnome.org/GNOME/gimp": "https://gitlab.gnome.org/gnome/gimp", + "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler?repository_url=https://gitlab.freedesktop.org/poppler/poppler": "https://gitlab.freedesktop.org/poppler/poppler", + "pkg:gitlab/salsa.debian.org/apt-team/apt?repository_url=https://salsa.debian.org/apt-team/apt": "https://salsa.debian.org/apt-team/apt", + "pkg:generic/gitea.com/htc47/entur": "https://gitea.com/htc47/entur", + "pkg:generic/codeberg.org/alpinelinux/aports": "https://codeberg.org/alpinelinux/aports", + "pkg:generic/git.kernel.org/pub/scm/utils/b4/b4": "https://git.kernel.org/pub/scm/utils/b4/b4.git", + "pkg:generic/git.kernel.org/pub/scm/virt/kvm/mst/qemu": "https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git", + "pkg:generic/gitweb.gentoo.org/dev/darkside": "https://gitweb.gentoo.org/dev/darkside.git", + "pkg:generic/gitweb.gentoo.org/repo/gentoo": "https://gitweb.gentoo.org/repo/gentoo.git", + "pkg:generic/android.googlesource.com/platform/frameworks/base": "https://android.googlesource.com/platform/frameworks/base", + "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal": "https://android.googlesource.com/device/generic/vulkan-cereal", + "pkg:generic/chromium.googlesource.com/aosp/platform/external/dbus-binding-generator": "https://chromium.googlesource.com/aosp/platform/external/dbus-binding-generator", + "pkg:generic/aomedia.googlesource.com/libavifinfo": "https://aomedia.googlesource.com/libavifinfo", + "pkg:generic/sourceforge.net/p/djvu/djvulibre-git": "https://sourceforge.net/p/djvu/djvulibre-git", + "pkg:generic/sourceforge.net/p/expat/code_git": "https://sourceforge.net/p/expat/code_git", + "pkg:generic/forge-allura.apache.org/p/allura/git": "https://forge-allura.apache.org/p/allura/git", + "pkg:generic/gcc.gnu.org/git/gcc": "https://gcc.gnu.org/git/?p=gcc.git", + "pkg:generic/git.postgresql.org/gitweb/hamn": "https://git.postgresql.org/gitweb/?p=hamn.git", } for purl, url in purls_url.items(): @@ -133,6 +169,61 @@ def test_purl2url_get_download_url(): assert url == purl2url.get_download_url(purl) +def test_purl2url_get_patch_url(): + purls_url = { + "pkg:github/aboutcode-org/vulnerablecode@98e516011d6e096e25247b82fc5f196bbeecff10": "https://github.com/aboutcode-org/vulnerablecode/commit/98e516011d6e096e25247b82fc5f196bbeecff10.patch", + "pkg:gitlab/tg1999/firebase@6ceeeb9feb2b7420230e0d19753a626f9a43f9cb": "https://gitlab.com/tg1999/firebase/-/commit/6ceeeb9feb2b7420230e0d19753a626f9a43f9cb.patch", + "pkg:bitbucket/trove4j/trove@d4433e656b9eba5b1ed713ffe8e15660af37dfb4": "https://bitbucket.org/trove4j/trove/commits/d4433e656b9eba5b1ed713ffe8e15660af37dfb4/raw", + "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm@a5f07894058c4198f61e533d727b343c5be879b0?repository_url=https://git.codelinaro.org/clo/qsdk/oss": "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm/-/commit/a5f07894058c4198f61e533d727b343c5be879b0.patch", + "pkg:gitlab/gitlab.gnome.org/GNOME/gimp@112a5e038f0646eae5ae314988ec074433d2b365?repository_url=https://gitlab.gnome.org/GNOME/gimp": "https://gitlab.gnome.org/gnome/gimp/-/commit/112a5e038f0646eae5ae314988ec074433d2b365.patch", + "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler@8677500399fc2548fa816b619580c2c07915a98c?repository_url=https://gitlab.freedesktop.org/poppler/poppler": "https://gitlab.freedesktop.org/poppler/poppler/-/commit/8677500399fc2548fa816b619580c2c07915a98c.patch", + "pkg:gitlab/salsa.debian.org/apt-team/apt@df81895bce764dd02fbb4d67b92d28a730b5281f?repository_url=https://salsa.debian.org/apt-team/apt": "https://salsa.debian.org/apt-team/apt/-/commit/df81895bce764dd02fbb4d67b92d28a730b5281f.patch", + "pkg:generic/git.kernel.org/pub/scm/libs/liba2i/liba2i@4fc8196d7811c26abefaf3a3ae6b5c67c4c9cbc9": "https://git.kernel.org/pub/scm/libs/liba2i/liba2i.git/patch/?id=4fc8196d7811c26abefaf3a3ae6b5c67c4c9cbc9", + "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs@bc3372351d0c8b2726b7d4229b878342e3e6b0e8": "https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git/patch/?id=bc3372351d0c8b2726b7d4229b878342e3e6b0e8", + "pkg:generic/gitweb.gentoo.org/dev/darkside@8d4b0836f3b6ab7075212926d9aad0b50246d825": "https://gitweb.gentoo.org/dev/darkside.git/patch/?id=8d4b0836f3b6ab7075212926d9aad0b50246d825", + "pkg:generic/gitweb.gentoo.org/repo/gentoo@f73ae47c5e48010f504f3f55567152258f3013ae": "https://gitweb.gentoo.org/repo/gentoo.git/patch/?id=f73ae47c5e48010f504f3f55567152258f3013ae", + "pkg:generic/android.googlesource.com/accessories/manifest@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://android.googlesource.com/accessories/manifest/+/9ad7ef740dc39834a88bf95c69f35f18b8f45543^!?format=TEXT", + "pkg:generic/aomedia.googlesource.com/libavifinfo@43716e9c34d3389b4882fbd1a81c04543ed04fe3": "https://aomedia.googlesource.com/libavifinfo/+/43716e9c34d3389b4882fbd1a81c04543ed04fe3^!?format=TEXT", + "pkg:generic/chromium.googlesource.com/infra/infra@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://chromium.googlesource.com/infra/infra/+/9ad7ef740dc39834a88bf95c69f35f18b8f45543^!?format=TEXT", + "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal@240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0": "https://android.googlesource.com/device/generic/vulkan-cereal/+/240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0^!?format=TEXT", + "pkg:generic/sourceforge.net/p/infrarecorder/code@8fab704119ff23691f075f6a281521b6c7d7e55f": None, + "pkg:generic/sourceforge.net/p/expat/code_git@f0bec73b018caa07d3e75ec8dd967f3785d71bde": None, + "pkg:generic/forge-allura.apache.org/p/allura/git@674e070e5ca7db7c75cf61d8efd2a3e3e49bd946": None, + "pkg:generic/gcc.gnu.org/git/gcc@82cc94e5fb69d1c45a386f83798251de5bff9339": "https://gcc.gnu.org/git/?p=gcc.git;a=patch;h=82cc94e5fb69d1c45a386f83798251de5bff9339", + "pkg:generic/git.postgresql.org/gitweb/p/infrarecorder/hamn@4f4fed18770ff15da3c7ab1e81854b75181ab5d0": "https://git.postgresql.org/gitweb/p/infrarecorder/?p=hamn.git;a=patch;h=4f4fed18770ff15da3c7ab1e81854b75181ab5d0", + } + + for purl, url in purls_url.items(): + assert url == purl2url.get_patch_url(purl) + + +def test_purl2url_get_commit_url(): + purls_url = { + "pkg:github/aboutcode-org/vulnerablecode@98e516011d6e096e25247b82fc5f196bbeecff10": "https://github.com/aboutcode-org/vulnerablecode/commit/98e516011d6e096e25247b82fc5f196bbeecff10", + "pkg:gitlab/tg1999/firebase@03afa56261250df3fa9ddb19915bc06e5d3ac971": "https://gitlab.com/tg1999/firebase/-/commit/03afa56261250df3fa9ddb19915bc06e5d3ac971", + "pkg:gitlab/git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm@a5f07894058c4198f61e533d727b343c5be879b0?repository_url=https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm": "https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-msm/-/commit/a5f07894058c4198f61e533d727b343c5be879b0", + "pkg:gitlab/gitlab.gnome.org/GNOME/gimp@112a5e038f0646eae5ae314988ec074433d2b365?repository_url=https://gitlab.gnome.org/gnome/gimp": "https://gitlab.gnome.org/gnome/gimp/-/commit/112a5e038f0646eae5ae314988ec074433d2b365", + "pkg:gitlab/gitlab.freedesktop.org/poppler/poppler@8677500399fc2548fa816b619580c2c07915a98c?repository_url=https://gitlab.freedesktop.org/poppler/poppler": "https://gitlab.freedesktop.org/poppler/poppler/-/commit/8677500399fc2548fa816b619580c2c07915a98c", + "pkg:gitlab/salsa.debian.org/apt-team/apt@df81895bce764dd02fbb4d67b92d28a730b5281f?repository_url=https://salsa.debian.org/apt-team/apt": "https://salsa.debian.org/apt-team/apt/-/commit/df81895bce764dd02fbb4d67b92d28a730b5281f", + "pkg:generic/git.kernel.org/pub/scm/libs/liba2i/liba2i@4fc8196d7811c26abefaf3a3ae6b5c67c4c9cbc9": "https://git.kernel.org/pub/scm/libs/liba2i/liba2i.git/commit/?id=4fc8196d7811c26abefaf3a3ae6b5c67c4c9cbc9", + "pkg:generic/git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs@bc3372351d0c8b2726b7d4229b878342e3e6b0e8": "https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git/commit/?id=bc3372351d0c8b2726b7d4229b878342e3e6b0e8", + "pkg:generic/gitweb.gentoo.org/dev/darkside@8d4b0836f3b6ab7075212926d9aad0b50246d825": "https://gitweb.gentoo.org/dev/darkside.git/commit/?id=8d4b0836f3b6ab7075212926d9aad0b50246d825", + "pkg:generic/gitweb.gentoo.org/repo/gentoo@f73ae47c5e48010f504f3f55567152258f3013ae": "https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f73ae47c5e48010f504f3f55567152258f3013ae", + "pkg:generic/android.googlesource.com/accessories/manifest@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://android.googlesource.com/accessories/manifest/+/9ad7ef740dc39834a88bf95c69f35f18b8f45543", + "pkg:generic/aomedia.googlesource.com/libavifinfo@43716e9c34d3389b4882fbd1a81c04543ed04fe3": "https://aomedia.googlesource.com/libavifinfo/+/43716e9c34d3389b4882fbd1a81c04543ed04fe3", + "pkg:generic/chromium.googlesource.com/infra/infra@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://chromium.googlesource.com/infra/infra/+/9ad7ef740dc39834a88bf95c69f35f18b8f45543", + "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal@240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0": "https://android.googlesource.com/device/generic/vulkan-cereal/+/240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0", + "pkg:generic/sourceforge.net/p/infrarecorder/code@8fab704119ff23691f075f6a281521b6c7d7e55f": "https://sourceforge.net/p/infrarecorder/code/ci/8fab704119ff23691f075f6a281521b6c7d7e55f", + "pkg:generic/sourceforge.net/p/expat/code_git@f0bec73b018caa07d3e75ec8dd967f3785d71bde": "https://sourceforge.net/p/expat/code_git/ci/f0bec73b018caa07d3e75ec8dd967f3785d71bde", + "pkg:generic/forge-allura.apache.org/p/allura/git@674e070e5ca7db7c75cf61d8efd2a3e3e49bd946": "https://forge-allura.apache.org/p/allura/git/ci/674e070e5ca7db7c75cf61d8efd2a3e3e49bd946", + "pkg:generic/gcc.gnu.org/git/gcc@82cc94e5fb69d1c45a386f83798251de5bff9339": "https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=82cc94e5fb69d1c45a386f83798251de5bff9339", + "pkg:generic/git.postgresql.org/gitweb/p/infrarecorder/hamn@4f4fed18770ff15da3c7ab1e81854b75181ab5d0": "https://git.postgresql.org/gitweb/p/infrarecorder/?p=hamn.git;a=commit;h=4f4fed18770ff15da3c7ab1e81854b75181ab5d0", + } + + for purl, url in purls_url.items(): + assert url == purl2url.get_commit_url(purl) + + def test_purl2url_get_inferred_urls(): purls_url = { "pkg:cargo/rand@0.7.2": [