fosslight-dependency 4.1.19__tar.gz → 4.1.21__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/PKG-INFO +9 -2
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/README.md +8 -1
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/setup.py +1 -1
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/_analyze_dependency.py +3 -3
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/_help.py +3 -1
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/_package_manager.py +2 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/constant.py +1 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Npm.py +16 -10
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Pypi.py +96 -94
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/run_dependency_scanner.py +99 -59
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/PKG-INFO +9 -2
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/LICENSE +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/LICENSES/Apache-2.0.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/LICENSES/MIT.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/MANIFEST.in +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/requirements.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/setup.cfg +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/LICENSES/LICENSE +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/LICENSES/LicenseRef-3rd_party_licenses.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/__init__.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/_graph_convertor.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/dependency_item.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Android.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Cargo.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Carthage.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Cocoapods.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Go.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Gradle.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Helm.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Maven.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Nuget.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Pnpm.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Pub.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Swift.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/Unity.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/package_manager/__init__.py +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/SOURCES.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/dependency_links.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/entry_points.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/requires.txt +0 -0
- {fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fosslight_dependency
|
3
|
-
Version: 4.1.
|
3
|
+
Version: 4.1.21
|
4
4
|
Summary: FOSSLight Dependency Scanner
|
5
5
|
Home-page: https://github.com/fosslight/fosslight_dependency_scanner
|
6
6
|
Download-URL: https://github.com/fosslight/fosslight_dependency_scanner
|
@@ -51,7 +51,7 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
51
51
|
</thead>
|
52
52
|
<tbody>
|
53
53
|
<tr>
|
54
|
-
<td rowspan="
|
54
|
+
<td rowspan="3">Javascript</td>
|
55
55
|
<td>Npm</td>
|
56
56
|
<td>package.json</td>
|
57
57
|
<td>O</td>
|
@@ -64,6 +64,13 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
64
64
|
<td>O</td>
|
65
65
|
<td>O</td>
|
66
66
|
<td>O</td>
|
67
|
+
</tr>
|
68
|
+
<tr>
|
69
|
+
<td>Yarn</td>
|
70
|
+
<td>package.json</td>
|
71
|
+
<td>O</td>
|
72
|
+
<td>O</td>
|
73
|
+
<td>O</td>
|
67
74
|
</tr>
|
68
75
|
<tr>
|
69
76
|
<td rowspan="2">Java</td>
|
@@ -31,7 +31,7 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
31
31
|
</thead>
|
32
32
|
<tbody>
|
33
33
|
<tr>
|
34
|
-
<td rowspan="
|
34
|
+
<td rowspan="3">Javascript</td>
|
35
35
|
<td>Npm</td>
|
36
36
|
<td>package.json</td>
|
37
37
|
<td>O</td>
|
@@ -44,6 +44,13 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
44
44
|
<td>O</td>
|
45
45
|
<td>O</td>
|
46
46
|
<td>O</td>
|
47
|
+
</tr>
|
48
|
+
<tr>
|
49
|
+
<td>Yarn</td>
|
50
|
+
<td>package.json</td>
|
51
|
+
<td>O</td>
|
52
|
+
<td>O</td>
|
53
|
+
<td>O</td>
|
47
54
|
</tr>
|
48
55
|
<tr>
|
49
56
|
<td rowspan="2">Java</td>
|
@@ -35,7 +35,7 @@ def analyze_dependency(package_manager_name, input_dir, output_dir, pip_activate
|
|
35
35
|
|
36
36
|
if package_manager_name == const.PYPI:
|
37
37
|
package_manager = Pypi(input_dir, output_dir, pip_activate_cmd, pip_deactivate_cmd)
|
38
|
-
elif package_manager_name == const.NPM:
|
38
|
+
elif package_manager_name == const.NPM or package_manager_name == const.YARN:
|
39
39
|
package_manager = Npm(input_dir, output_dir)
|
40
40
|
elif package_manager_name == const.MAVEN:
|
41
41
|
package_manager = Maven(input_dir, output_dir, output_custom_dir)
|
@@ -92,11 +92,11 @@ def analyze_dependency(package_manager_name, input_dir, output_dir, pip_activate
|
|
92
92
|
package_manager.parse_oss_information_for_pnpm()
|
93
93
|
package_dep_item_list.extend(package_manager.dep_items)
|
94
94
|
if ret:
|
95
|
-
logger.warning(f"### Complete to analyze: {package_manager_name}")
|
95
|
+
logger.warning(f"### Complete to analyze: {package_manager_name}({input_dir}: {','.join(manifest_file_name)})")
|
96
96
|
if package_manager.cover_comment:
|
97
97
|
cover_comment = package_manager.cover_comment
|
98
98
|
else:
|
99
|
-
logger.error(f"### Fail to analyze: {package_manager_name}")
|
99
|
+
logger.error(f"### Fail to analyze: {package_manager_name}({input_dir}: {','.join(manifest_file_name)})")
|
100
100
|
|
101
101
|
del package_manager
|
102
102
|
|
{fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/_help.py
RENAMED
@@ -16,6 +16,7 @@ _HELP_MESSAGE_DEPENDENCY = """
|
|
16
16
|
Maven (Java)
|
17
17
|
NPM (Node.js)
|
18
18
|
PNPM (Node.js)
|
19
|
+
Yarn (Node.js)
|
19
20
|
PIP (Python)
|
20
21
|
Pub (Dart with flutter)
|
21
22
|
Cocoapods (Swift/Obj-C)
|
@@ -33,7 +34,7 @@ _HELP_MESSAGE_DEPENDENCY = """
|
|
33
34
|
-v\t\t\t\t Print the version of the script.
|
34
35
|
-m <package_manager>\t Enter the package manager.
|
35
36
|
\t(npm, maven, gradle, pypi, pub, cocoapods, android, swift, carthage,
|
36
|
-
\t go, nuget, helm, unity, cargo, pnpm)
|
37
|
+
\t go, nuget, helm, unity, cargo, pnpm, yarn)
|
37
38
|
-p <input_path>\t\t Enter the path where the script will be run.
|
38
39
|
-e <exclude_path>\t\t Enter the path where the analysis will not be performed.
|
39
40
|
-o <output_path>\t\t Output path
|
@@ -46,6 +47,7 @@ _HELP_MESSAGE_DEPENDENCY = """
|
|
46
47
|
\t\t\t\t\t--graph-path option is required
|
47
48
|
--direct\t\t\t Print the direct/transitive dependency type in comment.
|
48
49
|
\t\tChoice 'True' or 'False'. (default:True)
|
50
|
+
-r\t\t\t\t Recursive mode. Scan all subdirectories for manifest files.
|
49
51
|
--notice\t\t\t Print the open source license notice text.
|
50
52
|
|
51
53
|
Required only for swift, carthage
|
@@ -108,6 +108,7 @@ class PackageManager:
|
|
108
108
|
cmd_gradle = "./gradlew"
|
109
109
|
else:
|
110
110
|
ret_task = False
|
111
|
+
self.set_direct_dependencies(False)
|
111
112
|
logger.warning('No gradlew file exists (Skip to find dependencies relationship.).')
|
112
113
|
if ret_plugin:
|
113
114
|
logger.warning('Also it cannot run android-dependency-scanning plugin.')
|
@@ -153,6 +154,7 @@ class PackageManager:
|
|
153
154
|
shutil.move(module_gradle_backup, module_build_gradle)
|
154
155
|
if os.path.isfile(self.input_file_name):
|
155
156
|
logger.info(f'Found {self.input_file_name}, skip to run plugin.')
|
157
|
+
self.set_direct_dependencies(False)
|
156
158
|
ret_task = True
|
157
159
|
return ret_task
|
158
160
|
|
@@ -31,12 +31,12 @@ class Npm(PackageManager):
|
|
31
31
|
super().__init__(self.package_manager_name, self.dn_url, input_dir, output_dir)
|
32
32
|
|
33
33
|
def __del__(self):
|
34
|
-
if os.path.isfile(self.input_file_name):
|
35
|
-
os.remove(self.input_file_name)
|
34
|
+
if os.path.isfile(os.path.join(self.input_dir, self.input_file_name)):
|
35
|
+
os.remove(os.path.join(self.input_dir, self.input_file_name))
|
36
36
|
if self.flag_tmp_node_modules:
|
37
|
-
shutil.rmtree(node_modules, ignore_errors=True)
|
38
|
-
if os.path.exists(self.tmp_custom_json):
|
39
|
-
os.remove(self.tmp_custom_json)
|
37
|
+
shutil.rmtree(os.path.join(self.input_dir, node_modules), ignore_errors=True)
|
38
|
+
if os.path.exists(os.path.join(self.input_dir, self.tmp_custom_json)):
|
39
|
+
os.remove(os.path.join(self.input_dir, self.tmp_custom_json))
|
40
40
|
|
41
41
|
def run_plugin(self):
|
42
42
|
ret = self.start_license_checker()
|
@@ -53,8 +53,14 @@ class Npm(PackageManager):
|
|
53
53
|
self.flag_tmp_node_modules = True
|
54
54
|
cmd_ret = subprocess.call(npm_install_cmd, shell=True)
|
55
55
|
if cmd_ret != 0:
|
56
|
-
logger.
|
57
|
-
|
56
|
+
logger.warning(f"{npm_install_cmd} returns an error. Trying yarn as fallback...")
|
57
|
+
yarn_install_cmd = 'yarn install --production --ignore-scripts'
|
58
|
+
cmd_ret = subprocess.call(yarn_install_cmd, shell=True)
|
59
|
+
if cmd_ret != 0:
|
60
|
+
logger.error(f"Both {npm_install_cmd} and {yarn_install_cmd} failed")
|
61
|
+
return False
|
62
|
+
else:
|
63
|
+
logger.info(f"Successfully executed {yarn_install_cmd}")
|
58
64
|
|
59
65
|
# customized json file for obtaining specific items with license-checker
|
60
66
|
self.make_custom_json(self.tmp_custom_json)
|
@@ -122,9 +128,9 @@ class Npm(PackageManager):
|
|
122
128
|
if len(rel_json) < 1:
|
123
129
|
ret = False
|
124
130
|
else:
|
125
|
-
self.package_name = f'{rel_json[_name]}({rel_json
|
131
|
+
self.package_name = f'{rel_json[_name]}({rel_json.get(_version, "")})'
|
126
132
|
if _dependencies in rel_json:
|
127
|
-
self.parse_rel_dependencies(rel_json[_name], rel_json
|
133
|
+
self.parse_rel_dependencies(rel_json[_name], rel_json.get(_version, ""), rel_json[_dependencies])
|
128
134
|
except Exception as e:
|
129
135
|
ret = False
|
130
136
|
err_msg = e
|
@@ -178,7 +184,7 @@ class Npm(PackageManager):
|
|
178
184
|
|
179
185
|
oss_item.download_location = f"{self.dn_url}{oss_init_name}/v/{oss_item.version}"
|
180
186
|
dn_loc = f"{self.dn_url}{oss_init_name}"
|
181
|
-
dep_item.purl = get_url_to_purl(
|
187
|
+
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name)
|
182
188
|
purl_dict[f'{oss_init_name}({oss_item.version})'] = dep_item.purl
|
183
189
|
if d[_repository]:
|
184
190
|
dn_loc = d[_repository]
|
@@ -13,7 +13,7 @@ import re
|
|
13
13
|
import fosslight_util.constant as constant
|
14
14
|
import fosslight_dependency.constant as const
|
15
15
|
from fosslight_dependency._package_manager import PackageManager
|
16
|
-
from fosslight_dependency._package_manager import
|
16
|
+
from fosslight_dependency._package_manager import get_url_to_purl, check_license_name
|
17
17
|
from fosslight_dependency.dependency_item import DependencyItem, change_dependson_to_purl
|
18
18
|
from fosslight_util.oss_item import OssItem
|
19
19
|
|
@@ -26,7 +26,6 @@ class Pypi(PackageManager):
|
|
26
26
|
dn_url = 'https://pypi.org/project/'
|
27
27
|
venv_tmp_dir = 'venv_osc_dep_tmp'
|
28
28
|
tmp_file_name = "tmp_pip_license_output.json"
|
29
|
-
tmp_pip_license_info_file_name = "tmp_pip_license_info_output.json"
|
30
29
|
tmp_deptree_file = "tmp_pipdeptree.json"
|
31
30
|
pip_activate_cmd = ''
|
32
31
|
pip_deactivate_cmd = ''
|
@@ -41,9 +40,6 @@ class Pypi(PackageManager):
|
|
41
40
|
if os.path.isfile(self.tmp_file_name):
|
42
41
|
os.remove(self.tmp_file_name)
|
43
42
|
|
44
|
-
if os.path.isfile(self.tmp_pip_license_info_file_name):
|
45
|
-
os.remove(self.tmp_pip_license_info_file_name)
|
46
|
-
|
47
43
|
shutil.rmtree(self.venv_tmp_dir, ignore_errors=True)
|
48
44
|
|
49
45
|
if os.path.isfile(self.tmp_deptree_file):
|
@@ -73,7 +69,7 @@ class Pypi(PackageManager):
|
|
73
69
|
ret = self.create_virtualenv()
|
74
70
|
|
75
71
|
if ret:
|
76
|
-
ret = self.
|
72
|
+
ret = self.start_pip_inspect()
|
77
73
|
|
78
74
|
return ret
|
79
75
|
|
@@ -103,7 +99,7 @@ class Pypi(PackageManager):
|
|
103
99
|
activate_cmd = os.path.join(self.venv_tmp_dir, "Scripts", "activate.bat")
|
104
100
|
cmd_separator = "&"
|
105
101
|
else:
|
106
|
-
create_venv_cmd = f"
|
102
|
+
create_venv_cmd = f"virtualenv -p python3 {self.venv_tmp_dir}"
|
107
103
|
activate_cmd = ". " + os.path.join(venv_path, "bin", "activate")
|
108
104
|
cmd_separator = ";"
|
109
105
|
|
@@ -117,11 +113,12 @@ class Pypi(PackageManager):
|
|
117
113
|
return False
|
118
114
|
|
119
115
|
deactivate_cmd = "deactivate"
|
116
|
+
pip_upgrade_cmd = "pip install --upgrade pip"
|
120
117
|
|
121
118
|
self.set_pip_activate_cmd(activate_cmd)
|
122
119
|
self.set_pip_deactivate_cmd(deactivate_cmd)
|
123
120
|
|
124
|
-
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, deactivate_cmd]
|
121
|
+
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, pip_upgrade_cmd, deactivate_cmd]
|
125
122
|
cmd = cmd_separator.join(cmd_list)
|
126
123
|
|
127
124
|
try:
|
@@ -139,9 +136,9 @@ class Pypi(PackageManager):
|
|
139
136
|
try:
|
140
137
|
if (not ret) and (self.platform != const.WINDOWS):
|
141
138
|
ret = True
|
142
|
-
create_venv_cmd = f"
|
139
|
+
create_venv_cmd = f"python3 -m venv {self.venv_tmp_dir}"
|
143
140
|
|
144
|
-
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, deactivate_cmd]
|
141
|
+
cmd_list = [create_venv_cmd, activate_cmd, install_cmd, pip_upgrade_cmd, deactivate_cmd]
|
145
142
|
cmd = cmd_separator.join(cmd_list)
|
146
143
|
cmd_ret = subprocess.run(cmd, shell=True, stderr=subprocess.PIPE)
|
147
144
|
if cmd_ret.returncode != 0:
|
@@ -160,14 +157,9 @@ class Pypi(PackageManager):
|
|
160
157
|
|
161
158
|
return ret
|
162
159
|
|
163
|
-
def
|
160
|
+
def start_pip_inspect(self):
|
164
161
|
ret = True
|
165
|
-
pip_licenses = 'pip-licenses'
|
166
|
-
prettytable = 'prettytable'
|
167
|
-
wcwidth = 'wcwidth'
|
168
162
|
pipdeptree = 'pipdeptree'
|
169
|
-
pip_licenses_default_options = ' --from=mixed --with-url --format=json --with-license-file'
|
170
|
-
pip_licenses_system_option = ' --with-system -p '
|
171
163
|
tmp_pip_list = "tmp_list.txt"
|
172
164
|
python_cmd = "python -m"
|
173
165
|
|
@@ -193,11 +185,21 @@ class Pypi(PackageManager):
|
|
193
185
|
command_list = [activate_command, pip_list_command, deactivate_command]
|
194
186
|
command = command_separator.join(command_list)
|
195
187
|
|
188
|
+
exists_pipdeptree = False
|
196
189
|
try:
|
197
190
|
cmd_ret = subprocess.call(command, shell=True)
|
198
191
|
if cmd_ret != 0:
|
199
192
|
ret = False
|
200
193
|
err_msg = f"cmd ret code({cmd_ret})"
|
194
|
+
else:
|
195
|
+
if os.path.isfile(tmp_pip_list):
|
196
|
+
with open(tmp_pip_list, 'r', encoding='utf-8') as pip_list_file:
|
197
|
+
for pip_list in pip_list_file.readlines():
|
198
|
+
pip_list_name = pip_list.split('==')[0]
|
199
|
+
if pip_list_name == pipdeptree:
|
200
|
+
exists_pipdeptree = True
|
201
|
+
break
|
202
|
+
os.remove(tmp_pip_list)
|
201
203
|
except Exception as e:
|
202
204
|
ret = False
|
203
205
|
err_msg = str(e)
|
@@ -206,63 +208,11 @@ class Pypi(PackageManager):
|
|
206
208
|
logger.error(f"Failed to freeze dependencies ({command}): {err_msg})")
|
207
209
|
return False
|
208
210
|
|
209
|
-
exists_pip_licenses = False
|
210
|
-
exists_prettytable = False
|
211
|
-
exists_wcwidth = False
|
212
|
-
pip_license_pkg_list = []
|
213
|
-
uninstall_pkg_list = []
|
214
|
-
exists_pipdeptree = False
|
215
|
-
|
216
|
-
if os.path.isfile(tmp_pip_list):
|
217
|
-
try:
|
218
|
-
with open(tmp_pip_list, 'r', encoding='utf-8') as pip_list_file:
|
219
|
-
for pip_list in pip_list_file.readlines():
|
220
|
-
pip_list_name = pip_list.split('==')[0]
|
221
|
-
if pip_list_name == pip_licenses:
|
222
|
-
exists_pip_licenses = True
|
223
|
-
if pip_list_name == prettytable:
|
224
|
-
exists_prettytable = True
|
225
|
-
if pip_list_name == wcwidth:
|
226
|
-
exists_wcwidth = True
|
227
|
-
if pip_list_name == pipdeptree:
|
228
|
-
exists_pipdeptree = True
|
229
|
-
os.remove(tmp_pip_list)
|
230
|
-
except Exception as e:
|
231
|
-
logger.error(f"Failed to read freezed package list file: {e}")
|
232
|
-
return False
|
233
|
-
if exists_pip_licenses:
|
234
|
-
pip_license_pkg_list.append(pip_licenses)
|
235
|
-
else:
|
236
|
-
uninstall_pkg_list.append(pip_licenses)
|
237
|
-
if exists_prettytable:
|
238
|
-
pip_license_pkg_list.append(prettytable)
|
239
|
-
else:
|
240
|
-
uninstall_pkg_list.append(prettytable)
|
241
|
-
if exists_wcwidth:
|
242
|
-
pip_license_pkg_list.append(wcwidth)
|
243
|
-
else:
|
244
|
-
uninstall_pkg_list.append(wcwidth)
|
245
|
-
|
246
211
|
command_list = []
|
247
212
|
command_list.append(activate_command)
|
248
|
-
if not exists_pip_licenses:
|
249
|
-
install_pip_command = f"{python_cmd} pip install {pip_licenses}"
|
250
|
-
command_list.append(install_pip_command)
|
251
|
-
|
252
|
-
pip_licenses_command = f"{pip_licenses}{pip_licenses_default_options} > {self.tmp_file_name}"
|
253
|
-
command_list.append(pip_licenses_command)
|
254
|
-
|
255
|
-
if len(pip_license_pkg_list) != 0:
|
256
|
-
pip_licenses_info_command = f"{pip_licenses}{pip_licenses_default_options}{pip_licenses_system_option}"
|
257
|
-
pip_licenses_info_command += " ".join(pip_license_pkg_list)
|
258
|
-
|
259
|
-
pip_licenses_info_command += f" > {self.tmp_pip_license_info_file_name}"
|
260
|
-
command_list.append(pip_licenses_info_command)
|
261
213
|
|
262
|
-
|
263
|
-
|
264
|
-
uninstall_pip_command += ' '.join(uninstall_pkg_list)
|
265
|
-
command_list.append(uninstall_pip_command)
|
214
|
+
pip_inspect_command = f"{python_cmd} pip inspect > {self.tmp_file_name}"
|
215
|
+
command_list.append(pip_inspect_command)
|
266
216
|
|
267
217
|
if not exists_pipdeptree:
|
268
218
|
install_deptree_command = f"{python_cmd} pip install {pipdeptree}"
|
@@ -270,30 +220,37 @@ class Pypi(PackageManager):
|
|
270
220
|
uninstall_deptree_command = f"{python_cmd} pip uninstall -y {pipdeptree}"
|
271
221
|
pipdeptree_command = f"{pipdeptree} --json-tree -e 'pipdeptree,pip,wheel,setuptools' > {self.tmp_deptree_file}"
|
272
222
|
command_list.append(pipdeptree_command)
|
273
|
-
|
223
|
+
|
224
|
+
if not exists_pipdeptree:
|
225
|
+
command_list.append(uninstall_deptree_command)
|
226
|
+
|
274
227
|
command_list.append(deactivate_command)
|
275
228
|
command = command_separator.join(command_list)
|
276
229
|
|
277
230
|
try:
|
278
231
|
cmd_ret = subprocess.call(command, shell=True)
|
279
232
|
if cmd_ret == 0:
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
233
|
+
if os.path.exists(self.tmp_file_name):
|
234
|
+
self.append_input_package_list_file(self.tmp_file_name)
|
235
|
+
|
236
|
+
with open(self.tmp_file_name, 'r', encoding='utf-8') as json_f:
|
237
|
+
inspect_data = json.load(json_f)
|
238
|
+
for package in inspect_data.get('installed', []):
|
239
|
+
metadata = package.get('metadata', {})
|
240
|
+
package_name = metadata.get('name', '')
|
241
|
+
if package_name:
|
242
|
+
if package_name in ['pip', 'setuptools']:
|
243
|
+
continue
|
244
|
+
self.total_dep_list.append(re.sub(r"[-_.]+", "-", package_name).lower())
|
245
|
+
else:
|
246
|
+
logger.error(f"pip inspect output file not found: {self.tmp_file_name}")
|
247
|
+
ret = False
|
291
248
|
else:
|
292
249
|
logger.error(f"Failed to run command: {command}")
|
293
250
|
ret = False
|
294
251
|
except Exception as e:
|
295
252
|
ret = False
|
296
|
-
logger.error(f"Failed to
|
253
|
+
logger.error(f"Failed to get package information using pip inspect: {e}")
|
297
254
|
|
298
255
|
return ret
|
299
256
|
|
@@ -302,25 +259,70 @@ class Pypi(PackageManager):
|
|
302
259
|
try:
|
303
260
|
oss_init_name = ''
|
304
261
|
with open(f_name, 'r', encoding='utf-8') as json_file:
|
305
|
-
|
262
|
+
inspect_data = json.load(json_file)
|
306
263
|
|
307
|
-
for
|
264
|
+
for package in inspect_data.get('installed', []):
|
308
265
|
dep_item = DependencyItem()
|
309
266
|
oss_item = OssItem()
|
310
|
-
|
267
|
+
metadata = package.get('metadata', {})
|
268
|
+
if not metadata:
|
269
|
+
continue
|
270
|
+
|
271
|
+
oss_init_name = metadata.get('name', '')
|
311
272
|
oss_init_name = re.sub(r"[-_.]+", "-", oss_init_name).lower()
|
273
|
+
if oss_init_name not in self.total_dep_list:
|
274
|
+
continue
|
312
275
|
oss_item.name = f"{self.package_manager_name}:{oss_init_name}"
|
313
|
-
|
314
|
-
|
315
|
-
|
276
|
+
oss_item.version = metadata.get('version', '')
|
277
|
+
|
278
|
+
# license_expression > license > classifier
|
279
|
+
license_info = check_UNKNOWN(metadata.get('license_expression', ''))
|
280
|
+
if not license_info:
|
281
|
+
license_info = metadata.get('license', '')
|
282
|
+
if '\n' in license_info:
|
283
|
+
license_info = check_UNKNOWN(check_license_name(license_info))
|
284
|
+
if not license_info:
|
285
|
+
classifiers = metadata.get('classifier', [])
|
286
|
+
license_classifiers = [c for c in classifiers if c.startswith('License ::')]
|
287
|
+
if license_classifiers:
|
288
|
+
license_info_l = []
|
289
|
+
for license_classifier in license_classifiers:
|
290
|
+
if license_classifier.startswith('License :: OSI Approved ::'):
|
291
|
+
license_info_l.append(license_classifier.split('::')[-1].strip())
|
292
|
+
break
|
293
|
+
license_info = ','.join(license_info_l)
|
294
|
+
license_name = check_UNKNOWN(license_info)
|
295
|
+
if license_name:
|
296
|
+
license_name = license_name.replace(';', ',')
|
297
|
+
oss_item.license = license_name
|
298
|
+
|
316
299
|
oss_item.download_location = f"{self.dn_url}{oss_init_name}/{oss_item.version}"
|
300
|
+
|
301
|
+
# project_url 'source' > download_url > project_url 'homepage' > homepage
|
302
|
+
homepage_url = check_UNKNOWN(metadata.get('home_page', ''))
|
303
|
+
download_url = check_UNKNOWN(metadata.get('download_url', ''))
|
304
|
+
project_urls = check_UNKNOWN(metadata.get('project_url', []))
|
305
|
+
if project_urls:
|
306
|
+
priority_order = ['source', 'repository', 'github', 'code', 'source code', 'homepage']
|
307
|
+
for priority in priority_order:
|
308
|
+
for url_entry in project_urls:
|
309
|
+
url_entry_lower = url_entry.lower()
|
310
|
+
if url_entry_lower.startswith(priority):
|
311
|
+
download_url = url_entry.split(', ')[-1]
|
312
|
+
break
|
313
|
+
if download_url:
|
314
|
+
break
|
315
|
+
oss_item.homepage = download_url or homepage_url or f"{self.dn_url}{oss_init_name}"
|
316
|
+
|
317
317
|
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name)
|
318
318
|
purl_dict[f'{oss_init_name}({oss_item.version})'] = dep_item.purl
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
319
|
+
|
320
|
+
direct_url = package.get('direct_url', {})
|
321
|
+
if direct_url:
|
322
|
+
oss_item.download_location = direct_url.get('url', '')
|
323
|
+
oss_item.homepage = oss_item.download_location
|
324
|
+
if not package.get('installer', ''):
|
325
|
+
oss_item.download_location = oss_item.homepage
|
324
326
|
|
325
327
|
if oss_init_name == self.package_name:
|
326
328
|
oss_item.comment = 'root package'
|
@@ -30,7 +30,7 @@ EXTENDED_HEADER = {_sheet_name: ['ID', 'Package URL', 'OSS Name',
|
|
30
30
|
'OSS Version', 'License', 'Download Location',
|
31
31
|
'Homepage', 'Copyright Text', 'Exclude',
|
32
32
|
'Comment', 'Depends On']}
|
33
|
-
_exclude_dir = ['
|
33
|
+
_exclude_dir = ['node_modules', 'venv', 'Pods', 'Carthage']
|
34
34
|
|
35
35
|
|
36
36
|
def get_terminal_size():
|
@@ -50,7 +50,7 @@ def paginate_file(file_path):
|
|
50
50
|
input("Press Enter to see the next page...")
|
51
51
|
|
52
52
|
|
53
|
-
def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[]):
|
53
|
+
def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[], recursive=False):
|
54
54
|
ret = True
|
55
55
|
if not manifest_file_name:
|
56
56
|
for value in const.SUPPORT_PACKAE.values():
|
@@ -62,9 +62,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
62
62
|
found_manifest_file = []
|
63
63
|
suggested_files = []
|
64
64
|
for parent, dirs, files in os.walk(input_dir):
|
65
|
-
|
66
|
-
|
67
|
-
if os.path.basename(parent) in _exclude_dir:
|
65
|
+
parent_parts = parent.split(os.sep)
|
66
|
+
if any(ex_dir in parent_parts for ex_dir in _exclude_dir):
|
68
67
|
continue
|
69
68
|
if os.path.abspath(parent) in abs_path_to_exclude:
|
70
69
|
continue
|
@@ -75,7 +74,8 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
75
74
|
for exclude_path in abs_path_to_exclude):
|
76
75
|
continue
|
77
76
|
if file in manifest_file_name:
|
78
|
-
|
77
|
+
path_with_filename = os.path.join(parent, file)
|
78
|
+
found_manifest_file.append(path_with_filename)
|
79
79
|
if file in const.SUGGESTED_PACKAGE.keys():
|
80
80
|
suggested_files.append(os.path.join(parent, file))
|
81
81
|
for dir in dirs:
|
@@ -84,31 +84,32 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
84
84
|
if len(manifest_l) > 1:
|
85
85
|
if manifest_l[0] == dir:
|
86
86
|
if os.path.exists(os.path.join(parent, manifest_f)):
|
87
|
-
found_manifest_file.append(manifest_f)
|
88
|
-
if
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
found_manifest_file.append(os.path.join(parent, manifest_f))
|
88
|
+
if not recursive:
|
89
|
+
if len(found_manifest_file) > 0:
|
90
|
+
input_dir = parent
|
91
|
+
break
|
92
|
+
|
93
|
+
found_package_manager = defaultdict(lambda: defaultdict(list))
|
94
|
+
for f_with_path in found_manifest_file:
|
95
|
+
f_name = os.path.basename(f_with_path)
|
96
|
+
dir_path = os.path.dirname(f_with_path)
|
93
97
|
for key, value in const.SUPPORT_PACKAE.items():
|
94
98
|
if isinstance(value, list):
|
95
|
-
|
96
|
-
|
97
|
-
if key in found_package_manager.keys():
|
98
|
-
found_package_manager[key].append(f_idx)
|
99
|
-
else:
|
100
|
-
found_package_manager[key] = [f_idx]
|
99
|
+
if f_name in value:
|
100
|
+
found_package_manager[key][dir_path].append(f_name)
|
101
101
|
else:
|
102
|
-
if
|
103
|
-
found_package_manager[key]
|
102
|
+
if f_name == value:
|
103
|
+
found_package_manager[key][dir_path].append(f_name)
|
104
|
+
found_package_manager = {k: dict(v) for k, v in found_package_manager.items()}
|
104
105
|
|
105
106
|
# both npm and pnpm are detected, remove npm.
|
106
|
-
if 'npm' in found_package_manager and 'pnpm' in found_package_manager:
|
107
|
+
if 'npm' in found_package_manager.keys() and 'pnpm' in found_package_manager.keys():
|
107
108
|
del found_package_manager['npm']
|
108
109
|
if len(found_package_manager) >= 1:
|
109
|
-
|
110
|
-
|
111
|
-
logger.
|
110
|
+
log_lines = ["\nDetected Manifest Files automatically"]
|
111
|
+
log_lines = print_package_info(found_package_manager, log_lines)
|
112
|
+
logger.info('\n'.join(log_lines))
|
112
113
|
else:
|
113
114
|
ret = False
|
114
115
|
logger.info("Cannot find the manifest file.")
|
@@ -116,10 +117,20 @@ def find_package_manager(input_dir, abs_path_to_exclude=[], manifest_file_name=[
|
|
116
117
|
return ret, found_package_manager, input_dir, suggested_files
|
117
118
|
|
118
119
|
|
120
|
+
def print_package_info(success_pm, log_lines):
|
121
|
+
if success_pm:
|
122
|
+
for pm, dir_dict in success_pm.items():
|
123
|
+
log_lines.append(f"- {pm}:")
|
124
|
+
for path, files in dir_dict.items():
|
125
|
+
file_list = ', '.join(files)
|
126
|
+
log_lines.append(f" {path}: {file_list}")
|
127
|
+
return log_lines
|
128
|
+
|
129
|
+
|
119
130
|
def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='', pip_activate_cmd='',
|
120
131
|
pip_deactivate_cmd='', output_custom_dir='', app_name=const.default_app_name,
|
121
132
|
github_token='', formats=[], direct=True, path_to_exclude=[], graph_path='',
|
122
|
-
graph_size=(600, 600)):
|
133
|
+
graph_size=(600, 600), recursive=False):
|
123
134
|
global logger
|
124
135
|
|
125
136
|
ret = True
|
@@ -196,6 +207,9 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
196
207
|
autodetect = True
|
197
208
|
found_package_manager = {}
|
198
209
|
if package_manager:
|
210
|
+
scan_item.set_cover_comment(f"Manual detect mode (-m {package_manager})")
|
211
|
+
if package_manager == const.YARN:
|
212
|
+
package_manager = const.NPM
|
199
213
|
autodetect = False
|
200
214
|
support_packagemanager = list(const.SUPPORT_PACKAE.keys())
|
201
215
|
|
@@ -210,16 +224,14 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
210
224
|
manifest_file_name.extend(value)
|
211
225
|
else:
|
212
226
|
manifest_file_name.append(value)
|
213
|
-
scan_item.set_cover_comment(f"Manual detect mode (-m {package_manager})")
|
214
227
|
else:
|
215
228
|
manifest_file_name = []
|
216
229
|
|
217
230
|
try:
|
218
231
|
ret, found_package_manager, input_dir, suggested_files = find_package_manager(input_dir,
|
219
232
|
abs_path_to_exclude,
|
220
|
-
manifest_file_name
|
221
|
-
|
222
|
-
os.chdir(input_dir)
|
233
|
+
manifest_file_name,
|
234
|
+
recursive)
|
223
235
|
except Exception as e:
|
224
236
|
if autodetect:
|
225
237
|
logger.error(f'Fail to find package manager: {e}')
|
@@ -228,7 +240,7 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
228
240
|
if not ret:
|
229
241
|
if not autodetect:
|
230
242
|
logger.info('Try to analyze dependency without manifest file. (Manual mode)')
|
231
|
-
found_package_manager[package_manager] =
|
243
|
+
found_package_manager[package_manager] = {}
|
232
244
|
else:
|
233
245
|
ret = False
|
234
246
|
if suggested_files:
|
@@ -243,40 +255,64 @@ def run_dependency_scanner(package_manager='', input_dir='', output_dir_file='',
|
|
243
255
|
else:
|
244
256
|
scan_item.set_cover_comment("No Package manager detected.")
|
245
257
|
|
246
|
-
pass_key = 'PASS'
|
247
|
-
success_pm =
|
248
|
-
fail_pm =
|
258
|
+
pass_key = ['PASS']
|
259
|
+
success_pm = defaultdict(lambda: defaultdict(list))
|
260
|
+
fail_pm = defaultdict(lambda: defaultdict(list))
|
249
261
|
cover_comment = ''
|
250
|
-
for pm,
|
251
|
-
if
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
if const.ANDROID in found_package_manager.keys():
|
262
|
-
found_package_manager[const.ANDROID] = pass_key
|
263
|
-
if f"{const.ANDROID} ({', '.join(manifest_file_name)})" in fail_pm:
|
264
|
-
fail_pm.remove(f"{const.ANDROID} ({', '.join(manifest_file_name)})")
|
265
|
-
elif pm == const.ANDROID:
|
266
|
-
if const.GRADLE in found_package_manager.keys():
|
267
|
-
found_package_manager[const.GRADLE] = pass_key
|
268
|
-
if f"{const.GRADLE} ({', '.join(manifest_file_name)})" in fail_pm:
|
269
|
-
fail_pm.remove(f"{const.GRADLE} ({', '.join(manifest_file_name)})")
|
262
|
+
for pm, manifest_file_name_list in found_package_manager.items():
|
263
|
+
if not manifest_file_name_list and not autodetect:
|
264
|
+
ret, package_dep_item_list, cover_comment = analyze_dependency(pm, input_dir, output_path,
|
265
|
+
pip_activate_cmd, pip_deactivate_cmd,
|
266
|
+
output_custom_dir, app_name, github_token,
|
267
|
+
[], direct)
|
268
|
+
if ret:
|
269
|
+
success_pm[pm][input_dir].extend(['manual mode (-m option)'])
|
270
|
+
scan_item.append_file_items(package_dep_item_list)
|
271
|
+
else:
|
272
|
+
fail_pm[pm][input_dir].extend(['manual mode (-m option)'])
|
270
273
|
else:
|
271
|
-
|
274
|
+
for manifest_dir, manifest_file_name in manifest_file_name_list.items():
|
275
|
+
input_dir = manifest_dir
|
276
|
+
if manifest_file_name == pass_key:
|
277
|
+
continue
|
278
|
+
os.chdir(input_dir)
|
279
|
+
ret, package_dep_item_list, cover_comment = analyze_dependency(pm, input_dir, output_path,
|
280
|
+
pip_activate_cmd, pip_deactivate_cmd,
|
281
|
+
output_custom_dir, app_name, github_token,
|
282
|
+
manifest_file_name, direct)
|
283
|
+
if ret:
|
284
|
+
success_pm[pm][input_dir].extend(manifest_file_name)
|
285
|
+
scan_item.append_file_items(package_dep_item_list)
|
286
|
+
|
287
|
+
dup_pm = None
|
288
|
+
if pm == const.GRADLE and const.ANDROID in found_package_manager:
|
289
|
+
dup_pm = const.ANDROID
|
290
|
+
elif pm == const.ANDROID and const.GRADLE in found_package_manager:
|
291
|
+
dup_pm = const.GRADLE
|
292
|
+
|
293
|
+
if dup_pm:
|
294
|
+
if dup_pm in fail_pm and input_dir in fail_pm[dup_pm]:
|
295
|
+
fail_pm[dup_pm].pop(input_dir, None)
|
296
|
+
if not fail_pm[dup_pm]:
|
297
|
+
fail_pm.pop(dup_pm, None)
|
298
|
+
else:
|
299
|
+
found_package_manager[dup_pm][manifest_dir] = pass_key
|
300
|
+
else:
|
301
|
+
fail_pm[pm][input_dir].extend(manifest_file_name)
|
272
302
|
|
303
|
+
success_pm = {k: dict(v) for k, v in success_pm.items()}
|
304
|
+
fail_pm = {k: dict(v) for k, v in fail_pm.items()}
|
273
305
|
if len(found_package_manager.keys()) > 0:
|
274
306
|
if len(success_pm) > 0:
|
275
|
-
|
307
|
+
log_lines = ["Success to analyze:"]
|
308
|
+
log_lines = print_package_info(success_pm, log_lines)
|
309
|
+
scan_item.set_cover_comment('\n'.join(log_lines))
|
276
310
|
if len(fail_pm) > 0:
|
277
|
-
|
278
|
-
|
279
|
-
scan_item.set_cover_comment(
|
311
|
+
log_lines = ["Fail to analyze:"]
|
312
|
+
log_lines = print_package_info(fail_pm, log_lines)
|
313
|
+
scan_item.set_cover_comment('\n'.join(log_lines))
|
314
|
+
scan_item.set_cover_comment('Check log file(fosslight_log*.txt) '
|
315
|
+
'and https://fosslight.org/fosslight-guide-en/scanner/3_dependency.html#-prerequisite.')
|
280
316
|
|
281
317
|
if ret and graph_path:
|
282
318
|
graph_path = os.path.abspath(graph_path)
|
@@ -335,6 +371,7 @@ def main():
|
|
335
371
|
graph_path = ''
|
336
372
|
graph_size = (600, 600)
|
337
373
|
direct = True
|
374
|
+
recursive = False
|
338
375
|
|
339
376
|
parser = argparse.ArgumentParser(add_help=False)
|
340
377
|
parser.add_argument('-h', '--help', action='store_true', required=False)
|
@@ -353,6 +390,7 @@ def main():
|
|
353
390
|
parser.add_argument('--graph-size', nargs=2, type=int, metavar=("WIDTH", "HEIGHT"), required=False)
|
354
391
|
parser.add_argument('--direct', choices=('true', 'false'), default='True', required=False)
|
355
392
|
parser.add_argument('--notice', action='store_true', required=False)
|
393
|
+
parser.add_argument('-r', '--recursive', action='store_true', required=False)
|
356
394
|
|
357
395
|
args = parser.parse_args()
|
358
396
|
|
@@ -405,10 +443,12 @@ def main():
|
|
405
443
|
paginate_file(source_file)
|
406
444
|
shutil.copyfile(source_file, destination_file)
|
407
445
|
sys.exit(0)
|
446
|
+
if args.recursive: # -r option
|
447
|
+
recursive = True
|
408
448
|
|
409
449
|
run_dependency_scanner(package_manager, input_dir, output_dir, pip_activate_cmd, pip_deactivate_cmd,
|
410
450
|
output_custom_dir, app_name, github_token, format, direct, path_to_exclude,
|
411
|
-
graph_path, graph_size)
|
451
|
+
graph_path, graph_size, recursive)
|
412
452
|
|
413
453
|
|
414
454
|
if __name__ == '__main__':
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fosslight-dependency
|
3
|
-
Version: 4.1.
|
3
|
+
Version: 4.1.21
|
4
4
|
Summary: FOSSLight Dependency Scanner
|
5
5
|
Home-page: https://github.com/fosslight/fosslight_dependency_scanner
|
6
6
|
Download-URL: https://github.com/fosslight/fosslight_dependency_scanner
|
@@ -51,7 +51,7 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
51
51
|
</thead>
|
52
52
|
<tbody>
|
53
53
|
<tr>
|
54
|
-
<td rowspan="
|
54
|
+
<td rowspan="3">Javascript</td>
|
55
55
|
<td>Npm</td>
|
56
56
|
<td>package.json</td>
|
57
57
|
<td>O</td>
|
@@ -64,6 +64,13 @@ In this user guide, you can see how to install the FOSSLight Dependency Scanner
|
|
64
64
|
<td>O</td>
|
65
65
|
<td>O</td>
|
66
66
|
<td>O</td>
|
67
|
+
</tr>
|
68
|
+
<tr>
|
69
|
+
<td>Yarn</td>
|
70
|
+
<td>package.json</td>
|
71
|
+
<td>O</td>
|
72
|
+
<td>O</td>
|
73
|
+
<td>O</td>
|
67
74
|
</tr>
|
68
75
|
<tr>
|
69
76
|
<td rowspan="2">Java</td>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{fosslight_dependency-4.1.19 → fosslight_dependency-4.1.21}/src/fosslight_dependency/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|