diff --git a/fetchcode/package.py b/fetchcode/package.py index 4469b690..92f8e16c 100644 --- a/fetchcode/package.py +++ b/fetchcode/package.py @@ -327,3 +327,29 @@ def get_rubygems_data_from_purl(purl): download_url=download_url, **purl.to_dict(), ) + + +@router.route("pkg:homebrew/.*") +def get_homebrew_data_from_purl(purl): + """ + Generate `Package` object from the `purl` string of rubygems type + """ + purl = PackageURL.from_string(purl) + name = purl.name + base_path = "https://formulae.brew.sh/api/formula" + api_url = f"{base_path}/{name}.json" + response = get_response(api_url) + declared_license = response.get("license") + homepage_url = response.get("homepage") + versions = response.get("versions") or {} + version = versions.get("stable") + urls = response.get("urls") or {{}} + stable_url = urls.get("stable") or {} + download_url = stable_url.get("url") + yield Package( + homepage_url=homepage_url, + api_url=api_url, + declared_license=declared_license, + download_url=download_url, + **purl.to_dict(), + ) diff --git a/tests/data/homebrew.json b/tests/data/homebrew.json new file mode 100644 index 00000000..3dc69e0b --- /dev/null +++ b/tests/data/homebrew.json @@ -0,0 +1,38 @@ +{ + "0": { + "type": "homebrew", + "namespace": null, + "name": "node", + "version": null, + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": "https://nodejs.org/", + "download_url": "https://nodejs.org/dist/v14.13.1/node-v14.13.1.tar.gz", + "api_url": "https://formulae.brew.sh/api/formula/node.json", + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "license_expression": null, + "declared_license": "MIT", + "notice_text": null, + "root_path": null, + "dependencies": [], + "contains_source_code": null, + "source_packages": [], + "purl": "pkg:homebrew/node", + "repository_homepage_url": null, + "repository_download_url": null, + "api_data_url": null + } +} \ No newline at end of file diff --git a/tests/data/homebrew_mock_data.json b/tests/data/homebrew_mock_data.json new file mode 100644 index 00000000..963ec329 --- /dev/null +++ b/tests/data/homebrew_mock_data.json @@ -0,0 +1,124 @@ +{ + "name": "node", + "full_name": "node", + "oldname": null, + "aliases": [ + "node.js", + "node@14", + "nodejs", + "npm" + ], + "versioned_formulae": [ + "node@12", + "node@10" + ], + "desc": "Platform built on V8 to build network applications", + "license": "MIT", + "homepage": "https://nodejs.org/", + "versions": { + "stable": "14.13.1", + "head": "HEAD", + "bottle": true + }, + "urls": { + "stable": { + "url": "https://nodejs.org/dist/v14.13.1/node-v14.13.1.tar.gz", + "tag": null, + "revision": null + } + }, + "revision": 0, + "version_scheme": 0, + "bottle": { + "stable": { + "rebuild": 0, + "cellar": ":any", + "prefix": "/usr/local", + "root_url": "https://homebrew.bintray.com/bottles", + "files": { + "catalina": { + "url": "https://homebrew.bintray.com/bottles/node-14.13.1.catalina.bottle.tar.gz", + "sha256": "c5574d926c10ecb8a18faa551f6a15c362512134577110c2678d52db3382ba42" + }, + "mojave": { + "url": "https://homebrew.bintray.com/bottles/node-14.13.1.mojave.bottle.tar.gz", + "sha256": "3d42a543356788cb20a3cd91306e9e533c2939b7609c3dc91ffdd405fab1b25f" + }, + "high_sierra": { + "url": "https://homebrew.bintray.com/bottles/node-14.13.1.high_sierra.bottle.tar.gz", + "sha256": "8c9d9dd8a341bd74aec4e8ba1a8abb8ba92e137d771290613676798f0b4a61ba" + } + } + } + }, + "keg_only": false, + "bottle_disabled": false, + "options": [], + "build_dependencies": [ + "pkg-config", + "python@3.8" + ], + "dependencies": [ + "icu4c" + ], + "recommended_dependencies": [], + "optional_dependencies": [], + "uses_from_macos": [], + "requirements": [], + "conflicts_with": [], + "caveats": null, + "installed": [], + "linked_keg": null, + "pinned": false, + "outdated": false, + "deprecated": false, + "disabled": false, + "analytics": { + "install": { + "30d": { + "node": 405637, + "node --HEAD": 44, + "node --with-full-icu": 1, + "node --without-npm": 1 + }, + "90d": { + "node": 1074821, + "node --HEAD": 117, + "node --without-npm": 3, + "Node": 1, + "node --with-full-icu": 1 + }, + "365d": { + "node": 4314220, + "node --HEAD": 617, + "node --without-npm": 29, + "node --without-icu4c": 13, + "node --with-openssl@1.1": 6 + } + }, + "install_on_request": { + "30d": { + "node": 294250, + "node --HEAD": 15 + }, + "90d": { + "node": 787407, + "node --HEAD": 52, + "Node": 1 + }, + "365d": { + "node": 3134446, + "node --HEAD": 343, + "node --without-icu4c": 13, + "node --without-npm": 9, + "node --with-openssl@1.1": 6 + } + }, + "build_error": { + "30d": { + "node": 0 + } + } + }, + "generated_date": "2020-10-11" +} diff --git a/tests/test_package.py b/tests/test_package.py index 64b12337..f97300c2 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -97,3 +97,13 @@ def test_rubygems_packages(mock_get): mock_get.side_effect = side_effect packages = list(info(purl)) match_data(packages, expected_data) + + +@mock.patch("fetchcode.package.get_response") +def test_homebrew_packages(mock_get): + side_effect = [file_data("tests/data/homebrew_mock_data.json")] + purl = "pkg:homebrew/node" + expected_data = file_data("tests/data/homebrew.json") + mock_get.side_effect = side_effect + packages = list(info(purl)) + match_data(packages, expected_data)