44# SPDX-License-Identifier: Apache-2.0
55import logging
66import re
7+ import requests
8+ from npm .bindings import npm_run
9+ from lastversion import latest
710from bs4 import BeautifulSoup
811from urllib .request import urlopen
912import fosslight_util .constant as constant
10- from npm .bindings import npm_run
1113
1214logger = logging .getLogger (constant .LOGGER_NAME )
1315
1416
17+ def extract_name_version_from_link (link ):
18+ # Github : https://github.com/(owner)/(repo)
19+ # npm : https://www.npmjs.com/package/(package)/v/(version)
20+ # npm2 : https://www.npmjs.com/package/@(group)/(package)/v/(version)
21+ # pypi : https://pypi.org/project/(oss_name)/(version)
22+ # pypi2 : https://files.pythonhosted.org/packages/source/(alphabet)/(oss_name)/(oss_name)-(version).tar.gz
23+ # Maven: https://mvnrepository.com/artifact/(group)/(artifact)/(version)
24+ # pub: https://pub.dev/packages/(package)/versions/(version)
25+ # Cocoapods: https://cocoapods.org/(package)
26+ pkg_pattern = {
27+ "pypi" : r'https?:\/\/pypi\.org\/project\/([^\/]+)[\/]?([^\/]*)' ,
28+ "pypi2" : r'https?:\/\/files\.pythonhosted\.org\/packages\/source\/[\w]\/([^\/]+)\/[\S]+-([^\-]+)\.tar\.gz' ,
29+ "maven" : r'https?:\/\/mvnrepository\.com\/artifact\/([^\/]+)\/([^\/]+)\/?([^\/]*)' ,
30+ "npm" : r'https?:\/\/www\.npmjs\.com\/package\/([^\/\@]+)(?:\/v\/)?([^\/]*)' ,
31+ "npm2" : r'https?:\/\/www\.npmjs\.com\/package\/(\@[^\/]+\/[^\/]+)(?:\/v\/)?([^\/]*)' ,
32+ "pub" : r'https?:\/\/pub\.dev\/packages\/([^\/]+)(?:\/versions\/)?([^\/]*)' ,
33+ "pods" : r'https?:\/\/cocoapods\.org\/pods\/([^\/]+)'
34+ }
35+ oss_name = ""
36+ oss_version = ""
37+ if link .startswith ("www." ):
38+ link = link .replace ("www." , "https://www." , 1 )
39+ for key , value in pkg_pattern .items ():
40+ p = re .compile (value )
41+ match = p .match (link )
42+ if match :
43+ try :
44+ origin_name = match .group (1 )
45+ if (key == "pypi" ) or (key == "pypi2" ):
46+ oss_name = f"pypi:{ origin_name } "
47+ oss_name = re .sub (r"[-_.]+" , "-" , oss_name ).lower ()
48+ oss_version = match .group (2 )
49+ elif key == "maven" :
50+ artifact = match .group (2 )
51+ oss_name = f"{ origin_name } :{ artifact } "
52+ origin_name = oss_name
53+ oss_version = match .group (3 )
54+ elif key == "npm" or key == "npm2" :
55+ oss_name = f"npm:{ origin_name } "
56+ oss_version = match .group (2 )
57+ elif key == "pub" :
58+ oss_name = f"pub:{ origin_name } "
59+ oss_version = match .group (2 )
60+ elif key == "pods" :
61+ oss_name = f"cocoapods:{ origin_name } "
62+ except Exception as ex :
63+ logger .info (f"extract_name_version_from_link { key } :{ ex } " )
64+ if oss_name and (not oss_version ):
65+ if key in ["pypi" , "maven" , "npm" , "npm2" , "pub" ]:
66+ oss_version , link = get_latest_package_version (link , key , origin_name )
67+ logger .debug (f'Try to download with the latest version:{ link } ' )
68+ break
69+ return oss_name , oss_version , link , key
70+
71+
72+ def get_latest_package_version (link , pkg_type , oss_name ):
73+ find_version = ''
74+ link_with_version = link
75+
76+ try :
77+ if pkg_type in ['npm' , 'npm2' ]:
78+ stderr , stdout = npm_run ('view' , oss_name , 'version' )
79+ if stdout :
80+ find_version = stdout .strip ()
81+ link_with_version = f'https://www.npmjs.com/package/{ oss_name } /v/{ find_version } '
82+ elif pkg_type == 'pypi' :
83+ find_version = str (latest (oss_name , at = 'pip' , output_format = 'version' , pre_ok = True ))
84+ link_with_version = f'https://pypi.org/project/{ oss_name } /{ find_version } '
85+ elif pkg_type == 'maven' :
86+ maven_response = requests .get (f'https://api.deps.dev/v3alpha/systems/maven/packages/{ oss_name } ' )
87+ if maven_response .status_code == 200 :
88+ find_version = maven_response .json ().get ('versions' )[- 1 ].get ('versionKey' ).get ('version' )
89+ oss_name = oss_name .replace (':' , '/' )
90+ link_with_version = f'https://mvnrepository.com/artifact/{ oss_name } /{ find_version } '
91+ elif pkg_type == 'pub' :
92+ pub_response = requests .get (f'https://pub.dev/api/packages/{ oss_name } ' )
93+ if pub_response .status_code == 200 :
94+ find_version = pub_response .json ().get ('latest' ).get ('version' )
95+ link_with_version = f'https://pub.dev/packages/{ oss_name } /versions/{ find_version } '
96+ except Exception as e :
97+ logger .debug (f'Fail to get latest package version({ link } :{ e } )' )
98+ return find_version , link_with_version
99+
100+
15101def get_downloadable_url (link ):
16102
17103 ret = False
18- new_link = ''
104+ result_link = link
19105
20- link = link .replace ('http://' , '' )
21- link = link .replace ('https://' , '' )
106+ oss_name , oss_version , new_link , pkg_type = extract_name_version_from_link (link )
107+ new_link = new_link .replace ('http://' , '' )
108+ new_link = new_link .replace ('https://' , '' )
22109
23- if link . startswith ( ' pypi.org/' ) :
24- ret , new_link = get_download_location_for_pypi (link )
25- elif link . startswith ( 'mvnrepository.com/artifact/' ) or link .startswith ('repo1.maven.org/' ):
26- ret , new_link = get_download_location_for_maven (link )
27- elif link . startswith ( 'www.npmjs.com/' ) or link .startswith ('registry.npmjs.org/' ):
28- ret , new_link = get_download_location_for_npm (link )
29- elif link . startswith ( ' pub.dev/' ) :
30- ret , new_link = get_download_location_for_pub (link )
110+ if pkg_type == " pypi" :
111+ ret , result_link = get_download_location_for_pypi (new_link )
112+ elif pkg_type == "maven" or new_link .startswith ('repo1.maven.org/' ):
113+ ret , result_link = get_download_location_for_maven (new_link )
114+ elif ( pkg_type in [ "npm" , "npm2" ] ) or new_link .startswith ('registry.npmjs.org/' ):
115+ ret , result_link = get_download_location_for_npm (new_link )
116+ elif pkg_type == " pub" :
117+ ret , result_link = get_download_location_for_pub (new_link )
31118
32- return ret , new_link
119+ return ret , result_link , oss_name , oss_version
33120
34121
35122def get_download_location_for_pypi (link ):
@@ -134,16 +221,9 @@ def get_download_location_for_npm(link):
134221 oss_name_npm = dn_loc_split [idx ]
135222 tar_name = oss_name_npm
136223 oss_version = dn_loc_split [idx + 2 ]
137- except Exception :
138- pass
139224
140- try :
141- if not oss_version :
142- stderr , stdout = npm_run ('view' , oss_name_npm , 'version' )
143- if stdout :
144- oss_version = stdout .strip ()
145- tar_name = f"{ tar_name } -{ oss_version } "
146- new_link = 'https://registry.npmjs.org/' + oss_name_npm + '/-/' + tar_name + '.tgz'
225+ tar_name = f'{ tar_name } -{ oss_version } '
226+ new_link = f'https://registry.npmjs.org/{ oss_name_npm } /-/{ tar_name } .tgz'
147227 ret = True
148228 except Exception as error :
149229 ret = False
@@ -159,7 +239,7 @@ def get_download_location_for_pub(link):
159239 # download url format : https://pub.dev/packages/(oss_name)/versions/(oss_version).tar.gz
160240 try :
161241 if link .startswith ('pub.dev/packages' ):
162- new_link = 'https://{link}.tar.gz'
242+ new_link = f 'https://{ link } .tar.gz'
163243 ret = True
164244
165245 except Exception as error :
0 commit comments