fosslight-util 2.0.0__py3-none-any.whl → 2.1.28__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_util/_get_downloadable_url.py +429 -63
- fosslight_util/compare_yaml.py +3 -1
- fosslight_util/constant.py +5 -1
- fosslight_util/correct.py +4 -6
- fosslight_util/download.py +216 -77
- fosslight_util/exclude.py +65 -0
- fosslight_util/help.py +14 -3
- fosslight_util/oss_item.py +24 -3
- fosslight_util/output_format.py +100 -18
- fosslight_util/set_log.py +8 -2
- fosslight_util/write_cyclonedx.py +210 -0
- fosslight_util/write_excel.py +5 -1
- fosslight_util/write_scancodejson.py +31 -14
- fosslight_util/write_spdx.py +161 -109
- {fosslight_util-2.0.0.dist-info → fosslight_util-2.1.28.dist-info}/METADATA +24 -21
- fosslight_util-2.1.28.dist-info/RECORD +32 -0
- {fosslight_util-2.0.0.dist-info → fosslight_util-2.1.28.dist-info}/WHEEL +1 -1
- {fosslight_util-2.0.0.dist-info → fosslight_util-2.1.28.dist-info}/entry_points.txt +0 -1
- fosslight_util/convert_excel_to_yaml.py +0 -69
- fosslight_util-2.0.0.dist-info/RECORD +0 -31
- {fosslight_util-2.0.0.dist-info → fosslight_util-2.1.28.dist-info/licenses}/LICENSE +0 -0
- {fosslight_util-2.0.0.dist-info → fosslight_util-2.1.28.dist-info}/top_level.txt +0 -0
fosslight_util/download.py
CHANGED
|
@@ -10,7 +10,7 @@ import zipfile
|
|
|
10
10
|
import logging
|
|
11
11
|
import argparse
|
|
12
12
|
import shutil
|
|
13
|
-
import
|
|
13
|
+
from git import Repo, GitCommandError, Git
|
|
14
14
|
import bz2
|
|
15
15
|
import contextlib
|
|
16
16
|
from datetime import datetime
|
|
@@ -26,9 +26,11 @@ import platform
|
|
|
26
26
|
import subprocess
|
|
27
27
|
import re
|
|
28
28
|
from typing import Tuple
|
|
29
|
+
import urllib.parse
|
|
30
|
+
import json
|
|
29
31
|
|
|
30
32
|
logger = logging.getLogger(constant.LOGGER_NAME)
|
|
31
|
-
compression_extension = {".tar.bz2", ".tar.gz", ".tar.xz", ".tgz", ".tar", ".zip", ".jar", ".bz2"}
|
|
33
|
+
compression_extension = {".tar.bz2", ".tar.gz", ".tar.xz", ".tgz", ".tar", ".zip", ".jar", ".bz2", ".whl"}
|
|
32
34
|
prefix_refs = ["refs/remotes/origin/", "refs/tags/"]
|
|
33
35
|
SIGNAL_TIMEOUT = 600
|
|
34
36
|
|
|
@@ -77,7 +79,7 @@ def parse_src_link(src_link):
|
|
|
77
79
|
if src_link.startswith("git://github.com/"):
|
|
78
80
|
src_link_changed = change_src_link_to_https(src_link_split[0])
|
|
79
81
|
elif src_link.startswith("git@github.com:"):
|
|
80
|
-
src_link_changed =
|
|
82
|
+
src_link_changed = src_link_split[0]
|
|
81
83
|
else:
|
|
82
84
|
if "rubygems.org" in src_link:
|
|
83
85
|
src_info["rubygems"] = True
|
|
@@ -92,39 +94,11 @@ def parse_src_link(src_link):
|
|
|
92
94
|
return src_info
|
|
93
95
|
|
|
94
96
|
|
|
95
|
-
def main():
|
|
96
|
-
parser = argparse.ArgumentParser(description='FOSSLight Downloader', prog='fosslight_download', add_help=False)
|
|
97
|
-
parser.add_argument('-h', '--help', help='Print help message', action='store_true', dest='help')
|
|
98
|
-
parser.add_argument('-s', '--source', help='Source link to download', type=str, dest='source')
|
|
99
|
-
parser.add_argument('-t', '--target_dir', help='Target directory', type=str, dest='target_dir', default="")
|
|
100
|
-
parser.add_argument('-d', '--log_dir', help='Directory to save log file', type=str, dest='log_dir', default="")
|
|
101
|
-
|
|
102
|
-
src_link = ""
|
|
103
|
-
target_dir = os.getcwd()
|
|
104
|
-
log_dir = os.getcwd()
|
|
105
|
-
|
|
106
|
-
try:
|
|
107
|
-
args = parser.parse_args()
|
|
108
|
-
except SystemExit:
|
|
109
|
-
sys.exit(0)
|
|
110
|
-
|
|
111
|
-
if args.help:
|
|
112
|
-
print_help_msg_download()
|
|
113
|
-
if args.source:
|
|
114
|
-
src_link = args.source
|
|
115
|
-
if args.target_dir:
|
|
116
|
-
target_dir = args.target_dir
|
|
117
|
-
if args.log_dir:
|
|
118
|
-
log_dir = args.log_dir
|
|
119
|
-
|
|
120
|
-
if not src_link:
|
|
121
|
-
print_help_msg_download()
|
|
122
|
-
else:
|
|
123
|
-
cli_download_and_extract(src_link, target_dir, log_dir)
|
|
124
|
-
|
|
125
|
-
|
|
126
97
|
def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_to: str = "",
|
|
127
|
-
compressed_only: bool = False
|
|
98
|
+
compressed_only: bool = False, ssh_key: str = "",
|
|
99
|
+
id: str = "", git_token: str = "",
|
|
100
|
+
called_cli: bool = True,
|
|
101
|
+
output: bool = False) -> Tuple[bool, str, str, str]:
|
|
128
102
|
global logger
|
|
129
103
|
|
|
130
104
|
success = True
|
|
@@ -136,6 +110,7 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
|
|
|
136
110
|
datetime.now().strftime('%Y%m%d_%H-%M-%S')+".txt"
|
|
137
111
|
logger, log_item = init_log(os.path.join(log_dir, log_file_name))
|
|
138
112
|
link = link.strip()
|
|
113
|
+
is_rubygems = False
|
|
139
114
|
|
|
140
115
|
try:
|
|
141
116
|
if not link:
|
|
@@ -144,6 +119,9 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
|
|
|
144
119
|
elif os.path.isfile(target_dir):
|
|
145
120
|
success = False
|
|
146
121
|
msg = f"The target directory exists as a file.: {target_dir}"
|
|
122
|
+
elif os.path.exists(link) or os.path.isdir(link) or os.path.isfile(link):
|
|
123
|
+
success = False
|
|
124
|
+
msg = f"You cannot enter a path instead of a link.: {link}"
|
|
147
125
|
else:
|
|
148
126
|
src_info = parse_src_link(link)
|
|
149
127
|
link = src_info.get("url", "")
|
|
@@ -152,12 +130,18 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
|
|
|
152
130
|
is_rubygems = src_info.get("rubygems", False)
|
|
153
131
|
|
|
154
132
|
# General download (git clone, wget)
|
|
155
|
-
success_git, msg, oss_name, oss_version = download_git_clone(link, target_dir,
|
|
133
|
+
success_git, msg, oss_name, oss_version = download_git_clone(link, target_dir,
|
|
134
|
+
checkout_to,
|
|
135
|
+
tag, branch,
|
|
136
|
+
ssh_key, id, git_token,
|
|
137
|
+
called_cli)
|
|
138
|
+
link = change_ssh_link_to_https(link)
|
|
156
139
|
if (not is_rubygems) and (not success_git):
|
|
157
140
|
if os.path.isfile(target_dir):
|
|
158
141
|
shutil.rmtree(target_dir)
|
|
159
142
|
|
|
160
|
-
success, downloaded_file, msg_wget, oss_name, oss_version = download_wget(link, target_dir,
|
|
143
|
+
success, downloaded_file, msg_wget, oss_name, oss_version = download_wget(link, target_dir,
|
|
144
|
+
compressed_only, checkout_to)
|
|
161
145
|
if success:
|
|
162
146
|
success = extract_compressed_file(downloaded_file, target_dir, True, compressed_only)
|
|
163
147
|
# Download from rubygems.org
|
|
@@ -177,6 +161,17 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
|
|
|
177
161
|
success = False
|
|
178
162
|
msg = str(error)
|
|
179
163
|
|
|
164
|
+
if output:
|
|
165
|
+
output_result = {
|
|
166
|
+
"success": success,
|
|
167
|
+
"message": msg,
|
|
168
|
+
"oss_name": oss_name,
|
|
169
|
+
"oss_version": oss_version
|
|
170
|
+
}
|
|
171
|
+
output_json = os.path.join(log_dir, "fosslight_download_output.json")
|
|
172
|
+
with open(output_json, 'w') as f:
|
|
173
|
+
json.dump(output_result, f, indent=4)
|
|
174
|
+
|
|
180
175
|
logger.info(f"\n* FOSSLight Downloader - Result: {success} ({msg})")
|
|
181
176
|
return success, msg, oss_name, oss_version
|
|
182
177
|
|
|
@@ -200,15 +195,60 @@ def get_ref_to_checkout(checkout_to, ref_list):
|
|
|
200
195
|
return ref_to_checkout
|
|
201
196
|
|
|
202
197
|
|
|
203
|
-
def
|
|
204
|
-
if
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
198
|
+
def get_remote_refs(git_url: str):
|
|
199
|
+
if not git_url:
|
|
200
|
+
return {"tags": [], "branches": []}
|
|
201
|
+
tags = []
|
|
202
|
+
branches = []
|
|
203
|
+
try:
|
|
204
|
+
cp = subprocess.run(["git", "ls-remote", "--tags", "--heads", git_url], capture_output=True, text=True, timeout=30)
|
|
205
|
+
if cp.returncode == 0:
|
|
206
|
+
for line in cp.stdout.splitlines():
|
|
207
|
+
parts = line.split('\t')
|
|
208
|
+
if len(parts) != 2:
|
|
209
|
+
continue
|
|
210
|
+
ref = parts[1]
|
|
211
|
+
if ref.startswith('refs/tags/'):
|
|
212
|
+
tags.append(ref[len('refs/tags/'):])
|
|
213
|
+
elif ref.startswith('refs/heads/'):
|
|
214
|
+
branches.append(ref[len('refs/heads/'):])
|
|
215
|
+
except Exception as e:
|
|
216
|
+
logger.debug(f"get_remote_refs - failed: {e}")
|
|
217
|
+
return {"tags": tags, "branches": branches}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def decide_checkout(checkout_to="", tag="", branch="", git_url=""):
|
|
221
|
+
base = checkout_to or tag or branch
|
|
222
|
+
if not base:
|
|
223
|
+
return ""
|
|
224
|
+
|
|
225
|
+
ref_dict = get_remote_refs(git_url)
|
|
226
|
+
tag_set = set(ref_dict.get("tags", []))
|
|
227
|
+
branch_set = set(ref_dict.get("branches", []))
|
|
228
|
+
|
|
229
|
+
ver_re = re.compile(r'^(?:v\.? ?)?' + re.escape(base) + r'$', re.IGNORECASE)
|
|
230
|
+
|
|
231
|
+
# tag: exact -> prefix variant -> endswith
|
|
232
|
+
if base in tag_set:
|
|
233
|
+
return base
|
|
234
|
+
tag_candidates = [c for c in tag_set if ver_re.match(c)]
|
|
235
|
+
if tag_candidates:
|
|
236
|
+
return min(tag_candidates, key=lambda x: (len(x), x.lower()))
|
|
237
|
+
tag_ends = [n for n in tag_set if n.endswith(base)]
|
|
238
|
+
if tag_ends:
|
|
239
|
+
return min(tag_ends, key=len)
|
|
240
|
+
|
|
241
|
+
# branch: exact -> prefix variant -> endswith
|
|
242
|
+
if base in branch_set:
|
|
243
|
+
return base
|
|
244
|
+
branch_candidates = [c for c in branch_set if ver_re.match(c)]
|
|
245
|
+
if branch_candidates:
|
|
246
|
+
return min(branch_candidates, key=lambda x: (len(x), x.lower()))
|
|
247
|
+
branch_ends = [n for n in branch_set if n.endswith(base)]
|
|
248
|
+
if branch_ends:
|
|
249
|
+
return min(branch_ends, key=len)
|
|
250
|
+
|
|
251
|
+
return base
|
|
212
252
|
|
|
213
253
|
|
|
214
254
|
def get_github_ossname(link):
|
|
@@ -229,15 +269,48 @@ def get_github_token(git_url):
|
|
|
229
269
|
return github_token
|
|
230
270
|
|
|
231
271
|
|
|
232
|
-
def
|
|
233
|
-
|
|
234
|
-
msg = ""
|
|
235
|
-
oss_name = get_github_ossname(git_url)
|
|
272
|
+
def download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli=True):
|
|
273
|
+
success = False
|
|
236
274
|
oss_version = ""
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
275
|
+
|
|
276
|
+
logger.info(f"Download git url :{git_url}")
|
|
277
|
+
env = os.environ.copy()
|
|
278
|
+
if not called_cli:
|
|
279
|
+
env["GIT_TERMINAL_PROMPT"] = "0"
|
|
280
|
+
if refs_to_checkout:
|
|
281
|
+
try:
|
|
282
|
+
# gitPython uses the branch argument the same whether you check out to a branch or a tag.
|
|
283
|
+
Repo.clone_from(git_url, target_dir, branch=refs_to_checkout, env=env)
|
|
284
|
+
if any(Path(target_dir).iterdir()):
|
|
285
|
+
success = True
|
|
286
|
+
oss_version = refs_to_checkout
|
|
287
|
+
logger.info(f"Files found in {target_dir} after clone.")
|
|
288
|
+
else:
|
|
289
|
+
logger.info(f"No files found in {target_dir} after clone.")
|
|
290
|
+
success = False
|
|
291
|
+
except GitCommandError as error:
|
|
292
|
+
logger.info(f"Git checkout error:{error}")
|
|
293
|
+
success = False
|
|
294
|
+
except Exception as e:
|
|
295
|
+
logger.info(f"Repo.clone_from error:{e}")
|
|
296
|
+
success = False
|
|
297
|
+
|
|
298
|
+
if not success:
|
|
299
|
+
Repo.clone_from(git_url, target_dir, env=env)
|
|
300
|
+
if any(Path(target_dir).iterdir()):
|
|
301
|
+
success = True
|
|
302
|
+
else:
|
|
303
|
+
logger.info(f"No files found in {target_dir} after clone.")
|
|
304
|
+
success = False
|
|
305
|
+
return success, oss_version
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def download_git_clone(git_url, target_dir, checkout_to="", tag="", branch="",
|
|
309
|
+
ssh_key="", id="", git_token="", called_cli=True):
|
|
310
|
+
oss_name = get_github_ossname(git_url)
|
|
311
|
+
refs_to_checkout = decide_checkout(checkout_to, tag, branch, git_url)
|
|
312
|
+
msg = ""
|
|
313
|
+
success = True
|
|
241
314
|
|
|
242
315
|
try:
|
|
243
316
|
if platform.system() != "Windows":
|
|
@@ -248,34 +321,45 @@ def download_git_clone(git_url, target_dir, checkout_to="", tag="", branch=""):
|
|
|
248
321
|
alarm.start()
|
|
249
322
|
|
|
250
323
|
Path(target_dir).mkdir(parents=True, exist_ok=True)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
signal.alarm(0)
|
|
324
|
+
|
|
325
|
+
if git_url.startswith("ssh:") and not ssh_key:
|
|
326
|
+
msg = "Private git needs ssh_key"
|
|
327
|
+
success = False
|
|
256
328
|
else:
|
|
257
|
-
|
|
329
|
+
if ssh_key:
|
|
330
|
+
logger.info(f"Download git with ssh_key:{git_url}")
|
|
331
|
+
git_ssh_cmd = f'ssh -i {ssh_key}'
|
|
332
|
+
with Git().custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
|
|
333
|
+
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli)
|
|
334
|
+
else:
|
|
335
|
+
if id and git_token:
|
|
336
|
+
try:
|
|
337
|
+
m = re.match(r"^(ht|f)tp(s?)\:\/\/", git_url)
|
|
338
|
+
protocol = m.group()
|
|
339
|
+
if protocol:
|
|
340
|
+
encoded_git_token = urllib.parse.quote(git_token, safe='')
|
|
341
|
+
encoded_id = urllib.parse.quote(id, safe='')
|
|
342
|
+
git_url = git_url.replace(protocol, f"{protocol}{encoded_id}:{encoded_git_token}@")
|
|
343
|
+
except Exception as error:
|
|
344
|
+
logger.info(f"Failed to insert id, token to git url:{error}")
|
|
345
|
+
success, oss_version = download_git_repository(refs_to_checkout, git_url, target_dir, tag, called_cli)
|
|
346
|
+
|
|
347
|
+
logger.info(f"git checkout: {oss_version}")
|
|
348
|
+
refs_to_checkout = oss_version
|
|
349
|
+
|
|
350
|
+
if platform.system() != "Windows":
|
|
351
|
+
signal.alarm(0)
|
|
352
|
+
else:
|
|
353
|
+
del alarm
|
|
258
354
|
except Exception as error:
|
|
355
|
+
success = False
|
|
259
356
|
logger.warning(f"git clone - failed: {error}")
|
|
260
357
|
msg = str(error)
|
|
261
|
-
return False, msg, oss_name, oss_version
|
|
262
|
-
try:
|
|
263
|
-
if ref_to_checkout != "":
|
|
264
|
-
ref_list = [x for x in repo.references]
|
|
265
|
-
ref_to_checkout = get_ref_to_checkout(ref_to_checkout, ref_list)
|
|
266
|
-
logger.info(f"git checkout: {ref_to_checkout}")
|
|
267
|
-
repo.checkout(ref_to_checkout)
|
|
268
|
-
|
|
269
|
-
for prefix_ref in prefix_refs:
|
|
270
|
-
if ref_to_checkout.startswith(prefix_ref):
|
|
271
|
-
oss_version = ref_to_checkout[len(prefix_ref):]
|
|
272
358
|
|
|
273
|
-
|
|
274
|
-
logger.warning(f"git checkout to {ref_to_checkout} - failed: {error}")
|
|
275
|
-
return True, msg, oss_name, oss_version
|
|
359
|
+
return success, msg, oss_name, refs_to_checkout
|
|
276
360
|
|
|
277
361
|
|
|
278
|
-
def download_wget(link, target_dir, compressed_only):
|
|
362
|
+
def download_wget(link, target_dir, compressed_only, checkout_to):
|
|
279
363
|
success = False
|
|
280
364
|
msg = ""
|
|
281
365
|
oss_name = ""
|
|
@@ -292,7 +376,7 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
292
376
|
|
|
293
377
|
Path(target_dir).mkdir(parents=True, exist_ok=True)
|
|
294
378
|
|
|
295
|
-
ret, new_link, oss_name, oss_version = get_downloadable_url(link)
|
|
379
|
+
ret, new_link, oss_name, oss_version, pkg_type = get_downloadable_url(link, checkout_to)
|
|
296
380
|
if ret and new_link:
|
|
297
381
|
link = new_link
|
|
298
382
|
|
|
@@ -301,6 +385,9 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
301
385
|
if link.endswith(ext):
|
|
302
386
|
success = True
|
|
303
387
|
break
|
|
388
|
+
if not success:
|
|
389
|
+
if pkg_type == 'cargo':
|
|
390
|
+
success = True
|
|
304
391
|
else:
|
|
305
392
|
success = True
|
|
306
393
|
|
|
@@ -308,7 +395,11 @@ def download_wget(link, target_dir, compressed_only):
|
|
|
308
395
|
raise Exception('Not supported compression type (link:{0})'.format(link))
|
|
309
396
|
|
|
310
397
|
logger.info(f"wget: {link}")
|
|
311
|
-
|
|
398
|
+
if pkg_type == 'cargo':
|
|
399
|
+
outfile = os.path.join(target_dir, f'{oss_name}.tar.gz')
|
|
400
|
+
downloaded_file = wget.download(link, out=outfile)
|
|
401
|
+
else:
|
|
402
|
+
downloaded_file = wget.download(link, target_dir)
|
|
312
403
|
if platform.system() != "Windows":
|
|
313
404
|
signal.alarm(0)
|
|
314
405
|
else:
|
|
@@ -357,6 +448,8 @@ def extract_compressed_file(fname, extract_path, remove_after_extract=True, comp
|
|
|
357
448
|
unzip(fname, extract_path)
|
|
358
449
|
elif fname.endswith(".bz2"):
|
|
359
450
|
decompress_bz2(fname, extract_path)
|
|
451
|
+
elif fname.endswith(".whl"):
|
|
452
|
+
unzip(fname, extract_path)
|
|
360
453
|
else:
|
|
361
454
|
is_compressed_file = False
|
|
362
455
|
if compressed_only:
|
|
@@ -443,5 +536,51 @@ def gem_download(link, target_dir, checkout_to):
|
|
|
443
536
|
return success
|
|
444
537
|
|
|
445
538
|
|
|
539
|
+
def main():
|
|
540
|
+
parser = argparse.ArgumentParser(description='FOSSLight Downloader', prog='fosslight_download', add_help=False)
|
|
541
|
+
parser.add_argument('-h', '--help', help='Print help message', action='store_true', dest='help')
|
|
542
|
+
parser.add_argument('-s', '--source', help='Source link to download', type=str, dest='source')
|
|
543
|
+
parser.add_argument('-t', '--target_dir', help='Target directory', type=str, dest='target_dir', default="")
|
|
544
|
+
parser.add_argument('-d', '--log_dir', help='Directory to save log file', type=str, dest='log_dir', default="")
|
|
545
|
+
parser.add_argument('-c', '--checkout_to', help='Checkout to branch or tag', type=str, dest='checkout_to', default="")
|
|
546
|
+
parser.add_argument('-z', '--compressed_only', help='Unzip only compressed file',
|
|
547
|
+
action='store_true', dest='compressed_only', default=False)
|
|
548
|
+
parser.add_argument('-o', '--output', help='Generate output file', action='store_true', dest='output', default=False)
|
|
549
|
+
|
|
550
|
+
src_link = ""
|
|
551
|
+
target_dir = os.getcwd()
|
|
552
|
+
log_dir = os.getcwd()
|
|
553
|
+
checkout_to = ""
|
|
554
|
+
compressed_only = False
|
|
555
|
+
output = False
|
|
556
|
+
|
|
557
|
+
try:
|
|
558
|
+
args = parser.parse_args()
|
|
559
|
+
except SystemExit:
|
|
560
|
+
sys.exit(0)
|
|
561
|
+
|
|
562
|
+
if args.help:
|
|
563
|
+
print_help_msg_download()
|
|
564
|
+
if args.source:
|
|
565
|
+
src_link = args.source
|
|
566
|
+
if args.target_dir:
|
|
567
|
+
target_dir = args.target_dir
|
|
568
|
+
if args.log_dir:
|
|
569
|
+
log_dir = args.log_dir
|
|
570
|
+
if args.checkout_to:
|
|
571
|
+
checkout_to = args.checkout_to
|
|
572
|
+
if args.compressed_only:
|
|
573
|
+
compressed_only = args.compressed_only
|
|
574
|
+
if args.output:
|
|
575
|
+
output = args.output
|
|
576
|
+
|
|
577
|
+
if not src_link:
|
|
578
|
+
print_help_msg_download()
|
|
579
|
+
else:
|
|
580
|
+
cli_download_and_extract(src_link, target_dir, log_dir, checkout_to,
|
|
581
|
+
compressed_only, "", "", "", False,
|
|
582
|
+
output)
|
|
583
|
+
|
|
584
|
+
|
|
446
585
|
if __name__ == '__main__':
|
|
447
586
|
main()
|
|
@@ -0,0 +1,65 @@
|
|
|
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 fnmatch
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def excluding_files(patterns: List[str], path_to_scan: str) -> List[str]:
|
|
12
|
+
excluded_paths = set()
|
|
13
|
+
|
|
14
|
+
# Normalize patterns: e.g., 'sample/', 'sample/*' -> 'sample'
|
|
15
|
+
# Replace backslash with slash
|
|
16
|
+
normalized_patterns = []
|
|
17
|
+
for pattern in patterns:
|
|
18
|
+
pattern = pattern.replace('\\', '/')
|
|
19
|
+
if pattern.endswith('/') or pattern.endswith('/*'):
|
|
20
|
+
pattern = pattern.rstrip('/*')
|
|
21
|
+
normalized_patterns.append(pattern)
|
|
22
|
+
|
|
23
|
+
# Traverse directories
|
|
24
|
+
for root, dirs, files in os.walk(path_to_scan):
|
|
25
|
+
remove_dir_list = []
|
|
26
|
+
|
|
27
|
+
# (1) Directory matching
|
|
28
|
+
for d in dirs:
|
|
29
|
+
dir_name = d
|
|
30
|
+
dir_path = os.path.relpath(os.path.join(root, d), path_to_scan).replace('\\', '/')
|
|
31
|
+
matched = False
|
|
32
|
+
|
|
33
|
+
for pat in normalized_patterns:
|
|
34
|
+
# Match directory name
|
|
35
|
+
if fnmatch.fnmatch(dir_name, pat):
|
|
36
|
+
matched = True
|
|
37
|
+
|
|
38
|
+
# Match the full relative path
|
|
39
|
+
if not matched:
|
|
40
|
+
if fnmatch.fnmatch(dir_path, pat) or fnmatch.fnmatch(dir_path, pat + "/*"):
|
|
41
|
+
matched = True
|
|
42
|
+
|
|
43
|
+
# If matched, exclude all files under this directory and stop checking patterns
|
|
44
|
+
if matched:
|
|
45
|
+
sub_root_path = os.path.join(root, d)
|
|
46
|
+
for sr, _, sf in os.walk(sub_root_path):
|
|
47
|
+
for sub_file in sf:
|
|
48
|
+
sub_file_path = os.path.relpath(os.path.join(sr, sub_file), path_to_scan)
|
|
49
|
+
excluded_paths.add(sub_file_path.replace('\\', '/'))
|
|
50
|
+
remove_dir_list.append(d)
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
# (1-2) Prune matched directories from further traversal
|
|
54
|
+
for rd in remove_dir_list:
|
|
55
|
+
dirs.remove(rd)
|
|
56
|
+
|
|
57
|
+
# (2) File matching
|
|
58
|
+
for f in files:
|
|
59
|
+
file_path = os.path.relpath(os.path.join(root, f), path_to_scan).replace('\\', '/')
|
|
60
|
+
for pat in normalized_patterns:
|
|
61
|
+
if fnmatch.fnmatch(file_path, pat) or fnmatch.fnmatch(file_path, pat + "/*"):
|
|
62
|
+
excluded_paths.add(file_path)
|
|
63
|
+
break
|
|
64
|
+
|
|
65
|
+
return sorted(excluded_paths)
|
fosslight_util/help.py
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
# Copyright (c) 2021 LG Electronics Inc.
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
import sys
|
|
6
|
-
|
|
6
|
+
try:
|
|
7
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
8
|
+
except ImportError:
|
|
9
|
+
from importlib_metadata import version, PackageNotFoundError # Python <3.8
|
|
7
10
|
|
|
8
11
|
_HELP_MESSAGE_COMMON = """
|
|
9
12
|
_______ _______ _______ _______ ___ ___ __
|
|
@@ -31,7 +34,12 @@ _HELP_MESSAGE_DOWNLOAD = """
|
|
|
31
34
|
Optional:
|
|
32
35
|
-h\t\t Print help message
|
|
33
36
|
-t\t\t Output path name
|
|
34
|
-
-d\t\t Directory name to save the log file
|
|
37
|
+
-d\t\t Directory name to save the log file
|
|
38
|
+
-s\t\t Source link to download
|
|
39
|
+
-t\t\t Directory to download source code
|
|
40
|
+
-c\t\t Checkout to branch or tag/ or version
|
|
41
|
+
-z\t\t Unzip only compressed file
|
|
42
|
+
-o\t\t Generate summary output file with this option"""
|
|
35
43
|
|
|
36
44
|
|
|
37
45
|
class PrintHelpMsg():
|
|
@@ -50,7 +58,10 @@ class PrintHelpMsg():
|
|
|
50
58
|
def print_package_version(pkg_name: str, msg: str = "", exitopt: bool = True) -> str:
|
|
51
59
|
if msg == "":
|
|
52
60
|
msg = f"{pkg_name} Version:"
|
|
53
|
-
|
|
61
|
+
try:
|
|
62
|
+
cur_version = version(pkg_name)
|
|
63
|
+
except PackageNotFoundError:
|
|
64
|
+
cur_version = "unknown"
|
|
54
65
|
|
|
55
66
|
if exitopt:
|
|
56
67
|
print(f'{msg} {cur_version}')
|
fosslight_util/oss_item.py
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
+
import hashlib
|
|
8
9
|
from fosslight_util.constant import LOGGER_NAME, FOSSLIGHT_SCANNER
|
|
9
10
|
from fosslight_util.cover import CoverItem
|
|
10
11
|
from typing import List, Dict
|
|
11
12
|
|
|
12
13
|
_logger = logging.getLogger(LOGGER_NAME)
|
|
14
|
+
CHECKSUM_NULL = "0"
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
class OssItem:
|
|
@@ -58,10 +60,12 @@ class OssItem:
|
|
|
58
60
|
|
|
59
61
|
@copyright.setter
|
|
60
62
|
def copyright(self, value):
|
|
61
|
-
if value
|
|
63
|
+
if value:
|
|
62
64
|
if isinstance(value, list):
|
|
63
|
-
value =
|
|
64
|
-
|
|
65
|
+
value = list(set(value))
|
|
66
|
+
else:
|
|
67
|
+
value = set(value.split("\n"))
|
|
68
|
+
value = "\n".join(value).strip()
|
|
65
69
|
self._copyright = value
|
|
66
70
|
|
|
67
71
|
@property
|
|
@@ -98,6 +102,7 @@ class FileItem:
|
|
|
98
102
|
self._comment = ""
|
|
99
103
|
self.is_binary = False
|
|
100
104
|
self.oss_items: List[OssItem] = []
|
|
105
|
+
self.checksum = CHECKSUM_NULL
|
|
101
106
|
|
|
102
107
|
def __del__(self):
|
|
103
108
|
pass
|
|
@@ -169,6 +174,22 @@ class FileItem:
|
|
|
169
174
|
return items
|
|
170
175
|
|
|
171
176
|
|
|
177
|
+
def get_checksum_sha1(source_name_or_path) -> str:
|
|
178
|
+
checksum = CHECKSUM_NULL
|
|
179
|
+
try:
|
|
180
|
+
checksum = str(hashlib.sha1(source_name_or_path.encode()).hexdigest())
|
|
181
|
+
except Exception:
|
|
182
|
+
try:
|
|
183
|
+
f = open(source_name_or_path, "rb")
|
|
184
|
+
byte = f.read()
|
|
185
|
+
checksum = str(hashlib.sha1(byte).hexdigest())
|
|
186
|
+
f.close()
|
|
187
|
+
except Exception as ex:
|
|
188
|
+
_logger.info(f"(Error) Get_checksum: {ex}")
|
|
189
|
+
|
|
190
|
+
return checksum
|
|
191
|
+
|
|
192
|
+
|
|
172
193
|
def invalid(cmd):
|
|
173
194
|
_logger.info('[{}] is invalid'.format(cmd))
|
|
174
195
|
|