fosslight-dependency 3.0.7__py3-none-any.whl → 4.1.30__py3-none-any.whl
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/LICENSES/LICENSE +201 -0
- fosslight_dependency/LICENSES/LicenseRef-3rd_party_licenses.txt +1254 -0
- fosslight_dependency/__init__.py +0 -1
- fosslight_dependency/_analyze_dependency.py +130 -0
- fosslight_dependency/_graph_convertor.py +67 -0
- fosslight_dependency/_help.py +79 -0
- fosslight_dependency/_package_manager.py +397 -0
- fosslight_dependency/cli.py +127 -0
- fosslight_dependency/constant.py +57 -0
- fosslight_dependency/dependency_item.py +103 -0
- fosslight_dependency/package_manager/Android.py +90 -0
- fosslight_dependency/package_manager/Cargo.py +144 -0
- fosslight_dependency/package_manager/Carthage.py +130 -0
- fosslight_dependency/package_manager/Cocoapods.py +194 -0
- fosslight_dependency/package_manager/Go.py +179 -0
- fosslight_dependency/package_manager/Gradle.py +123 -0
- fosslight_dependency/package_manager/Helm.py +106 -0
- fosslight_dependency/package_manager/Maven.py +274 -0
- fosslight_dependency/package_manager/Npm.py +296 -0
- fosslight_dependency/package_manager/Nuget.py +368 -0
- fosslight_dependency/package_manager/Pnpm.py +155 -0
- fosslight_dependency/package_manager/Pub.py +241 -0
- fosslight_dependency/package_manager/Pypi.py +395 -0
- fosslight_dependency/package_manager/Swift.py +159 -0
- fosslight_dependency/package_manager/Unity.py +118 -0
- fosslight_dependency/package_manager/Yarn.py +231 -0
- fosslight_dependency/package_manager/__init__.py +0 -0
- fosslight_dependency/run_dependency_scanner.py +393 -0
- fosslight_dependency-4.1.30.dist-info/METADATA +213 -0
- fosslight_dependency-4.1.30.dist-info/RECORD +37 -0
- {fosslight_dependency-3.0.7.dist-info → fosslight_dependency-4.1.30.dist-info}/WHEEL +1 -1
- fosslight_dependency-4.1.30.dist-info/entry_points.txt +2 -0
- fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/Apache-2.0.txt +201 -0
- fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/LicenseRef-3rd_party_licenses.txt +1254 -0
- fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/MIT.txt +21 -0
- fosslight_dependency/_version.py +0 -1
- fosslight_dependency/analyze_dependency.py +0 -1090
- fosslight_dependency/third_party/askalono/askalono.exe +0 -0
- fosslight_dependency/third_party/askalono/askalono_macos +0 -0
- fosslight_dependency/third_party/nomos/nomossa +0 -0
- fosslight_dependency-3.0.7.dist-info/3rd_party_licenses.txt +0 -726
- fosslight_dependency-3.0.7.dist-info/METADATA +0 -51
- fosslight_dependency-3.0.7.dist-info/RECORD +0 -13
- fosslight_dependency-3.0.7.dist-info/entry_points.txt +0 -3
- {fosslight_dependency-3.0.7.dist-info → fosslight_dependency-4.1.30.dist-info/licenses}/LICENSE +0 -0
- {fosslight_dependency-3.0.7.dist-info → fosslight_dependency-4.1.30.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import logging
|
|
8
|
+
import json
|
|
9
|
+
import subprocess
|
|
10
|
+
import fosslight_util.constant as constant
|
|
11
|
+
import fosslight_dependency.constant as const
|
|
12
|
+
from fosslight_dependency._package_manager import PackageManager
|
|
13
|
+
from fosslight_dependency._package_manager import connect_github, get_github_license
|
|
14
|
+
from fosslight_dependency._package_manager import get_url_to_purl
|
|
15
|
+
from fosslight_dependency.dependency_item import DependencyItem, change_dependson_to_purl
|
|
16
|
+
from fosslight_util.oss_item import OssItem
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Swift(PackageManager):
|
|
22
|
+
package_manager_name = const.SWIFT
|
|
23
|
+
|
|
24
|
+
input_file_name = const.SUPPORT_PACKAE.get(package_manager_name)
|
|
25
|
+
tmp_dep_tree_fname = 'show-dep.json'
|
|
26
|
+
|
|
27
|
+
def __init__(self, input_dir, output_dir, github_token):
|
|
28
|
+
super().__init__(self.package_manager_name, '', input_dir, output_dir)
|
|
29
|
+
self.github_token = github_token
|
|
30
|
+
|
|
31
|
+
self.check_input_file_path()
|
|
32
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
33
|
+
|
|
34
|
+
def check_input_file_path(self):
|
|
35
|
+
if not os.path.isfile(self.input_file_name):
|
|
36
|
+
for file_in_swift in os.listdir("."):
|
|
37
|
+
if file_in_swift.endswith(".xcodeproj"):
|
|
38
|
+
input_file_name_in_xcodeproj = os.path.join(file_in_swift,
|
|
39
|
+
"project.xcworkspace/xcshareddata/swiftpm",
|
|
40
|
+
self.input_file_name)
|
|
41
|
+
if input_file_name_in_xcodeproj != self.input_file_name:
|
|
42
|
+
if os.path.isfile(input_file_name_in_xcodeproj):
|
|
43
|
+
self.input_file_name = input_file_name_in_xcodeproj
|
|
44
|
+
logger.info(f"It uses the manifest file: {self.input_file_name}")
|
|
45
|
+
|
|
46
|
+
def parse_direct_dependencies(self):
|
|
47
|
+
ret = False
|
|
48
|
+
if os.path.isfile('Package.swift') or os.path.isfile(self.tmp_dep_tree_fname):
|
|
49
|
+
if not os.path.isfile(self.tmp_dep_tree_fname):
|
|
50
|
+
cmd = "swift package show-dependencies --format json"
|
|
51
|
+
try:
|
|
52
|
+
ret_txt = subprocess.check_output(cmd, text=True, shell=True)
|
|
53
|
+
if ret_txt is not None:
|
|
54
|
+
deps_l = json.loads(ret_txt)
|
|
55
|
+
ret = self.parse_dep_tree_json(deps_l)
|
|
56
|
+
except Exception as e:
|
|
57
|
+
logger.warning(f'Fail to get swift dependency tree information: {e}')
|
|
58
|
+
else:
|
|
59
|
+
with open(self.tmp_dep_tree_fname) as f:
|
|
60
|
+
try:
|
|
61
|
+
deps_l = json.load(f)
|
|
62
|
+
ret = self.parse_dep_tree_json(deps_l)
|
|
63
|
+
except Exception as e:
|
|
64
|
+
logger.warning(f'Fail to load swift dependency tree json: {e}')
|
|
65
|
+
else:
|
|
66
|
+
logger.info(f"No Package.swift or {self.tmp_dep_tree_fname}, skip to print direct/transitive.")
|
|
67
|
+
if not ret:
|
|
68
|
+
self.direct_dep = False
|
|
69
|
+
|
|
70
|
+
def get_dependencies(self, dependencies, package):
|
|
71
|
+
package_name = 'name'
|
|
72
|
+
deps = 'dependencies'
|
|
73
|
+
version = 'version'
|
|
74
|
+
|
|
75
|
+
pkg_name = package[package_name]
|
|
76
|
+
pkg_ver = package[version]
|
|
77
|
+
dependency_list = package[deps]
|
|
78
|
+
dependencies[f"{pkg_name}({pkg_ver})"] = []
|
|
79
|
+
for dependency in dependency_list:
|
|
80
|
+
dep_name = dependency[package_name]
|
|
81
|
+
dep_version = dependency[version]
|
|
82
|
+
dependencies[f"{pkg_name}({pkg_ver})"].append(f"{dep_name}({dep_version})")
|
|
83
|
+
if dependency[deps] != []:
|
|
84
|
+
dependencies = self.get_dependencies(dependencies, dependency)
|
|
85
|
+
return dependencies
|
|
86
|
+
|
|
87
|
+
def parse_dep_tree_json(self, rel_json):
|
|
88
|
+
ret = True
|
|
89
|
+
try:
|
|
90
|
+
for p in rel_json['dependencies']:
|
|
91
|
+
self.direct_dep_list.append(p['name'])
|
|
92
|
+
if p['dependencies'] == []:
|
|
93
|
+
continue
|
|
94
|
+
self.relation_tree = self.get_dependencies(self.relation_tree, p)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f'Failed to parse dependency tree: {e}')
|
|
97
|
+
ret = False
|
|
98
|
+
return ret
|
|
99
|
+
|
|
100
|
+
def parse_oss_information(self, f_name):
|
|
101
|
+
json_ver = 2
|
|
102
|
+
purl_dict = {}
|
|
103
|
+
|
|
104
|
+
with open(f_name, 'r', encoding='utf8') as json_file:
|
|
105
|
+
json_raw = json.load(json_file)
|
|
106
|
+
json_ver = json_raw['version']
|
|
107
|
+
|
|
108
|
+
if json_ver == 1:
|
|
109
|
+
json_data = json_raw["object"]["pins"]
|
|
110
|
+
elif json_ver == 2 or json_ver == 3:
|
|
111
|
+
json_data = json_raw["pins"]
|
|
112
|
+
else:
|
|
113
|
+
logger.warning(f'Not supported Package.resolved version {json_ver}')
|
|
114
|
+
logger.warning('Try to parse as version 2(or 3)')
|
|
115
|
+
json_data = json_raw["pins"]
|
|
116
|
+
|
|
117
|
+
g = connect_github(self.github_token)
|
|
118
|
+
|
|
119
|
+
for key in json_data:
|
|
120
|
+
dep_item = DependencyItem()
|
|
121
|
+
oss_item = OssItem()
|
|
122
|
+
if json_ver == 1:
|
|
123
|
+
oss_origin_name = key['package']
|
|
124
|
+
oss_item.homepage = key['repositoryURL']
|
|
125
|
+
else:
|
|
126
|
+
oss_origin_name = key['identity']
|
|
127
|
+
oss_item.homepage = key['location']
|
|
128
|
+
|
|
129
|
+
if oss_item.homepage.endswith('.git'):
|
|
130
|
+
oss_item.homepage = oss_item.homepage[:-4]
|
|
131
|
+
|
|
132
|
+
oss_item.name = f"{self.package_manager_name}:{oss_origin_name}"
|
|
133
|
+
|
|
134
|
+
oss_item.version = key['state'].get('version', None)
|
|
135
|
+
if oss_item.version is None:
|
|
136
|
+
oss_item.version = key['state'].get('revision', None)
|
|
137
|
+
|
|
138
|
+
oss_item.download_location = oss_item.homepage
|
|
139
|
+
|
|
140
|
+
github_repo = "/".join(oss_item.homepage.split('/')[-2:])
|
|
141
|
+
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name, github_repo, oss_item.version)
|
|
142
|
+
purl_dict[f'{oss_origin_name}({oss_item.version})'] = dep_item.purl
|
|
143
|
+
oss_item.license = get_github_license(g, github_repo)
|
|
144
|
+
|
|
145
|
+
if self.direct_dep and len(self.direct_dep_list) > 0:
|
|
146
|
+
if oss_origin_name in self.direct_dep_list:
|
|
147
|
+
oss_item.comment = 'direct'
|
|
148
|
+
else:
|
|
149
|
+
oss_item.comment = 'transitive'
|
|
150
|
+
if f'{oss_origin_name}({oss_item.version})' in self.relation_tree:
|
|
151
|
+
dep_item.depends_on_raw = self.relation_tree[f'{oss_origin_name}({oss_item.version})']
|
|
152
|
+
|
|
153
|
+
dep_item.oss_items.append(oss_item)
|
|
154
|
+
self.dep_items.append(dep_item)
|
|
155
|
+
|
|
156
|
+
if self.direct_dep:
|
|
157
|
+
self.dep_items = change_dependson_to_purl(purl_dict, self.dep_items)
|
|
158
|
+
|
|
159
|
+
return
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2024 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import logging
|
|
8
|
+
import re
|
|
9
|
+
import yaml
|
|
10
|
+
import requests
|
|
11
|
+
import fosslight_util.constant as constant
|
|
12
|
+
import fosslight_dependency.constant as const
|
|
13
|
+
from fosslight_dependency._package_manager import PackageManager
|
|
14
|
+
from fosslight_dependency._package_manager import check_license_name, get_url_to_purl
|
|
15
|
+
from fosslight_dependency.dependency_item import DependencyItem
|
|
16
|
+
from fosslight_util.oss_item import OssItem
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
19
|
+
proprietary_license = 'Proprietary License'
|
|
20
|
+
license_md = 'LICENSE.md'
|
|
21
|
+
third_party_md = 'Third Party Notices.md'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Unity(PackageManager):
|
|
25
|
+
package_manager_name = const.UNITY
|
|
26
|
+
|
|
27
|
+
input_file_name = const.SUPPORT_PACKAE.get(package_manager_name)
|
|
28
|
+
packageCache_dir = os.path.join('Library', 'PackageCache')
|
|
29
|
+
mirror_url = 'https://github.com/needle-mirror/'
|
|
30
|
+
unity_internal_url = 'https://github.cds.internal.unity3d.com'
|
|
31
|
+
third_notice_txt = 'third_party_notice.txt'
|
|
32
|
+
|
|
33
|
+
def __init__(self, input_dir, output_dir):
|
|
34
|
+
super().__init__(self.package_manager_name, '', input_dir, output_dir)
|
|
35
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
36
|
+
|
|
37
|
+
def parse_oss_information(self, f_name):
|
|
38
|
+
with open(f_name, 'r', encoding='utf8') as f:
|
|
39
|
+
f_yml = yaml.safe_load(f)
|
|
40
|
+
resolvedPkg = f_yml['m_ResolvedPackages']
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
for pkg_data in resolvedPkg:
|
|
44
|
+
dep_item = DependencyItem()
|
|
45
|
+
oss_item = OssItem()
|
|
46
|
+
oss_item.name = pkg_data['name']
|
|
47
|
+
oss_item.version = pkg_data['version']
|
|
48
|
+
|
|
49
|
+
oss_packagecache_dir = os.path.join(self.packageCache_dir, f'{oss_item.name}@{oss_item.version}')
|
|
50
|
+
license_f = os.path.join(oss_packagecache_dir, license_md)
|
|
51
|
+
if os.path.isfile(license_f):
|
|
52
|
+
license_name = check_license_name(license_f, True)
|
|
53
|
+
if license_name == '':
|
|
54
|
+
with open(license_f, 'r', encoding='utf-8') as f:
|
|
55
|
+
for line in f:
|
|
56
|
+
matched_l = re.search(r'Unity\s[\s\w]*\sLicense', line)
|
|
57
|
+
if matched_l:
|
|
58
|
+
license_name = matched_l[0]
|
|
59
|
+
break
|
|
60
|
+
else:
|
|
61
|
+
license_name = proprietary_license
|
|
62
|
+
oss_item.license = license_name
|
|
63
|
+
|
|
64
|
+
third_f = os.path.join(oss_packagecache_dir, third_party_md)
|
|
65
|
+
if os.path.isfile(third_f):
|
|
66
|
+
with open(third_f, 'r', encoding='utf-8') as f:
|
|
67
|
+
third_notice = f.readlines()
|
|
68
|
+
with open(self.third_notice_txt, 'a+', encoding='utf-8') as tf:
|
|
69
|
+
for line in third_notice:
|
|
70
|
+
tf.write(line)
|
|
71
|
+
tf.flush()
|
|
72
|
+
|
|
73
|
+
oss_item.homepage = pkg_data['repository']['url']
|
|
74
|
+
if oss_item.homepage and oss_item.homepage.startswith('git@'):
|
|
75
|
+
oss_item.homepage = oss_item.homepage.replace('git@', 'https://')
|
|
76
|
+
if oss_item.homepage is None or oss_item.homepage.startswith(self.unity_internal_url):
|
|
77
|
+
if (license_name != proprietary_license) and license_name != '':
|
|
78
|
+
oss_item.homepage = f'{self.mirror_url}{oss_item.name}'
|
|
79
|
+
if oss_item.homepage is None:
|
|
80
|
+
oss_item.homepage = ''
|
|
81
|
+
else:
|
|
82
|
+
if not check_url_alive(oss_item.homepage):
|
|
83
|
+
minor_version = '.'.join(oss_item.version.split('.')[0:2])
|
|
84
|
+
oss_item.homepage = f'https://docs.unity3d.com/Packages/{oss_item.name}@{minor_version}'
|
|
85
|
+
oss_item.download_location = oss_item.homepage
|
|
86
|
+
dep_item.purl = get_url_to_purl(oss_item.download_location, self.package_manager_name)
|
|
87
|
+
if dep_item.purl == 'None':
|
|
88
|
+
dep_item.purl = ''
|
|
89
|
+
if dep_item.purl != '':
|
|
90
|
+
dep_item.purl = f'{dep_item.purl}@{oss_item.version}'
|
|
91
|
+
|
|
92
|
+
comment_list = []
|
|
93
|
+
if self.direct_dep:
|
|
94
|
+
if pkg_data['isDirectDependency']:
|
|
95
|
+
comment_list.append('direct')
|
|
96
|
+
else:
|
|
97
|
+
comment_list.append('transitive')
|
|
98
|
+
|
|
99
|
+
oss_item.comment = ','.join(comment_list)
|
|
100
|
+
dep_item.oss_items.append(oss_item)
|
|
101
|
+
self.dep_items.append(dep_item)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.error(f"Fail to parse unity oss information: {e}")
|
|
104
|
+
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def check_url_alive(url):
|
|
109
|
+
alive = False
|
|
110
|
+
try:
|
|
111
|
+
response = requests.get(url)
|
|
112
|
+
if response.status_code == 200:
|
|
113
|
+
alive = True
|
|
114
|
+
else:
|
|
115
|
+
logger.debug(f"{url} returned status code {response.status_code}")
|
|
116
|
+
except requests.exceptions.RequestException as e:
|
|
117
|
+
logger.debug(f"Check if url({url})is alive err: {e}")
|
|
118
|
+
return alive
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2025 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import logging
|
|
8
|
+
import subprocess
|
|
9
|
+
import json
|
|
10
|
+
import fosslight_util.constant as constant
|
|
11
|
+
import fosslight_dependency.constant as const
|
|
12
|
+
from fosslight_dependency.package_manager.Npm import Npm
|
|
13
|
+
from fosslight_dependency.dependency_item import DependencyItem, change_dependson_to_purl
|
|
14
|
+
from fosslight_util.oss_item import OssItem
|
|
15
|
+
from fosslight_dependency._package_manager import get_url_to_purl
|
|
16
|
+
from fosslight_dependency.package_manager.Npm import check_multi_license, check_unknown_license
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Yarn(Npm):
|
|
22
|
+
|
|
23
|
+
def __init__(self, input_dir, output_dir):
|
|
24
|
+
super().__init__(input_dir, output_dir)
|
|
25
|
+
self.package_manager_name = const.YARN
|
|
26
|
+
self.yarn_version = None
|
|
27
|
+
|
|
28
|
+
def detect_yarn_version(self):
|
|
29
|
+
"""Detect Yarn version (1.x = Classic, 2+ = Berry)"""
|
|
30
|
+
if self.yarn_version is not None:
|
|
31
|
+
return self.yarn_version
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
result = subprocess.run('yarn -v', shell=True, capture_output=True, text=True, encoding='utf-8')
|
|
35
|
+
if result.returncode == 0:
|
|
36
|
+
version_str = result.stdout.strip()
|
|
37
|
+
major_version = int(version_str.split('.')[0])
|
|
38
|
+
self.yarn_version = major_version
|
|
39
|
+
logger.info(f"Detected Yarn version: {version_str} (major: {major_version})")
|
|
40
|
+
return major_version
|
|
41
|
+
except Exception as e:
|
|
42
|
+
logger.warning(f"Failed to detect Yarn version: {e}")
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def start_license_checker(self):
|
|
46
|
+
ret = True
|
|
47
|
+
license_checker_cmd = f'license-checker --production --json --out {self.input_file_name}'
|
|
48
|
+
custom_path_option = ' --customPath '
|
|
49
|
+
node_modules = 'node_modules'
|
|
50
|
+
|
|
51
|
+
self.detect_yarn_version()
|
|
52
|
+
|
|
53
|
+
# For Yarn Berry (2+), check if using PnP mode
|
|
54
|
+
is_pnp_mode = False
|
|
55
|
+
if self.yarn_version and self.yarn_version >= 2:
|
|
56
|
+
# Check if .pnp.cjs exists (PnP mode indicator)
|
|
57
|
+
if os.path.exists('.pnp.cjs') or os.path.exists('.pnp.js'):
|
|
58
|
+
is_pnp_mode = True
|
|
59
|
+
logger.info("Detected Yarn Berry with PnP mode")
|
|
60
|
+
|
|
61
|
+
if not os.path.isdir(node_modules):
|
|
62
|
+
logger.info("node_modules directory does not exist.")
|
|
63
|
+
self.flag_tmp_node_modules = True
|
|
64
|
+
|
|
65
|
+
# For PnP mode, try to force node_modules creation
|
|
66
|
+
if is_pnp_mode:
|
|
67
|
+
logger.info("Attempting to create node_modules for PnP project...")
|
|
68
|
+
yarn_install_cmd = 'YARN_NODE_LINKER=node-modules yarn install --production --ignore-scripts'
|
|
69
|
+
logger.info(f"Executing: {yarn_install_cmd}")
|
|
70
|
+
else:
|
|
71
|
+
yarn_install_cmd = 'yarn install --production --ignore-scripts'
|
|
72
|
+
logger.info(f"Executing: {yarn_install_cmd}")
|
|
73
|
+
|
|
74
|
+
cmd_ret = subprocess.call(yarn_install_cmd, shell=True)
|
|
75
|
+
if cmd_ret != 0:
|
|
76
|
+
logger.error(f"{yarn_install_cmd} failed")
|
|
77
|
+
if is_pnp_mode:
|
|
78
|
+
logger.error("Yarn Berry PnP mode detected. Consider setting 'nodeLinker: node-modules' in .yarnrc.yml")
|
|
79
|
+
return False
|
|
80
|
+
else:
|
|
81
|
+
logger.info(f"Successfully executed {yarn_install_cmd}")
|
|
82
|
+
|
|
83
|
+
self.make_custom_json(self.tmp_custom_json)
|
|
84
|
+
|
|
85
|
+
cmd = license_checker_cmd + custom_path_option + self.tmp_custom_json
|
|
86
|
+
cmd_ret = subprocess.call(cmd, shell=True)
|
|
87
|
+
if cmd_ret != 0:
|
|
88
|
+
logger.error(f"It returns the error: {cmd}")
|
|
89
|
+
logger.error("Please check if the license-checker is installed.(sudo npm install -g license-checker)")
|
|
90
|
+
ret = False
|
|
91
|
+
else:
|
|
92
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
93
|
+
if os.path.exists(self.tmp_custom_json):
|
|
94
|
+
os.remove(self.tmp_custom_json)
|
|
95
|
+
|
|
96
|
+
return ret
|
|
97
|
+
|
|
98
|
+
def parse_oss_information(self, f_name):
|
|
99
|
+
with open(f_name, 'r', encoding='utf8') as json_file:
|
|
100
|
+
json_data = json.load(json_file)
|
|
101
|
+
|
|
102
|
+
_licenses = 'licenses'
|
|
103
|
+
_repository = 'repository'
|
|
104
|
+
_private = 'private'
|
|
105
|
+
|
|
106
|
+
keys = [key for key in json_data]
|
|
107
|
+
purl_dict = {}
|
|
108
|
+
for i in range(0, len(keys)):
|
|
109
|
+
dep_item = DependencyItem()
|
|
110
|
+
oss_item = OssItem()
|
|
111
|
+
d = json_data.get(keys[i - 1])
|
|
112
|
+
oss_init_name = d['name']
|
|
113
|
+
oss_item.name = f'{const.NPM}:{oss_init_name}'
|
|
114
|
+
|
|
115
|
+
if d[_licenses]:
|
|
116
|
+
license_name = d[_licenses]
|
|
117
|
+
else:
|
|
118
|
+
license_name = ''
|
|
119
|
+
|
|
120
|
+
oss_item.version = d['version']
|
|
121
|
+
package_path = d['path']
|
|
122
|
+
|
|
123
|
+
private_pkg = False
|
|
124
|
+
if _private in d and d[_private]:
|
|
125
|
+
private_pkg = True
|
|
126
|
+
|
|
127
|
+
oss_item.download_location = ''
|
|
128
|
+
|
|
129
|
+
npm_dl_url = f"{self.dn_url}{oss_init_name}/v/{oss_item.version}"
|
|
130
|
+
npm_home_url = f"{self.dn_url}{oss_init_name}"
|
|
131
|
+
dep_item.purl = get_url_to_purl(npm_dl_url, self.package_manager_name)
|
|
132
|
+
purl_dict[f'{oss_init_name}({oss_item.version})'] = dep_item.purl
|
|
133
|
+
|
|
134
|
+
repo_url = d[_repository] if d[_repository] else ''
|
|
135
|
+
if private_pkg:
|
|
136
|
+
oss_item.homepage = repo_url or ''
|
|
137
|
+
oss_item.download_location = oss_item.homepage
|
|
138
|
+
oss_item.comment = 'private'
|
|
139
|
+
else:
|
|
140
|
+
npm_url_exists = False
|
|
141
|
+
if self._network_available is True:
|
|
142
|
+
npm_url_exists = self._npm_url_exists(oss_init_name, oss_item.version)
|
|
143
|
+
|
|
144
|
+
if self._network_available and not npm_url_exists:
|
|
145
|
+
oss_item.homepage = repo_url or ""
|
|
146
|
+
oss_item.download_location = oss_item.homepage
|
|
147
|
+
else:
|
|
148
|
+
oss_item.homepage = repo_url or npm_home_url
|
|
149
|
+
oss_item.download_location = npm_dl_url
|
|
150
|
+
|
|
151
|
+
if self.package_name == f'{oss_init_name}({oss_item.version})':
|
|
152
|
+
oss_item.comment = 'root package'
|
|
153
|
+
elif self.direct_dep and len(self.relation_tree) > 0:
|
|
154
|
+
if f'{oss_init_name}({oss_item.version})' in self.relation_tree[self.package_name]:
|
|
155
|
+
oss_item.comment = 'direct'
|
|
156
|
+
else:
|
|
157
|
+
oss_item.comment = 'transitive'
|
|
158
|
+
|
|
159
|
+
if f'{oss_init_name}({oss_item.version})' in self.relation_tree:
|
|
160
|
+
dep_item.depends_on_raw = self.relation_tree[f'{oss_init_name}({oss_item.version})']
|
|
161
|
+
|
|
162
|
+
# For Yarn, use 'package.json' instead of yarn.lock for license info
|
|
163
|
+
manifest_file_path = os.path.join(package_path, 'package.json')
|
|
164
|
+
multi_license, license_comment, multi_flag = check_multi_license(license_name, manifest_file_path)
|
|
165
|
+
|
|
166
|
+
if multi_flag:
|
|
167
|
+
oss_item.comment = license_comment
|
|
168
|
+
license_name = multi_license
|
|
169
|
+
else:
|
|
170
|
+
license_name = license_name.replace(",", "")
|
|
171
|
+
license_name = check_unknown_license(license_name, manifest_file_path)
|
|
172
|
+
oss_item.license = license_name
|
|
173
|
+
|
|
174
|
+
dep_item.oss_items.append(oss_item)
|
|
175
|
+
self.dep_items.append(dep_item)
|
|
176
|
+
|
|
177
|
+
if self.direct_dep:
|
|
178
|
+
self.dep_items = change_dependson_to_purl(purl_dict, self.dep_items)
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
def parse_rel_dependencies(self, rel_name, rel_ver, rel_dependencies):
|
|
182
|
+
"""Override to handle missing packages and packages without version"""
|
|
183
|
+
_dependencies = 'dependencies'
|
|
184
|
+
_version = 'version'
|
|
185
|
+
_peer = 'peerMissing'
|
|
186
|
+
_missing = 'missing'
|
|
187
|
+
|
|
188
|
+
for rel_dep_name in rel_dependencies.keys():
|
|
189
|
+
# Optional, non-installed dependencies are listed as empty objects
|
|
190
|
+
if rel_dependencies[rel_dep_name] == {}:
|
|
191
|
+
continue
|
|
192
|
+
if _peer in rel_dependencies[rel_dep_name]:
|
|
193
|
+
if rel_dependencies[rel_dep_name][_peer]:
|
|
194
|
+
continue
|
|
195
|
+
# Skip missing packages (not installed)
|
|
196
|
+
if _missing in rel_dependencies[rel_dep_name]:
|
|
197
|
+
if rel_dependencies[rel_dep_name][_missing]:
|
|
198
|
+
continue
|
|
199
|
+
# Skip if version key doesn't exist
|
|
200
|
+
if _version not in rel_dependencies[rel_dep_name]:
|
|
201
|
+
continue
|
|
202
|
+
|
|
203
|
+
if f'{rel_name}({rel_ver})' not in self.relation_tree:
|
|
204
|
+
self.relation_tree[f'{rel_name}({rel_ver})'] = []
|
|
205
|
+
elif f'{rel_dep_name}({rel_dependencies[rel_dep_name][_version]})' in self.relation_tree[f'{rel_name}({rel_ver})']:
|
|
206
|
+
continue
|
|
207
|
+
self.relation_tree[f'{rel_name}({rel_ver})'].append(f'{rel_dep_name}({rel_dependencies[rel_dep_name][_version]})')
|
|
208
|
+
if _dependencies in rel_dependencies[rel_dep_name]:
|
|
209
|
+
self.parse_rel_dependencies(rel_dep_name, rel_dependencies[rel_dep_name][_version],
|
|
210
|
+
rel_dependencies[rel_dep_name][_dependencies])
|
|
211
|
+
|
|
212
|
+
def parse_direct_dependencies(self):
|
|
213
|
+
if not self.direct_dep:
|
|
214
|
+
return
|
|
215
|
+
try:
|
|
216
|
+
# For Yarn, check if package.json exists (not yarn.lock)
|
|
217
|
+
# input_package_list_file[0] is the license-checker output file path
|
|
218
|
+
manifest_dir = os.path.dirname(self.input_package_list_file[0])
|
|
219
|
+
package_json_path = os.path.join(manifest_dir, 'package.json')
|
|
220
|
+
|
|
221
|
+
if os.path.isfile(package_json_path):
|
|
222
|
+
ret, err_msg = self.parse_transitive_relationship()
|
|
223
|
+
if not ret:
|
|
224
|
+
self.direct_dep = False
|
|
225
|
+
logger.warning(f'It cannot print direct/transitive dependency: {err_msg}')
|
|
226
|
+
else:
|
|
227
|
+
logger.info('Direct/transitive support is not possible because the package.json file does not exist.')
|
|
228
|
+
self.direct_dep = False
|
|
229
|
+
except Exception as e:
|
|
230
|
+
logger.warning(f'Cannot print direct/transitive dependency: {e}')
|
|
231
|
+
self.direct_dep = False
|
|
File without changes
|