Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Composer in purl2url #144

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/packageurl/contrib/purl2url.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,23 @@ def build_pypi_repo_url(purl):
return f"https://pypi.org/project/{name}/"


@repo_router.route("pkg:composer/.*")
def build_composer_repo_url(purl):
"""
Return a composer repo URL from the `purl` string.
"""
purl_data = PackageURL.from_string(purl)

name = purl_data.name
version = purl_data.version
namespace = purl_data.namespace

if name and version:
return f"https://packagist.org/packages/{namespace}/{name}#{version}"
elif name:
return f"https://packagist.org/packages/{namespace}/{name}"


@repo_router.route("pkg:nuget/.*")
def build_nuget_repo_url(purl):
"""
Expand Down
15 changes: 15 additions & 0 deletions src/packageurl/contrib/url2purl.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,21 @@ def build_pypi_purl(uri):
return purl_from_pattern("pypi", pypi_pattern, last_segment)


# https://packagist.org/packages/webmozart/assert#1.9.1
@purl_router.route("https?://packagist.org/packages/.*")
def build_composer_purl(uri):
# We use a more general route pattern instead of using `composer_pattern`
# below by itself because we want to capture all packagist download URLs,
# even the ones that are not completely formed. This helps prevent url2purl
# from attempting to create a generic PackageURL from an invalid packagist
# download URL.

# https://packagist.org/packages/ralouphie/getallheaders
# https://packagist.org/packages/symfony/process#v7.0.0-BETA3
composer_pattern = r"^https?://packagist\.org/packages/(?P<namespace>[^/]+)/(?P<name>[^\#]+?)(\#(?P<version>.+))?$"
return purl_from_pattern("composer", composer_pattern, uri)


# http://nuget.org/packages/EntityFramework/4.2.0.0
# https://www.nuget.org/api/v2/package/Newtonsoft.Json/11.0.1
nuget_www_pattern = r"^https?://.*nuget.org/(api/v2/)?packages?/(?P<name>.+)/(?P<version>.+)$"
Expand Down
3 changes: 3 additions & 0 deletions tests/contrib/data/url2purl.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@
"https://rubygems.org/downloads/unf-0.1.3.gem": "pkg:gem/[email protected]",
"https://rubygems.org/downloads/yajl-ruby-1.2.0.gem": "pkg:gem/[email protected]",
"https://rubygems.org/gems/i18n-js-3.0.11.gem": "pkg:gem/[email protected]",
"https://packagist.org/packages/webmozart/assert":"pkg:composer/webmozart/assert",
"https://packagist.org/packages/guzzlehttp/psr7#2.6.1":"pkg:composer/guzzlehttp/[email protected]",
"https://packagist.org/packages/symfony/process#v7.0.0-BETA3":"pkg:composer/symfony/[email protected]",
"https://pypi.org/packages/source/z/zc.recipe.egg/zc.recipe.egg-2.0.0.tar.gz": "pkg:pypi/[email protected]",
"https://pypi.org/project/widgetsnbextension": "pkg:pypi/widgetsnbextension",
"https://pypi.org/project/widgetsnbextension/3.0.7/": "pkg:pypi/[email protected]",
Expand Down
4 changes: 4 additions & 0 deletions tests/contrib/test_purl2url.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ def test_purl2url_get_repo_url():
"pkg:pypi/sortedcontainers": "https://pypi.org/project/sortedcontainers/",
"pkg:pypi/[email protected]": "https://pypi.org/project/sortedcontainers/2.4.0/",
"pkg:pypi/packageurl_python": "https://pypi.org/project/packageurl-python/",
"pkg:composer/psr/log": "https://packagist.org/packages/psr/log",
"pkg:composer/psr/[email protected]": "https://packagist.org/packages/psr/log#1.1.3",
"pkg:npm/is-npm": "https://www.npmjs.com/package/is-npm",
"pkg:npm/[email protected]": "https://www.npmjs.com/package/is-npm/v/1.0.0",
"pkg:nuget/System.Text.Json": "https://www.nuget.org/packages/System.Text.Json",
Expand Down Expand Up @@ -95,6 +97,7 @@ def test_purl2url_get_download_url():
"pkg:rubygems/package-name": None,
"pkg:bitbucket/birkenfeld": None,
"pkg:pypi/[email protected]": None,
"pkg:composer/psr/[email protected]": None,
"pkg:golang/xorm.io/[email protected]": None,
"pkg:golang/gopkg.in/[email protected]": None,
}
Expand Down Expand Up @@ -132,6 +135,7 @@ def test_purl2url_get_inferred_urls():
"https://gitlab.com/tg1999/firebase/-/archive/1a122122/firebase-1a122122.tar.gz",
],
"pkg:pypi/[email protected]": ["https://pypi.org/project/sortedcontainers/2.4.0/"],
"pkg:composer/psr/[email protected]": ["https://packagist.org/packages/psr/log#1.1.3"],
"pkg:rubygems/package-name": ["https://rubygems.org/gems/package-name"],
"pkg:bitbucket/birkenfeld": [],
}
Expand Down
12 changes: 12 additions & 0 deletions tests/data/test-suite-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@
"subpath": null,
"is_invalid": false
},
{
"description": "valid packagist purl",
"purl": "pkg:composer/guzzlehttp/[email protected]",
"canonical_purl": "pkg:composer/guzzlehttp/[email protected]",
"type": "composer",
"namespace": "guzzlehttp",
"name": "promises",
"version": "2.0.2",
"qualifiers": null,
"subpath": null,
"is_invalid": false
},
{
"description": "rpm often use qualifiers",
"purl": "pkg:Rpm/fedora/[email protected]?Arch=i386&Distro=fedora-25",
Expand Down
Loading