From 1e66dd0e52f273e1fdd8cfcca3a95f9e76cc52ef Mon Sep 17 00:00:00 2001 From: ziad hany Date: Tue, 10 Feb 2026 14:13:31 +0200 Subject: [PATCH 1/4] Add url2purl support for git.kernel.org, android.googlesource.com Signed-off-by: ziad hany --- src/packageurl/contrib/url2purl.py | 57 ++++++++++++++++++++++++++++++ tests/contrib/data/url2purl.json | 6 +++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/packageurl/contrib/url2purl.py b/src/packageurl/contrib/url2purl.py index 2353b0b..84fb2b0 100644 --- a/src/packageurl/contrib/url2purl.py +++ b/src/packageurl/contrib/url2purl.py @@ -667,6 +667,63 @@ def build_bitbucket_purl(url): ) +@purl_router.route("https?://git\.kernel\\.org/.*") +def build_kernel_purl(url): + """ + Return a PackageURL object from Kernel `url`. + For example: + https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=74770b1fd2be612f9c2cf807db81fcdcc35e6560 + """ + + kernel_project_pattern = ( + r"^https?://git\.kernel\.org/pub/scm/[^/]+/" + r"(?P.+)/" + r"(?P[^/]+?)" + r"(?:\.git)?" + r"/commit/\?id=" + r"(?P[0-9a-fA-F]{7,64})/?$" + ) + + commit_matche = re.search(kernel_project_pattern, url) + if commit_matche: + namespace = "git.kernel.org/" + commit_matche.group("namespace") + return PackageURL( + type="generic", + namespace=namespace, + name=commit_matche.group("name"), + version=commit_matche.group("version"), + qualifiers={}, + subpath="", + ) + + +@purl_router.route("https?://android\.googlesource\\.com/.*") +def build_android_purl(url): + """ + Return a PackageURL object from Android `url`. + For example: + https://android.googlesource.com/platform/packages/apps/Settings/+/2968ccc911956fa5813a9a6a5e5c8970e383a60f + """ + + commit_pattern = ( + r"^https?://android\.googlesource\.com/" + r"(?P.+)" + r"/\+/" + r"(?P[0-9a-fA-F]{7,64})" + ) + + commit_matche = re.search(commit_pattern, url) + if commit_matche: + return PackageURL( + type="generic", + namespace="android.googlesource.com", + name=commit_matche.group("name"), + version=commit_matche.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..07c3d20 100644 --- a/tests/contrib/data/url2purl.json +++ b/tests/contrib/data/url2purl.json @@ -277,5 +277,9 @@ "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.kernel.org/pub/scm/utils/b4/b4.git/commit/?id=477734000555ffc24bf873952e40367deee26f17": "pkg:generic/git.kernel.org/b4/b4@477734000555ffc24bf873952e40367deee26f17", + "https://git.kernel.org/pub/scm/docs/kernel/ksmap.git/commit/?id=e8c7bac5321ba31d63496bd7fecea3db1848e355": "pkg:generic/git.kernel.org/kernel/ksmap@e8c7bac5321ba31d63496bd7fecea3db1848e355", + "https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git/commit/?id=7457fe9541b5162f285454947448d553a5d5a531": "pkg:generic/git.kernel.org/kvm/mst/qemu@7457fe9541b5162f285454947448d553a5d5a531", + "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" } From 7eae2ffe6092d2a059741c6c739566e6a038659d Mon Sep 17 00:00:00 2001 From: ziad hany Date: Fri, 13 Feb 2026 14:54:16 +0200 Subject: [PATCH 2/4] Extend url2purl to support sourceforge.net for commit extraction Signed-off-by: ziad hany --- src/packageurl/contrib/url2purl.py | 32 +++++++++++++++++++++++++++++- tests/contrib/data/url2purl.json | 9 +++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/packageurl/contrib/url2purl.py b/src/packageurl/contrib/url2purl.py index 84fb2b0..b55ea95 100644 --- a/src/packageurl/contrib/url2purl.py +++ b/src/packageurl/contrib/url2purl.py @@ -676,7 +676,7 @@ def build_kernel_purl(url): """ kernel_project_pattern = ( - r"^https?://git\.kernel\.org/pub/scm/[^/]+/" + r"^https?://git\.kernel\.org/" r"(?P.+)/" r"(?P[^/]+?)" r"(?:\.git)?" @@ -724,6 +724,36 @@ def build_android_purl(url): ) +@purl_router.route("https?://sourceforge\\.net/p/.*") +def build_sourceforge_purl(url): + """ + Return a PackageURL object from sourceforge `url`. + For example: + https://sourceforge.net/p/djvu/djvulibre-git/ci/e15d51510048927f172f1bf1f27ede65907d940d + https://sourceforge.net/p/infrarecorder/code/ci/9361b6f267e7b1c1576c48f6dac6dec18d8a93e0/ + """ + + sourceforge_pattern = ( + r"^https?://sourceforge\.net/" + r"(?P.+)/" + r"(?P[^/]+?)" + r"/ci/" + r"(?P[0-9a-fA-F]{7,64})/?$" + ) + + commit_matche = re.search(sourceforge_pattern, url) + if commit_matche: + namespace = "sourceforge.net/" + commit_matche.group("namespace") + return PackageURL( + type="generic", + namespace=namespace, + name=commit_matche.group("name"), + version=commit_matche.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 07c3d20..f5034c6 100644 --- a/tests/contrib/data/url2purl.json +++ b/tests/contrib/data/url2purl.json @@ -277,9 +277,10 @@ "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://git.kernel.org/pub/scm/utils/b4/b4.git/commit/?id=477734000555ffc24bf873952e40367deee26f17": "pkg:generic/git.kernel.org/b4/b4@477734000555ffc24bf873952e40367deee26f17", - "https://git.kernel.org/pub/scm/docs/kernel/ksmap.git/commit/?id=e8c7bac5321ba31d63496bd7fecea3db1848e355": "pkg:generic/git.kernel.org/kernel/ksmap@e8c7bac5321ba31d63496bd7fecea3db1848e355", - "https://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git/commit/?id=7457fe9541b5162f285454947448d553a5d5a531": "pkg:generic/git.kernel.org/kvm/mst/qemu@7457fe9541b5162f285454947448d553a5d5a531", + "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/docs/kernel/ksmap.git/commit/?id=e8c7bac5321ba31d63496bd7fecea3db1848e355": "pkg:generic/git.kernel.org/pub/scm/docs/kernel/ksmap@e8c7bac5321ba31d63496bd7fecea3db1848e355", + "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://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://android.googlesource.com/device/generic/vulkan-cereal/+/240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0": "pkg:generic/android.googlesource.com/device/generic/vulkan-cereal@240dedcb0fa917b3d2dcc4a9d4c332697c5e48a0", + "https://sourceforge.net/p/djvu/djvulibre-git/ci/e15d51510048927f172f1bf1f27ede65907d940d": "pkg:generic/sourceforge.net/p/djvu/djvulibre-git@e15d51510048927f172f1bf1f27ede65907d940d" } From 98f4d71daea3dcc18ca43fa70f685d9d67a822aa Mon Sep 17 00:00:00 2001 From: ziad hany Date: Tue, 17 Feb 2026 01:40:16 +0200 Subject: [PATCH 3/4] Add support to purl2url for git.kernel.org, android.googlesource.com, sourceforge.net Signed-off-by: ziad hany --- src/packageurl/contrib/purl2url.py | 17 +++++++++++++++++ tests/contrib/test_purl2url.py | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/src/packageurl/contrib/purl2url.py b/src/packageurl/contrib/purl2url.py index 5806251..3470d29 100644 --- a/src/packageurl/contrib/purl2url.py +++ b/src/packageurl/contrib/purl2url.py @@ -172,6 +172,23 @@ def build_gitlab_repo_url(purl): return f"https://gitlab.com/{namespace}/{name}" +@repo_router.route("pkg:generic/.*") +def build_generic_repo_url(purl): + """ + Return a Generic repo URL from the `purl` string. + """ + purl_data = PackageURL.from_string(purl) + name = purl_data.name + namespace = purl_data.namespace + version = purl_data.version + if namespace.startswith("git.kernel.org"): + return f"https://{namespace}/{name}/commit/?id={version}" + if namespace.startswith("android.googlesource.com"): + return f"https://{namespace}/{name}/+/{version}" + if namespace.startswith("sourceforge.net"): + return f"https://{namespace}/{name}/ci/{version}" + + @repo_router.route("pkg:(gem|rubygems)/.*") def build_rubygems_repo_url(purl): """ diff --git a/tests/contrib/test_purl2url.py b/tests/contrib/test_purl2url.py index b34348c..8a61d34 100644 --- a/tests/contrib/test_purl2url.py +++ b/tests/contrib/test_purl2url.py @@ -70,6 +70,10 @@ 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:generic/git.kernel.org/pub/scm/libs/liba2i/liba2i.git@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.git@bc3372351d0c8b2726b7d4229b878342e3e6b0e8": "https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git/commit/?id=bc3372351d0c8b2726b7d4229b878342e3e6b0e8", + "pkg:generic/android.googlesource.com/accessories/manifest@9ad7ef740dc39834a88bf95c69f35f18b8f45543": "https://android.googlesource.com/accessories/manifest/+/9ad7ef740dc39834a88bf95c69f35f18b8f45543", + "pkg:generic/sourceforge.net/p/infrarecorder/code@8fab704119ff23691f075f6a281521b6c7d7e55f": "https://sourceforge.net/p/infrarecorder/code/ci/8fab704119ff23691f075f6a281521b6c7d7e55f", } for purl, url in purls_url.items(): From 031c8f8ea0d40bbc8b7dd513892e1f19b6f17ff7 Mon Sep 17 00:00:00 2001 From: ziad hany Date: Wed, 18 Feb 2026 16:03:09 +0200 Subject: [PATCH 4/4] Update purl2url and url2purl to support aomedia.googlesource.com Signed-off-by: ziad hany --- src/packageurl/contrib/purl2url.py | 6 +++++- src/packageurl/contrib/url2purl.py | 19 ++++++++++--------- tests/contrib/test_purl2url.py | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/packageurl/contrib/purl2url.py b/src/packageurl/contrib/purl2url.py index 3470d29..f2cdcab 100644 --- a/src/packageurl/contrib/purl2url.py +++ b/src/packageurl/contrib/purl2url.py @@ -27,6 +27,7 @@ from packageurl import PackageURL from packageurl.contrib.route import NoRouteAvailable from packageurl.contrib.route import Router +import re DEFAULT_MAVEN_REPOSITORY = "https://repo.maven.apache.org/maven2" @@ -181,10 +182,13 @@ def build_generic_repo_url(purl): name = purl_data.name namespace = purl_data.namespace version = purl_data.version + if namespace.startswith("git.kernel.org"): return f"https://{namespace}/{name}/commit/?id={version}" - if namespace.startswith("android.googlesource.com"): + + if re.match(r"^(android|aomedia)\.googlesource\.com(/.*)?$", namespace): return f"https://{namespace}/{name}/+/{version}" + if namespace.startswith("sourceforge.net"): return f"https://{namespace}/{name}/ci/{version}" diff --git a/src/packageurl/contrib/url2purl.py b/src/packageurl/contrib/url2purl.py index b55ea95..c1bf181 100644 --- a/src/packageurl/contrib/url2purl.py +++ b/src/packageurl/contrib/url2purl.py @@ -697,28 +697,29 @@ def build_kernel_purl(url): ) -@purl_router.route("https?://android\.googlesource\\.com/.*") -def build_android_purl(url): +@purl_router.route(r"https?://(android|aomedia)\.googlesource\.com/.*") +def build_googlesource_purl(url): """ Return a PackageURL object from Android `url`. For example: https://android.googlesource.com/platform/packages/apps/Settings/+/2968ccc911956fa5813a9a6a5e5c8970e383a60f + https://aomedia.googlesource.com/libavifinfo/+/43716e9c34d3389b4882fbd1a81c04543ed04fe3 """ commit_pattern = ( - r"^https?://android\.googlesource\.com/" - r"(?P.+)" + r"^https?://(?P(android|aomedia)\.googlesource\.com(?:/.*)?)" + r"/(?P[^/]+)" r"/\+/" r"(?P[0-9a-fA-F]{7,64})" ) - commit_matche = re.search(commit_pattern, url) - if commit_matche: + match = re.search(commit_pattern, url) + if match: return PackageURL( type="generic", - namespace="android.googlesource.com", - name=commit_matche.group("name"), - version=commit_matche.group("version"), + namespace=match.group("namespace"), + name=match.group("name"), + version=match.group("version"), qualifiers={}, subpath="", ) diff --git a/tests/contrib/test_purl2url.py b/tests/contrib/test_purl2url.py index 8a61d34..02f985e 100644 --- a/tests/contrib/test_purl2url.py +++ b/tests/contrib/test_purl2url.py @@ -73,6 +73,7 @@ def test_purl2url_get_repo_url(): "pkg:generic/git.kernel.org/pub/scm/libs/liba2i/liba2i.git@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.git@bc3372351d0c8b2726b7d4229b878342e3e6b0e8": "https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git/commit/?id=bc3372351d0c8b2726b7d4229b878342e3e6b0e8", "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/sourceforge.net/p/infrarecorder/code@8fab704119ff23691f075f6a281521b6c7d7e55f": "https://sourceforge.net/p/infrarecorder/code/ci/8fab704119ff23691f075f6a281521b6c7d7e55f", }