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/src/packageurl/contrib/url2purl.py b/src/packageurl/contrib/url2purl.py index 2353b0b..b55ea95 100644 --- a/src/packageurl/contrib/url2purl.py +++ b/src/packageurl/contrib/url2purl.py @@ -667,6 +667,93 @@ 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/" + 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?://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 3a99dd2..f5034c6 100644 --- a/tests/contrib/data/url2purl.json +++ b/tests/contrib/data/url2purl.json @@ -277,5 +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://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/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://sourceforge.net/p/djvu/djvulibre-git/ci/e15d51510048927f172f1bf1f27ede65907d940d": "pkg:generic/sourceforge.net/p/djvu/djvulibre-git@e15d51510048927f172f1bf1f27ede65907d940d" } 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():