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.
Files changed (46) hide show
  1. fosslight_dependency/LICENSES/LICENSE +201 -0
  2. fosslight_dependency/LICENSES/LicenseRef-3rd_party_licenses.txt +1254 -0
  3. fosslight_dependency/__init__.py +0 -1
  4. fosslight_dependency/_analyze_dependency.py +130 -0
  5. fosslight_dependency/_graph_convertor.py +67 -0
  6. fosslight_dependency/_help.py +79 -0
  7. fosslight_dependency/_package_manager.py +397 -0
  8. fosslight_dependency/cli.py +127 -0
  9. fosslight_dependency/constant.py +57 -0
  10. fosslight_dependency/dependency_item.py +103 -0
  11. fosslight_dependency/package_manager/Android.py +90 -0
  12. fosslight_dependency/package_manager/Cargo.py +144 -0
  13. fosslight_dependency/package_manager/Carthage.py +130 -0
  14. fosslight_dependency/package_manager/Cocoapods.py +194 -0
  15. fosslight_dependency/package_manager/Go.py +179 -0
  16. fosslight_dependency/package_manager/Gradle.py +123 -0
  17. fosslight_dependency/package_manager/Helm.py +106 -0
  18. fosslight_dependency/package_manager/Maven.py +274 -0
  19. fosslight_dependency/package_manager/Npm.py +296 -0
  20. fosslight_dependency/package_manager/Nuget.py +368 -0
  21. fosslight_dependency/package_manager/Pnpm.py +155 -0
  22. fosslight_dependency/package_manager/Pub.py +241 -0
  23. fosslight_dependency/package_manager/Pypi.py +395 -0
  24. fosslight_dependency/package_manager/Swift.py +159 -0
  25. fosslight_dependency/package_manager/Unity.py +118 -0
  26. fosslight_dependency/package_manager/Yarn.py +231 -0
  27. fosslight_dependency/package_manager/__init__.py +0 -0
  28. fosslight_dependency/run_dependency_scanner.py +393 -0
  29. fosslight_dependency-4.1.30.dist-info/METADATA +213 -0
  30. fosslight_dependency-4.1.30.dist-info/RECORD +37 -0
  31. {fosslight_dependency-3.0.7.dist-info → fosslight_dependency-4.1.30.dist-info}/WHEEL +1 -1
  32. fosslight_dependency-4.1.30.dist-info/entry_points.txt +2 -0
  33. fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/Apache-2.0.txt +201 -0
  34. fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/LicenseRef-3rd_party_licenses.txt +1254 -0
  35. fosslight_dependency-4.1.30.dist-info/licenses/LICENSES/MIT.txt +21 -0
  36. fosslight_dependency/_version.py +0 -1
  37. fosslight_dependency/analyze_dependency.py +0 -1090
  38. fosslight_dependency/third_party/askalono/askalono.exe +0 -0
  39. fosslight_dependency/third_party/askalono/askalono_macos +0 -0
  40. fosslight_dependency/third_party/nomos/nomossa +0 -0
  41. fosslight_dependency-3.0.7.dist-info/3rd_party_licenses.txt +0 -726
  42. fosslight_dependency-3.0.7.dist-info/METADATA +0 -51
  43. fosslight_dependency-3.0.7.dist-info/RECORD +0 -13
  44. fosslight_dependency-3.0.7.dist-info/entry_points.txt +0 -3
  45. {fosslight_dependency-3.0.7.dist-info → fosslight_dependency-4.1.30.dist-info/licenses}/LICENSE +0 -0
  46. {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