diff --git a/package_registry/github_tags.py b/package_registry/github_tags.py new file mode 100644 index 00000000..0bdec6a0 --- /dev/null +++ b/package_registry/github_tags.py @@ -0,0 +1,50 @@ +# fetchcode is a free software tool from nexB Inc. and others. +# Visit https://github.com/nexB/fetchcode for support and download. +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# http://nexb.com and http://aboutcode.org +# +# This software is licensed under the Apache License version 2.0. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: +# http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +import requests +from urllib.parse import urlparse + + +def build_url(url): + """ + Return a URL to access the list of tags using the GitHub API + """ + base_url='https://api.github.com/repos' + url_parts = urlparse(url) + path_parts = url_parts.path.split('/') + namespace = path_parts[1] + name = path_parts[2] + return '{}/{}/{}/tags'.format(base_url, namespace, name) + + +def get_tags(url): + """ + Return a list of git tags given the `url` to a Github repository + """ + + url_parts = urlparse(url) + + if not(url_parts.netloc == 'github.com'): + raise Exception('Not a GitHub URL') + + else: + final_url = build_url(url) + resp = requests.get(final_url) + tags = [] + for res in resp.json(): + if 'name' in res: + tags.append(res['name']) + return tags diff --git a/requirements.txt b/requirements.txt index 1e662359..c423d901 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,6 @@ importlib-metadata==1.5.0 more-itertools==8.2.0 packaging==20.1 pathlib2==2.3.5 -pkg-resources==0.0.0 pluggy==0.13.1 py==1.8.1 pyparsing==2.4.6 diff --git a/tests/data/gh_tags_response.json b/tests/data/gh_tags_response.json new file mode 100644 index 00000000..e4eb3fa2 --- /dev/null +++ b/tests/data/gh_tags_response.json @@ -0,0 +1,302 @@ +[ + { + "name": "v3.1.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v3.1.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v3.1.1", + "commit": { + "sha": "1af5ac8449cbb1ce98a0b461a6d9a5ad42a5d248", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/1af5ac8449cbb1ce98a0b461a6d9a5ad42a5d248" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djMuMS4x" + }, + { + "name": "v3.1.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v3.1.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v3.1.0", + "commit": { + "sha": "c697222cec7b7ef5a122bf9f64eeef5a4ede11f9", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/c697222cec7b7ef5a122bf9f64eeef5a4ede11f9" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djMuMS4w" + }, + { + "name": "v3.0.2", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v3.0.2", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v3.0.2", + "commit": { + "sha": "3f699d09f446a50a1021b5756df8b5c4485a55f0", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/3f699d09f446a50a1021b5756df8b5c4485a55f0" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djMuMC4y" + }, + { + "name": "v3.0.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v3.0.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v3.0.1", + "commit": { + "sha": "12dee4a50acd489965a81a3051d6f15e930cd485", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/12dee4a50acd489965a81a3051d6f15e930cd485" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djMuMC4x" + }, + { + "name": "v3.0.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v3.0.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v3.0.0", + "commit": { + "sha": "fba90b2f52361c2c099e1c2bed043d70b39d1743", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/fba90b2f52361c2c099e1c2bed043d70b39d1743" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djMuMC4w" + }, + { + "name": "v2.9.9", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.9", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.9", + "commit": { + "sha": "fd04833e3e9a1eeacc8e9945d677a4998b18854b", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/fd04833e3e9a1eeacc8e9945d677a4998b18854b" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS45" + }, + { + "name": "v2.9.8", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.8", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.8", + "commit": { + "sha": "a2fc22739372f6290499459f4843b2a9fe14952d", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/a2fc22739372f6290499459f4843b2a9fe14952d" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS44" + }, + { + "name": "v2.9.7", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.7", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.7", + "commit": { + "sha": "f4a832378ee2e65f6319d671161a13e47ed06fb7", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/f4a832378ee2e65f6319d671161a13e47ed06fb7" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS43" + }, + { + "name": "v2.9.6", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.6", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.6", + "commit": { + "sha": "f499e18ee62c28880b187670ffd1f9aefc51dc64", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/f499e18ee62c28880b187670ffd1f9aefc51dc64" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS42" + }, + { + "name": "v2.9.5", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.5", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.5", + "commit": { + "sha": "3be6be88683fe906ea928f17bfcfa24d9607454d", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/3be6be88683fe906ea928f17bfcfa24d9607454d" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS41" + }, + { + "name": "v2.9.4", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.4", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.4", + "commit": { + "sha": "d3bedeef80c03bb3fa486c262980eb108e49a342", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/d3bedeef80c03bb3fa486c262980eb108e49a342" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS40" + }, + { + "name": "v2.9.3", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.3", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.3", + "commit": { + "sha": "3f970b1e156442b869663b22e27aa8f9637c2c9e", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/3f970b1e156442b869663b22e27aa8f9637c2c9e" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS4z" + }, + { + "name": "v2.9.2", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.2", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.2", + "commit": { + "sha": "7e654ef927deed27334b15019254bf3b4be0efb4", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/7e654ef927deed27334b15019254bf3b4be0efb4" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS4y" + }, + { + "name": "v2.9.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.1", + "commit": { + "sha": "96cf70dcec8fb1dd1908c1a355dc369f8617059f", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/96cf70dcec8fb1dd1908c1a355dc369f8617059f" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS4x" + }, + { + "name": "v2.9.0b1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.9.0b1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.9.0b1", + "commit": { + "sha": "8ca9921f4be2c742926219348a1ef333a9d4304b", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/8ca9921f4be2c742926219348a1ef333a9d4304b" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuOS4wYjE=" + }, + { + "name": "v2.2.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.2.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.2.1", + "commit": { + "sha": "bd9a0c3e801d916a54ec77228ce1d0801cf7d374", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/bd9a0c3e801d916a54ec77228ce1d0801cf7d374" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMi4x" + }, + { + "name": "v2.2.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.2.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.2.0", + "commit": { + "sha": "b981c3f912438b037a330a6f804e1935d1176c46", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/b981c3f912438b037a330a6f804e1935d1176c46" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMi4w" + }, + { + "name": "v2.1.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.1.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.1.0", + "commit": { + "sha": "2d6d9045a4a87331835340d37bd63813c2f9dea6", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/2d6d9045a4a87331835340d37bd63813c2f9dea6" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMS4w" + }, + { + "name": "v2.0.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.0.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.0.1", + "commit": { + "sha": "1960ffcf27e14f0f7163a4d541e377509a4092f8", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/1960ffcf27e14f0f7163a4d541e377509a4092f8" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMC4x" + }, + { + "name": "v2.0.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.0.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.0.0", + "commit": { + "sha": "92e16663ced395af16a988c42cadebf4c738defa", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/92e16663ced395af16a988c42cadebf4c738defa" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMC4w" + }, + { + "name": "v2.0.0.rc3", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.0.0.rc3", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.0.0.rc3", + "commit": { + "sha": "89f9dee91bbb377479681cb2cf22c7994c38ded5", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/89f9dee91bbb377479681cb2cf22c7994c38ded5" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMC4wLnJjMw==" + }, + { + "name": "v2.0.0.rc2", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.0.0.rc2", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.0.0.rc2", + "commit": { + "sha": "eeb6f2734b8ec90956b675a13b23d90be9a8e312", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/eeb6f2734b8ec90956b675a13b23d90be9a8e312" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMC4wLnJjMg==" + }, + { + "name": "v2.0.0.rc1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v2.0.0.rc1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v2.0.0.rc1", + "commit": { + "sha": "7a57e44bece5ad0385e6b84371be33e9674fd6ef", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/7a57e44bece5ad0385e6b84371be33e9674fd6ef" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djIuMC4wLnJjMQ==" + }, + { + "name": "v1.6.3", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.6.3", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.6.3", + "commit": { + "sha": "2e271bab84ae787df9aa944cebf7ad945401e4c5", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/2e271bab84ae787df9aa944cebf7ad945401e4c5" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNi4z" + }, + { + "name": "v1.6.2", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.6.2", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.6.2", + "commit": { + "sha": "91b8f0fd6f145468bd2ec573c1d38e23c29d2f3a", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/91b8f0fd6f145468bd2ec573c1d38e23c29d2f3a" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNi4y" + }, + { + "name": "v1.6.1", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.6.1", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.6.1", + "commit": { + "sha": "10eea0cad9f6e389a54094e6cc77ec585ba9fa8a", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/10eea0cad9f6e389a54094e6cc77ec585ba9fa8a" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNi4x" + }, + { + "name": "v1.6.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.6.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.6.0", + "commit": { + "sha": "d0926424ce9c31e240a96f4ef6a3c744c5b42c82", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/d0926424ce9c31e240a96f4ef6a3c744c5b42c82" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNi4w" + }, + { + "name": "v1.5.0", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.5.0", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.5.0", + "commit": { + "sha": "070f611263154dec7ac000cb86257728d2fb5647", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/070f611263154dec7ac000cb86257728d2fb5647" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNS4w" + }, + { + "name": "v1.4.3", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.4.3", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.4.3", + "commit": { + "sha": "0844aee2d6b4210d9c68d621e1a243837e167a87", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/0844aee2d6b4210d9c68d621e1a243837e167a87" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNC4z" + }, + { + "name": "v1.4.2", + "zipball_url": "https://api.github.com/repos/nexB/scancode-toolkit/zipball/v1.4.2", + "tarball_url": "https://api.github.com/repos/nexB/scancode-toolkit/tarball/v1.4.2", + "commit": { + "sha": "0feda39a57f0d121302127411994e63b1db2bfa3", + "url": "https://api.github.com/repos/nexB/scancode-toolkit/commits/0feda39a57f0d121302127411994e63b1db2bfa3" + }, + "node_id": "MDM6UmVmMzgzNzMzMzg6djEuNC4y" + } + ] \ No newline at end of file diff --git a/tests/test_github_tags.py b/tests/test_github_tags.py new file mode 100644 index 00000000..ba7a23e7 --- /dev/null +++ b/tests/test_github_tags.py @@ -0,0 +1,52 @@ +# fetchcode is a free software tool from nexB Inc. and others. +# Visit https://github.com/nexB/fetchcode for support and download. +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# http://nexb.com and http://aboutcode.org +# +# This software is licensed under the Apache License version 2.0. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: +# http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +import json +from unittest import mock + +from package_registry import github_tags + + +@mock.patch('package_registry.github_tags.requests.get') +def test_github_tags_for_not_empty_list(mock_get): + url = 'https://github.com/nexb/scancode-toolkit' + with open('tests/data/gh_tags_response.json') as file: + data = file.read() + mock_get.return_value.json.return_value = json.loads(data) + response = github_tags.get_tags(url=url) + tags = ['v3.1.1', 'v3.1.0', 'v3.0.2', 'v3.0.1', 'v3.0.0', 'v2.9.9', 'v2.9.8', 'v2.9.7', 'v2.9.6', 'v2.9.5', 'v2.9.4', 'v2.9.3', 'v2.9.2', 'v2.9.1', 'v2.9.0b1', 'v2.2.1', 'v2.2.0', 'v2.1.0', 'v2.0.1', 'v2.0.0', 'v2.0.0.rc3', 'v2.0.0.rc2', 'v2.0.0.rc1', 'v1.6.3', 'v1.6.2', 'v1.6.1', 'v1.6.0', 'v1.5.0', 'v1.4.3', 'v1.4.2'] + for tag in tags: + assert tag in response + assert 'v5.0.1' not in response + +@mock.patch('package_registry.github_tags.requests.get') +def test_github_tags_for_empty_list(mock_get): + mock_get.return_value.json.return_value=[] + url = 'https://github.com/nexb/fetchcode' + response = github_tags.get_tags(url=url) + assert 0 == len(response) + +def test_build_url_with_conventional_URL(): + url = 'https://github.com/nexb/fetchcode' + excepted = 'https://api.github.com/repos/nexb/fetchcode/tags' + final_url = github_tags.build_url(url) + assert excepted == final_url + +def test_build_url_with_unconventional_URL(): + url = 'https://github.com/nexB/fetchcode/tree/master' + excepted = 'https://api.github.com/repos/nexB/fetchcode/tags' + final_url = github_tags.build_url(url) + assert excepted == final_url