Skip to content

Commit

Permalink
Add support for Composer in purl2url (#144)
Browse files Browse the repository at this point in the history
Signed-off-by: Camille Moulin <[email protected]>
  • Loading branch information
camillem authored Mar 18, 2024
1 parent a46d424 commit ea4ad00
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/packageurl/contrib/purl2url.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,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 @@ -340,6 +340,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

0 comments on commit ea4ad00

Please sign in to comment.