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,127 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2020 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import argparse
|
|
9
|
+
import shutil
|
|
10
|
+
import fosslight_dependency.constant as const
|
|
11
|
+
from fosslight_dependency._help import print_version, print_help_msg
|
|
12
|
+
from fosslight_dependency.run_dependency_scanner import run_dependency_scanner, _PKG_NAME
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_terminal_size():
|
|
16
|
+
size = shutil.get_terminal_size()
|
|
17
|
+
return size.lines
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def paginate_file(file_path):
|
|
21
|
+
lines_per_page = get_terminal_size() - 1
|
|
22
|
+
with open(file_path, 'r', encoding='utf8') as file:
|
|
23
|
+
lines = file.readlines()
|
|
24
|
+
|
|
25
|
+
for i in range(0, len(lines), lines_per_page):
|
|
26
|
+
os.system('clear' if os.name == 'posix' else 'cls')
|
|
27
|
+
print(''.join(lines[i: i + lines_per_page]))
|
|
28
|
+
if i + lines_per_page < len(lines):
|
|
29
|
+
input("Press Enter to see the next page...")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def main():
|
|
33
|
+
package_manager = ''
|
|
34
|
+
input_dir = ''
|
|
35
|
+
output_dir = ''
|
|
36
|
+
path_to_exclude = []
|
|
37
|
+
pip_activate_cmd = ''
|
|
38
|
+
pip_deactivate_cmd = ''
|
|
39
|
+
output_custom_dir = ''
|
|
40
|
+
app_name = const.default_app_name
|
|
41
|
+
github_token = ''
|
|
42
|
+
format = []
|
|
43
|
+
graph_path = ''
|
|
44
|
+
graph_size = (600, 600)
|
|
45
|
+
direct = True
|
|
46
|
+
recursive = False
|
|
47
|
+
|
|
48
|
+
parser = argparse.ArgumentParser(add_help=False)
|
|
49
|
+
parser.add_argument('-h', '--help', action='store_true', required=False)
|
|
50
|
+
parser.add_argument('-v', '--version', action='store_true', required=False)
|
|
51
|
+
parser.add_argument('-m', '--manager', nargs=1, type=str, default='', required=False)
|
|
52
|
+
parser.add_argument('-p', '--path', nargs=1, type=str, required=False)
|
|
53
|
+
parser.add_argument('-e', '--exclude', nargs='*', required=False, default=[])
|
|
54
|
+
parser.add_argument('-o', '--output', nargs=1, type=str, required=False)
|
|
55
|
+
parser.add_argument('-a', '--activate', nargs=1, type=str, default='', required=False)
|
|
56
|
+
parser.add_argument('-d', '--deactivate', nargs=1, type=str, default='', required=False)
|
|
57
|
+
parser.add_argument('-c', '--customized', nargs=1, type=str, required=False)
|
|
58
|
+
parser.add_argument('-n', '--appname', nargs=1, type=str, required=False)
|
|
59
|
+
parser.add_argument('-t', '--token', nargs=1, type=str, required=False)
|
|
60
|
+
parser.add_argument('-f', '--format', nargs="*", type=str, required=False)
|
|
61
|
+
parser.add_argument('--graph-path', nargs=1, type=str, required=False)
|
|
62
|
+
parser.add_argument('--graph-size', nargs=2, type=int, metavar=("WIDTH", "HEIGHT"), required=False)
|
|
63
|
+
parser.add_argument('--direct', choices=('true', 'false'), default='True', required=False)
|
|
64
|
+
parser.add_argument('--notice', action='store_true', required=False)
|
|
65
|
+
parser.add_argument('-r', '--recursive', action='store_true', required=False)
|
|
66
|
+
|
|
67
|
+
args = parser.parse_args()
|
|
68
|
+
|
|
69
|
+
if args.help: # -h option
|
|
70
|
+
print_help_msg()
|
|
71
|
+
|
|
72
|
+
if args.version: # -v option
|
|
73
|
+
print_version(_PKG_NAME)
|
|
74
|
+
|
|
75
|
+
if args.manager: # -m option
|
|
76
|
+
package_manager = ''.join(args.manager)
|
|
77
|
+
if args.path: # -p option
|
|
78
|
+
input_dir = ''.join(args.path)
|
|
79
|
+
if args.exclude: # -e option
|
|
80
|
+
path_to_exclude = args.exclude
|
|
81
|
+
if args.output: # -o option
|
|
82
|
+
output_dir = ''.join(args.output)
|
|
83
|
+
if args.activate: # -a option
|
|
84
|
+
pip_activate_cmd = ''.join(args.activate)
|
|
85
|
+
if args.deactivate: # -d option
|
|
86
|
+
pip_deactivate_cmd = ''.join(args.deactivate)
|
|
87
|
+
if args.customized: # -c option
|
|
88
|
+
output_custom_dir = ''.join(args.customized)
|
|
89
|
+
if args.appname: # -n option
|
|
90
|
+
app_name = ''.join(args.appname)
|
|
91
|
+
if args.token: # -t option
|
|
92
|
+
github_token = ''.join(args.token)
|
|
93
|
+
if args.format: # -f option
|
|
94
|
+
format = list(args.format)
|
|
95
|
+
if args.graph_path:
|
|
96
|
+
graph_path = ''.join(args.graph_path)
|
|
97
|
+
if args.graph_size:
|
|
98
|
+
graph_size = args.graph_size
|
|
99
|
+
if args.direct: # --direct option
|
|
100
|
+
if args.direct == 'true' or args.direct == 'True':
|
|
101
|
+
direct = True
|
|
102
|
+
elif args.direct == 'false' or args.direct == 'False':
|
|
103
|
+
direct = False
|
|
104
|
+
if args.notice: # --notice option
|
|
105
|
+
try:
|
|
106
|
+
base_path = sys._MEIPASS
|
|
107
|
+
except Exception:
|
|
108
|
+
base_path = os.path.dirname(__file__)
|
|
109
|
+
|
|
110
|
+
data_path = os.path.join(base_path, 'LICENSES')
|
|
111
|
+
print(f"*** {_PKG_NAME} open source license notice ***")
|
|
112
|
+
for ff in os.listdir(data_path):
|
|
113
|
+
source_file = os.path.join(data_path, ff)
|
|
114
|
+
destination_file = os.path.join(base_path, ff)
|
|
115
|
+
paginate_file(source_file)
|
|
116
|
+
shutil.copyfile(source_file, destination_file)
|
|
117
|
+
sys.exit(0)
|
|
118
|
+
if args.recursive: # -r option
|
|
119
|
+
recursive = True
|
|
120
|
+
|
|
121
|
+
run_dependency_scanner(package_manager, input_dir, output_dir, pip_activate_cmd, pip_deactivate_cmd,
|
|
122
|
+
output_custom_dir, app_name, github_token, format, direct, path_to_exclude,
|
|
123
|
+
graph_path, graph_size, recursive)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == '__main__':
|
|
127
|
+
main()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
# System platform name
|
|
8
|
+
WINDOWS = 'Windows'
|
|
9
|
+
LINUX = 'Linux'
|
|
10
|
+
MACOS = 'Darwin'
|
|
11
|
+
|
|
12
|
+
# Package manager name
|
|
13
|
+
PYPI = 'pypi'
|
|
14
|
+
NPM = 'npm'
|
|
15
|
+
MAVEN = 'maven'
|
|
16
|
+
GRADLE = 'gradle'
|
|
17
|
+
PUB = 'pub'
|
|
18
|
+
COCOAPODS = 'cocoapods'
|
|
19
|
+
ANDROID = 'android'
|
|
20
|
+
SWIFT = 'swift'
|
|
21
|
+
CARTHAGE = 'carthage'
|
|
22
|
+
GO = 'go'
|
|
23
|
+
NUGET = 'nuget'
|
|
24
|
+
HELM = 'helm'
|
|
25
|
+
UNITY = 'unity'
|
|
26
|
+
CARGO = 'cargo'
|
|
27
|
+
PNPM = 'pnpm'
|
|
28
|
+
YARN = 'yarn'
|
|
29
|
+
|
|
30
|
+
# Supported package name and manifest file
|
|
31
|
+
SUPPORT_PACKAE = {
|
|
32
|
+
PYPI: ['requirements.txt', 'setup.py', 'pyproject.toml'],
|
|
33
|
+
PNPM: 'pnpm-lock.yaml',
|
|
34
|
+
NPM: 'package.json',
|
|
35
|
+
YARN: 'yarn.lock',
|
|
36
|
+
MAVEN: 'pom.xml',
|
|
37
|
+
GRADLE: 'build.gradle',
|
|
38
|
+
PUB: 'pubspec.yaml',
|
|
39
|
+
COCOAPODS: 'Podfile.lock',
|
|
40
|
+
ANDROID: 'build.gradle',
|
|
41
|
+
SWIFT: 'Package.resolved',
|
|
42
|
+
CARTHAGE: 'Cartfile.resolved',
|
|
43
|
+
GO: 'go.mod',
|
|
44
|
+
NUGET: ['packages.config', os.path.join('obj', 'project.assets.json'), 'Directory.Packages.props'],
|
|
45
|
+
HELM: 'Chart.yaml',
|
|
46
|
+
UNITY: os.path.join('Library', 'PackageManager', 'ProjectCache'),
|
|
47
|
+
CARGO: 'Cargo.toml'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
SUGGESTED_PACKAGE = {
|
|
51
|
+
'Podfile': COCOAPODS,
|
|
52
|
+
'Package.swift': SWIFT,
|
|
53
|
+
'Cartfile': CARTHAGE
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# default android app name
|
|
57
|
+
default_app_name = 'app'
|
|
@@ -0,0 +1,103 @@
|
|
|
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 logging
|
|
7
|
+
from fosslight_util.constant import LOGGER_NAME
|
|
8
|
+
from fosslight_util.oss_item import FileItem
|
|
9
|
+
|
|
10
|
+
_logger = logging.getLogger(LOGGER_NAME)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DependencyItem(FileItem):
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__("")
|
|
16
|
+
|
|
17
|
+
self._depends_on_raw = [] # name(version) format
|
|
18
|
+
self._depends_on = [] # purl format
|
|
19
|
+
self.purl = ""
|
|
20
|
+
|
|
21
|
+
def __del__(self):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def depends_on(self):
|
|
26
|
+
return self._depends_on
|
|
27
|
+
|
|
28
|
+
@depends_on.setter
|
|
29
|
+
def depends_on(self, value):
|
|
30
|
+
if not value:
|
|
31
|
+
self._depends_on = []
|
|
32
|
+
else:
|
|
33
|
+
if not isinstance(value, list):
|
|
34
|
+
value = value.split(",")
|
|
35
|
+
self._depends_on.extend(value)
|
|
36
|
+
self._depends_on = [item.strip() for item in self._depends_on]
|
|
37
|
+
self._depends_on = list(set(self._depends_on))
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def depends_on_raw(self):
|
|
41
|
+
return self._depends_on_raw
|
|
42
|
+
|
|
43
|
+
@depends_on_raw.setter
|
|
44
|
+
def depends_on_raw(self, value):
|
|
45
|
+
if not value:
|
|
46
|
+
self._depends_on_raw = []
|
|
47
|
+
else:
|
|
48
|
+
if not isinstance(value, list):
|
|
49
|
+
value = value.split(",")
|
|
50
|
+
self._depends_on_raw.extend(value)
|
|
51
|
+
self._depends_on_raw = [item.strip() for item in self._depends_on_raw]
|
|
52
|
+
self._depends_on_raw = list(set(self._depends_on_raw))
|
|
53
|
+
|
|
54
|
+
def get_print_array(self):
|
|
55
|
+
items = []
|
|
56
|
+
for oss in self.oss_items:
|
|
57
|
+
exclude = "Exclude" if self.exclude or oss.exclude else ""
|
|
58
|
+
lic = ",".join(oss.license)
|
|
59
|
+
depends_on = ",".join(self.depends_on) if len(self.depends_on) > 0 else ""
|
|
60
|
+
|
|
61
|
+
oss_item = [self.purl, oss.name, oss.version, lic, oss.download_location, oss.homepage,
|
|
62
|
+
oss.copyright, exclude, oss.comment, depends_on]
|
|
63
|
+
items.append(oss_item)
|
|
64
|
+
|
|
65
|
+
return items
|
|
66
|
+
|
|
67
|
+
def get_print_json(self):
|
|
68
|
+
items = []
|
|
69
|
+
for oss in self.oss_items:
|
|
70
|
+
json_item = {}
|
|
71
|
+
json_item["name"] = oss.name
|
|
72
|
+
json_item["version"] = oss.version
|
|
73
|
+
|
|
74
|
+
if self.purl != "":
|
|
75
|
+
json_item["package url"] = self.purl
|
|
76
|
+
if len(oss.license) > 0:
|
|
77
|
+
json_item["license"] = oss.license
|
|
78
|
+
if oss.download_location != "":
|
|
79
|
+
json_item["download location"] = oss.download_location
|
|
80
|
+
if oss.homepage != "":
|
|
81
|
+
json_item["homepage"] = oss.homepage
|
|
82
|
+
if oss.copyright != "":
|
|
83
|
+
json_item["copyright text"] = oss.copyright
|
|
84
|
+
if self.exclude or oss.exclude:
|
|
85
|
+
json_item["exclude"] = True
|
|
86
|
+
if oss.comment != "":
|
|
87
|
+
json_item["comment"] = oss.comment
|
|
88
|
+
if len(self.depends_on) > 0:
|
|
89
|
+
json_item["depends on"] = self.depends_on
|
|
90
|
+
|
|
91
|
+
items.append(json_item)
|
|
92
|
+
|
|
93
|
+
return items
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def change_dependson_to_purl(purl_dict, dep_items):
|
|
97
|
+
for dep_item in dep_items:
|
|
98
|
+
try:
|
|
99
|
+
dep_item.depends_on = list(filter(None, map(lambda x: purl_dict.get(x, ''), dep_item.depends_on_raw)))
|
|
100
|
+
|
|
101
|
+
except Exception as e:
|
|
102
|
+
_logger.warning(f'Fail to change depend_on to purl:{e}')
|
|
103
|
+
return dep_items
|
|
@@ -0,0 +1,90 @@
|
|
|
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 fosslight_util.constant as constant
|
|
9
|
+
import fosslight_dependency.constant as const
|
|
10
|
+
from fosslight_dependency._package_manager import PackageManager, get_url_to_purl
|
|
11
|
+
from fosslight_dependency.dependency_item import DependencyItem, change_dependson_to_purl
|
|
12
|
+
from fosslight_util.get_pom_license import get_license_from_pom
|
|
13
|
+
from fosslight_util.oss_item import OssItem
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Android(PackageManager):
|
|
19
|
+
package_manager_name = const.ANDROID
|
|
20
|
+
|
|
21
|
+
plugin_output_file = 'android_dependency_output.txt'
|
|
22
|
+
app_name = const.default_app_name
|
|
23
|
+
input_file_name = ''
|
|
24
|
+
plugin_auto_run = False
|
|
25
|
+
|
|
26
|
+
def __init__(self, input_dir, output_dir, app_name):
|
|
27
|
+
super().__init__(self.package_manager_name, '', input_dir, output_dir)
|
|
28
|
+
if app_name:
|
|
29
|
+
self.app_name = app_name
|
|
30
|
+
self.input_file_name = self.check_input_path()
|
|
31
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
32
|
+
|
|
33
|
+
def __del__(self):
|
|
34
|
+
if self.plugin_auto_run:
|
|
35
|
+
if os.path.isfile(self.input_file_name):
|
|
36
|
+
os.remove(self.input_file_name)
|
|
37
|
+
|
|
38
|
+
def check_input_path(self):
|
|
39
|
+
if os.path.isfile(self.plugin_output_file):
|
|
40
|
+
return self.plugin_output_file
|
|
41
|
+
else:
|
|
42
|
+
return os.path.join(self.app_name, self.plugin_output_file)
|
|
43
|
+
|
|
44
|
+
def parse_oss_information(self, f_name):
|
|
45
|
+
with open(f_name, 'r', encoding='utf8') as input_fp:
|
|
46
|
+
purl_dict = {}
|
|
47
|
+
for i, line in enumerate(input_fp.readlines()):
|
|
48
|
+
dep_item = DependencyItem()
|
|
49
|
+
oss_item = OssItem()
|
|
50
|
+
split_str = line.strip().split("\t")
|
|
51
|
+
if i < 2:
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
if len(split_str) == 9 or len(split_str) == 7:
|
|
55
|
+
_, _, oss_item.name, oss_item.version, oss_item.license, \
|
|
56
|
+
oss_item.download_location, oss_item.homepage = split_str[:7]
|
|
57
|
+
else:
|
|
58
|
+
continue
|
|
59
|
+
if not oss_item.license:
|
|
60
|
+
license_names = get_license_from_pom(oss_item.name.split(':')[0],
|
|
61
|
+
oss_item.name.split(':')[1],
|
|
62
|
+
oss_item.version)
|
|
63
|
+
if license_names:
|
|
64
|
+
oss_item.license = license_names
|
|
65
|
+
|
|
66
|
+
dep_item.purl = get_url_to_purl(oss_item.download_location, 'maven')
|
|
67
|
+
purl_dict[f'{oss_item.name}({oss_item.version})'] = dep_item.purl
|
|
68
|
+
|
|
69
|
+
if self.direct_dep:
|
|
70
|
+
dep_key = f"{oss_item.name}({oss_item.version})"
|
|
71
|
+
if self.total_dep_list:
|
|
72
|
+
if dep_key not in self.total_dep_list:
|
|
73
|
+
continue
|
|
74
|
+
if dep_key in self.direct_dep_list:
|
|
75
|
+
oss_item.comment = 'direct'
|
|
76
|
+
else:
|
|
77
|
+
oss_item.comment = 'transitive'
|
|
78
|
+
try:
|
|
79
|
+
if dep_key in self.relation_tree:
|
|
80
|
+
dep_item.depends_on_raw = self.relation_tree[dep_key]
|
|
81
|
+
except Exception as e:
|
|
82
|
+
logger.error(f"Fail to find oss scope in dependency tree: {e}")
|
|
83
|
+
|
|
84
|
+
dep_item.oss_items.append(oss_item)
|
|
85
|
+
self.dep_items.append(dep_item)
|
|
86
|
+
|
|
87
|
+
if self.direct_dep:
|
|
88
|
+
self.dep_items = change_dependson_to_purl(purl_dict, self.dep_items)
|
|
89
|
+
|
|
90
|
+
return
|
|
@@ -0,0 +1,144 @@
|
|
|
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 re
|
|
10
|
+
import subprocess
|
|
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 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
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Cargo(PackageManager):
|
|
21
|
+
package_manager_name = const.CARGO
|
|
22
|
+
|
|
23
|
+
dn_url = 'https://crates.io/crates/'
|
|
24
|
+
input_file_name = 'tmp_cargo_fosslight_output.json'
|
|
25
|
+
tmp_input_file_flag = False
|
|
26
|
+
cur_path = ''
|
|
27
|
+
cargo_lock_f = 'Cargo.lock'
|
|
28
|
+
|
|
29
|
+
def __init__(self, input_dir, output_dir):
|
|
30
|
+
super().__init__(self.package_manager_name, self.dn_url, input_dir, output_dir)
|
|
31
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
32
|
+
|
|
33
|
+
def __del__(self):
|
|
34
|
+
if self.tmp_input_file_flag:
|
|
35
|
+
os.remove(self.input_file_name)
|
|
36
|
+
|
|
37
|
+
def run_plugin(self):
|
|
38
|
+
if os.path.exists(self.input_file_name):
|
|
39
|
+
logger.info(f"Found {self.input_file_name}, skip the flutter cmd to analyze dependency.")
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
if not os.path.exists(const.SUPPORT_PACKAE.get(self.package_manager_name)):
|
|
43
|
+
logger.error(f"Cannot find the file({const.SUPPORT_PACKAE.get(self.package_manager_name)})")
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
if os.path.exists(self.cargo_lock_f):
|
|
47
|
+
cmd = f'cargo metadata --locked --format-version 1 > {self.input_file_name}'
|
|
48
|
+
else:
|
|
49
|
+
cmd = f'cargo metadata --format-version 1 > {self.input_file_name}'
|
|
50
|
+
ret = subprocess.call(cmd, shell=True)
|
|
51
|
+
if ret != 0:
|
|
52
|
+
logger.error(f"Failed to run: {cmd}")
|
|
53
|
+
os.chdir(self.cur_path)
|
|
54
|
+
return False
|
|
55
|
+
self.tmp_input_file_flag = True
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
def parse_oss_information(self, f_name):
|
|
59
|
+
json_data = ''
|
|
60
|
+
|
|
61
|
+
with open(f_name, 'r', encoding='utf8') as cargo_file:
|
|
62
|
+
json_f = json.load(cargo_file)
|
|
63
|
+
try:
|
|
64
|
+
purl_dict = {}
|
|
65
|
+
workspace_members_key = 'workspace_members'
|
|
66
|
+
resolve_key = 'resolve'
|
|
67
|
+
root_key = 'root'
|
|
68
|
+
nodes_key = 'nodes'
|
|
69
|
+
workspace_members = []
|
|
70
|
+
root = ''
|
|
71
|
+
resolve_node = []
|
|
72
|
+
|
|
73
|
+
if workspace_members_key in json_f:
|
|
74
|
+
workspace_members = json_f[workspace_members_key]
|
|
75
|
+
|
|
76
|
+
if resolve_key in json_f:
|
|
77
|
+
if root_key in json_f[resolve_key]:
|
|
78
|
+
root = json_f[resolve_key][root_key]
|
|
79
|
+
if nodes_key in json_f[resolve_key]:
|
|
80
|
+
resolve_node = json_f[resolve_key][nodes_key]
|
|
81
|
+
if root and resolve_node:
|
|
82
|
+
self.direct_dep_list.extend(get_matched_dependencies(root, resolve_node))
|
|
83
|
+
else:
|
|
84
|
+
self.direct_dep = False
|
|
85
|
+
logger.info('Cannot find dependencies relationship (no resolve nodes.)')
|
|
86
|
+
|
|
87
|
+
for json_data in json_f['packages']:
|
|
88
|
+
dep_item = DependencyItem()
|
|
89
|
+
oss_item = OssItem()
|
|
90
|
+
pkg_id = json_data['id']
|
|
91
|
+
oss_origin_name = json_data['name']
|
|
92
|
+
|
|
93
|
+
oss_item.name = f"{self.package_manager_name}:{oss_origin_name}"
|
|
94
|
+
oss_item.version = json_data['version']
|
|
95
|
+
dn_without_ver = f"{self.dn_url}{oss_origin_name}"
|
|
96
|
+
oss_item.homepage = json_data['repository']
|
|
97
|
+
if oss_item.homepage is None:
|
|
98
|
+
oss_item.homepage = dn_without_ver
|
|
99
|
+
dep_item.purl = get_url_to_purl(dn_without_ver, self.package_manager_name, oss_origin_name, oss_item.version)
|
|
100
|
+
oss_item.download_location = f'{dn_without_ver}/{oss_item.version}'
|
|
101
|
+
purl_dict[f'{oss_origin_name}({oss_item.version})'] = dep_item.purl
|
|
102
|
+
if json_data['license'] is not None:
|
|
103
|
+
oss_item.license = json_data['license']
|
|
104
|
+
|
|
105
|
+
if self.direct_dep:
|
|
106
|
+
if pkg_id == root:
|
|
107
|
+
oss_item.comment = 'root package'
|
|
108
|
+
if pkg_id in workspace_members:
|
|
109
|
+
oss_item.comment = 'local package'
|
|
110
|
+
if len(self.direct_dep_list) > 0:
|
|
111
|
+
if pkg_id != root:
|
|
112
|
+
if f'{oss_origin_name}({oss_item.version})' in self.direct_dep_list:
|
|
113
|
+
oss_item.comment = 'direct'
|
|
114
|
+
else:
|
|
115
|
+
oss_item.comment = 'transitive'
|
|
116
|
+
dep_item.depends_on_raw.extend(get_matched_dependencies(pkg_id, resolve_node))
|
|
117
|
+
|
|
118
|
+
dep_item.oss_items.append(oss_item)
|
|
119
|
+
self.dep_items.append(dep_item)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
logger.error(f"Fail to parse pub oss information: {e}")
|
|
122
|
+
if self.direct_dep:
|
|
123
|
+
self.dep_items = change_dependson_to_purl(purl_dict, self.dep_items)
|
|
124
|
+
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def get_matched_dependencies(match_id, resolve_node):
|
|
129
|
+
dependencies_list = []
|
|
130
|
+
for node in resolve_node:
|
|
131
|
+
if match_id == node['id']:
|
|
132
|
+
for dep_pkg in node['dependencies']:
|
|
133
|
+
try:
|
|
134
|
+
match = re.findall(r'^.*#(\S*)@(\S*)', dep_pkg)
|
|
135
|
+
dependencies_list.append(f'{match[0][0]}({match[0][1]})')
|
|
136
|
+
except Exception:
|
|
137
|
+
try:
|
|
138
|
+
match = re.findall(r'^(\S*)\s(\S*)\s', dep_pkg)
|
|
139
|
+
dependencies_list.append(f'{match[0][0]}({match[0][1]})')
|
|
140
|
+
except Exception:
|
|
141
|
+
logger.info(f'cannot find name and version for dependencies: {match_id}')
|
|
142
|
+
pass
|
|
143
|
+
break
|
|
144
|
+
return dependencies_list
|
|
@@ -0,0 +1,130 @@
|
|
|
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 logging
|
|
7
|
+
import re
|
|
8
|
+
import os
|
|
9
|
+
import fosslight_util.constant as constant
|
|
10
|
+
import fosslight_dependency.constant as const
|
|
11
|
+
from fosslight_dependency._package_manager import PackageManager
|
|
12
|
+
from fosslight_dependency._package_manager import connect_github, get_github_license
|
|
13
|
+
from fosslight_dependency._package_manager import get_url_to_purl, check_license_name
|
|
14
|
+
from fosslight_dependency.dependency_item import DependencyItem
|
|
15
|
+
from fosslight_util.oss_item import OssItem
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
checkout_dir = os.path.join("Carthage", 'Checkouts')
|
|
21
|
+
license_file_regs = ['licen[cs]e[s]?', 'notice[s]?', 'copying*', 'copyright[s]?',
|
|
22
|
+
'mit', 'bsd[-]?[0-4]?', 'bsd[-]?[0-4][-]?clause[s]?', 'apache[-,_]?[1-2]?[.,-,_]?[0-2]?',
|
|
23
|
+
'unlicen[cs]e', '[a,l]?gpl[-]?[1-3]?[.,-,_]?[0-1]?', 'legal']
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Carthage(PackageManager):
|
|
27
|
+
package_manager_name = const.CARTHAGE
|
|
28
|
+
|
|
29
|
+
input_file_name = const.SUPPORT_PACKAE.get(package_manager_name)
|
|
30
|
+
dn_url = "https://github.com/"
|
|
31
|
+
|
|
32
|
+
def __init__(self, input_dir, output_dir, github_token):
|
|
33
|
+
super().__init__(self.package_manager_name, self.dn_url, input_dir, output_dir)
|
|
34
|
+
self.github_token = github_token
|
|
35
|
+
self.append_input_package_list_file(self.input_file_name)
|
|
36
|
+
|
|
37
|
+
def parse_oss_information(self, f_name):
|
|
38
|
+
github = "github"
|
|
39
|
+
checkout_dir_list = get_checkout_dirname()
|
|
40
|
+
|
|
41
|
+
with open(f_name, 'r', encoding='utf8') as input_fp:
|
|
42
|
+
g = ''
|
|
43
|
+
if not checkout_dir_list:
|
|
44
|
+
g = connect_github(self.github_token)
|
|
45
|
+
|
|
46
|
+
for i, line in enumerate(input_fp.readlines()):
|
|
47
|
+
# Cartfile origin : github, git
|
|
48
|
+
# Ref. https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md
|
|
49
|
+
re_result = re.findall(r'(github|git)[\s]\"(\S*)\"[\s]\"(\S*)\"', line)
|
|
50
|
+
try:
|
|
51
|
+
dep_item = DependencyItem()
|
|
52
|
+
oss_item = OssItem()
|
|
53
|
+
repo = re_result[0][0]
|
|
54
|
+
oss_path = re_result[0][1]
|
|
55
|
+
if oss_path.endswith('.git'):
|
|
56
|
+
oss_path = oss_path[:-4]
|
|
57
|
+
oss_origin_name = oss_path.split('/')[-1]
|
|
58
|
+
oss_item.name = self.package_manager_name + ":" + oss_origin_name
|
|
59
|
+
|
|
60
|
+
if repo == github:
|
|
61
|
+
oss_item.homepage = self.dn_url + oss_path
|
|
62
|
+
else:
|
|
63
|
+
oss_item.homepage = oss_path
|
|
64
|
+
oss_item.download_location = oss_item.homepage
|
|
65
|
+
oss_item.version = re_result[0][2]
|
|
66
|
+
|
|
67
|
+
dep_item.purl = get_url_to_purl(oss_item.homepage, self.package_manager_name,
|
|
68
|
+
oss_origin_name, oss_item.version)
|
|
69
|
+
|
|
70
|
+
license_name = ''
|
|
71
|
+
find_license = False
|
|
72
|
+
if oss_origin_name in checkout_dir_list:
|
|
73
|
+
oss_path_in_checkout = os.path.join(checkout_dir, oss_origin_name)
|
|
74
|
+
for filename_in_dir in os.listdir(oss_path_in_checkout):
|
|
75
|
+
if find_license:
|
|
76
|
+
break
|
|
77
|
+
filename_with_checkout_path = os.path.join(oss_path_in_checkout, filename_in_dir)
|
|
78
|
+
if os.path.isfile(filename_with_checkout_path):
|
|
79
|
+
for license_file_reg in license_file_regs:
|
|
80
|
+
match_result = re.match(license_file_reg, filename_in_dir.lower())
|
|
81
|
+
if match_result is not None:
|
|
82
|
+
license_name = check_license_name(filename_with_checkout_path, True)
|
|
83
|
+
find_license = True
|
|
84
|
+
break
|
|
85
|
+
if license_name == '':
|
|
86
|
+
if repo == github:
|
|
87
|
+
try:
|
|
88
|
+
if not g:
|
|
89
|
+
g = connect_github(self.github_token)
|
|
90
|
+
license_name = get_github_license(g, oss_path)
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logger.warning(f"Failed to get license with github api: {e}")
|
|
93
|
+
license_name == ''
|
|
94
|
+
oss_item.license = license_name
|
|
95
|
+
if self.direct_dep_list:
|
|
96
|
+
if oss_origin_name in self.direct_dep_list:
|
|
97
|
+
oss_item.comment = 'direct'
|
|
98
|
+
else:
|
|
99
|
+
oss_item.comment = 'transitive'
|
|
100
|
+
dep_item.oss_items.append(oss_item)
|
|
101
|
+
self.dep_items.append(dep_item)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
logger.warning(f"Failed to parse oss information: {e}")
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
def parse_direct_dependencies(self):
|
|
107
|
+
self.direct_dep = True
|
|
108
|
+
cartfile = 'Cartfile'
|
|
109
|
+
if os.path.exists(cartfile):
|
|
110
|
+
with open(cartfile, 'r', encoding='utf8') as input_fp:
|
|
111
|
+
for i, line in enumerate(input_fp.readlines()):
|
|
112
|
+
re_result = re.findall(r'(github|git)[\s]\"(\S*)\"[\s]\"(\S*)\"', line)
|
|
113
|
+
try:
|
|
114
|
+
oss_path = re_result[0][1]
|
|
115
|
+
if oss_path.endswith('.git'):
|
|
116
|
+
oss_path = oss_path[:-4]
|
|
117
|
+
oss_origin_name = oss_path.split('/')[-1]
|
|
118
|
+
self.direct_dep_list.append(oss_origin_name)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
logger.warning(f"Failed to parse Cartfile: {e}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_checkout_dirname():
|
|
124
|
+
checkout_dir_list = []
|
|
125
|
+
if os.path.isdir(checkout_dir):
|
|
126
|
+
for item in os.listdir(checkout_dir):
|
|
127
|
+
if os.path.isdir(os.path.join(checkout_dir, item)):
|
|
128
|
+
checkout_dir_list.append(item)
|
|
129
|
+
|
|
130
|
+
return checkout_dir_list
|