Skip to content

Commit 7199996

Browse files
authored
Merge pull request #113 from fosslight/develop
Exclude untracked files and ignored files in lint mode
2 parents 4367feb + 28e52ae commit 7199996

File tree

3 files changed

+82
-17
lines changed

3 files changed

+82
-17
lines changed

src/fosslight_prechecker/_help.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
-p <path>\t\t Path to check(Default: current directory)
2626
-f <format>\t\t Result format(yaml, xml, html)
2727
-o <file_name>\t Output file name
28-
-n\t\t\t Don't exclude venv*, node_modules, and .*/ from the analysis
2928
-i\t\t\t Don't both write log file and show progress bar
3029
--notice\t\t Print the open source license notice text.
3130
31+
Option for only 'lint' mode
32+
-n\t\t\t Don't exclude venv*, node_modules, .*/, and the result of FOSSLight Scanners from the analysis
33+
3234
Options for only 'add' mode
3335
-l <license>\t License name(SPDX format) to add
3436
-c <copyright>\t Copyright to add(ex, 2015-2021 LG Electronics Inc.)"""

src/fosslight_prechecker/_precheck.py

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import locale
1010
import platform
1111
import re
12+
import subprocess
1213
from datetime import datetime
1314
from binaryornot.check import is_binary
1415
import fosslight_util.constant as constant
@@ -17,13 +18,14 @@
1718
from reuse import report
1819
from reuse.project import Project
1920
from reuse.report import ProjectReport
21+
from reuse.vcs import VCSStrategyGit
2022
from fosslight_prechecker._result import write_result_file, create_result_file, result_for_summary, ResultItem
2123
from fosslight_prechecker._constant import DEFAULT_EXCLUDE_EXTENSION, OSS_PKG_INFO_FILES, PKG_NAME
2224

2325
is_windows = platform.system() == 'Windows'
2426
REUSE_CONFIG_FILE = ".reuse/dep5"
2527
DEFAULT_EXCLUDE_EXTENSION_FILES = [] # Exclude files from reuse
26-
_turn_on_default_reuse_config = True
28+
_turn_on_exclude_config = True
2729
_check_only_file_mode = False
2830
error_items = []
2931
_start_time = ""
@@ -32,12 +34,61 @@
3234
logger = logging.getLogger(constant.LOGGER_NAME)
3335

3436

35-
def find_oss_pkg_info(path):
37+
def exclude_untracked_files(path):
38+
global DEFAULT_EXCLUDE_EXTENSION_FILES
39+
try:
40+
cmd_result = subprocess.check_output(['git', 'ls-files', '-o', f'{path}'], universal_newlines=True)
41+
cmd_result = cmd_result.split('\n')
42+
cmd_result.remove('')
43+
if not path.endswith("/"):
44+
path += "/"
45+
cmd_result = [file.replace(path, '', 1) for file in cmd_result]
46+
DEFAULT_EXCLUDE_EXTENSION_FILES.extend(cmd_result)
47+
except Exception as ex:
48+
logger.error(f"Error to get git untracked files : {ex}")
49+
50+
51+
def exclude_gitignore_files(path):
52+
global DEFAULT_EXCLUDE_EXTENSION_FILES
53+
try:
54+
cmd_result = subprocess.check_output(['git',
55+
'ls-files',
56+
'-i',
57+
f"--exclude-from={os.path.join(path, '.gitignore')}"],
58+
universal_newlines=True)
59+
cmd_result = cmd_result.split('\n')
60+
cmd_result.remove('')
61+
if not path.endswith("/"):
62+
path += "/"
63+
cmd_result = [file.replace(path, '', 1) for file in cmd_result]
64+
DEFAULT_EXCLUDE_EXTENSION_FILES.extend(cmd_result)
65+
except Exception as ex:
66+
logger.error(f"Error to get git ignored files : {ex}")
67+
68+
69+
def find_oss_pkg_info_and_exlcude_file(path):
3670
global DEFAULT_EXCLUDE_EXTENSION_FILES
3771
oss_pkg_info = []
72+
git_present = shutil.which("git")
73+
74+
# Exlcude untracked files
75+
if _turn_on_exclude_config and git_present and VCSStrategyGit.in_repo(path):
76+
exclude_untracked_files(path)
77+
# Exclude all files from .gitignore
78+
if os.path.isfile(os.path.join(path, '.gitignore')):
79+
exclude_gitignore_files(path)
3880

3981
try:
4082
for root, dirs, files in os.walk(path):
83+
for dir in dirs:
84+
# For hidden folders
85+
if dir.startswith("."):
86+
all_files_in_dir = [os.path.join(root, dir, file)
87+
for file in os.listdir(os.path.join(root, dir))
88+
if os.path.isfile(os.path.join(root, dir, file))]
89+
all_files_rel_path = [os.path.relpath(file, path) for file in all_files_in_dir]
90+
DEFAULT_EXCLUDE_EXTENSION_FILES.extend(all_files_rel_path)
91+
4192
for file in files:
4293
file_lower_case = file.lower()
4394
file_abs_path = os.path.join(root, file)
@@ -46,6 +97,9 @@ def find_oss_pkg_info(path):
4697
if any(re.search(re_oss_pkg_pattern, file_lower_case) for re_oss_pkg_pattern in OSS_PKG_INFO_FILES) \
4798
or file_lower_case.startswith("module_license_"):
4899
oss_pkg_info.append(file_rel_path)
100+
# Exclude hidden files
101+
elif _turn_on_exclude_config and file.startswith('.'):
102+
DEFAULT_EXCLUDE_EXTENSION_FILES.append(file_rel_path)
49103
elif is_binary(file_abs_path):
50104
if is_windows:
51105
file_rel_path = file_rel_path.replace(os.sep, '/')
@@ -56,14 +110,14 @@ def find_oss_pkg_info(path):
56110
if is_windows:
57111
file_rel_path = file_rel_path.replace(os.sep, '/')
58112
DEFAULT_EXCLUDE_EXTENSION_FILES.append(file_rel_path)
59-
60113
except Exception as ex:
61114
dump_error_msg(f"Error_FIND_OSS_PKG : {ex}")
62115

63116
return oss_pkg_info
64117

65118

66119
def create_reuse_dep5_file(path):
120+
global DEFAULT_EXCLUDE_EXTENSION_FILES
67121
# Create .reuse/dep5 for excluding directories from reuse.
68122
_DEFAULT_CONFIG_PREFIX = "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: \
69123
reuse\nUpstream-Contact: Carmen Bianca Bakker <[email protected]>\nSource: https://github.com/fsfe/reuse-tool\n"
@@ -86,7 +140,8 @@ def create_reuse_dep5_file(path):
86140
need_rollback = True
87141

88142
DEFAULT_EXCLUDE_EXTENSION_FILES.extend(_DEFAULT_EXCLUDE_FOLDERS)
89-
for file_to_exclude in DEFAULT_EXCLUDE_EXTENSION_FILES:
143+
exclude_file_list = list(set(DEFAULT_EXCLUDE_EXTENSION_FILES))
144+
for file_to_exclude in exclude_file_list:
90145
str_contents += f"\nFiles: {file_to_exclude} \nCopyright: -\nLicense: -\n"
91146

92147
with open(reuse_config_file, "a") as f:
@@ -161,8 +216,8 @@ def precheck_for_project(path_to_find):
161216
missing_license = []
162217
missing_copyright = []
163218

164-
oss_pkg_info_files = find_oss_pkg_info(path_to_find)
165-
if _turn_on_default_reuse_config:
219+
oss_pkg_info_files = find_oss_pkg_info_and_exlcude_file(path_to_find)
220+
if _turn_on_exclude_config:
166221
need_rollback, temp_file_name, temp_dir_name = create_reuse_dep5_file(path_to_find)
167222

168223
try:
@@ -183,7 +238,7 @@ def precheck_for_project(path_to_find):
183238
except Exception as ex:
184239
dump_error_msg(f"Error prechecker lint: {ex}", True)
185240

186-
if _turn_on_default_reuse_config:
241+
if _turn_on_exclude_config:
187242
remove_reuse_dep5_file(need_rollback, temp_file_name, temp_dir_name)
188243
return missing_license, missing_copyright, oss_pkg_info_files, project, report
189244

@@ -234,7 +289,7 @@ def get_path_to_find(target_path, _check_only_file_mode):
234289

235290

236291
def run_lint(target_path, disable, output_file_name, format='', need_log_file=True):
237-
global _turn_on_default_reuse_config, _check_only_file_mode, _start_time
292+
global _turn_on_exclude_config, _check_only_file_mode, _start_time
238293

239294
file_to_check_list = []
240295
_exit_code = 0
@@ -256,7 +311,7 @@ def run_lint(target_path, disable, output_file_name, format='', need_log_file=Tr
256311

257312
if os.path.isdir(path_to_find):
258313
oss_pkg_info = []
259-
_turn_on_default_reuse_config = not disable
314+
_turn_on_exclude_config = not disable
260315

261316
if need_log_file:
262317
# Use ProgressBar
@@ -268,6 +323,7 @@ def run_lint(target_path, disable, output_file_name, format='', need_log_file=Tr
268323
license_missing_files, copyright_missing_files, project = precheck_for_files(path_to_find, file_to_check_list)
269324
else:
270325
license_missing_files, copyright_missing_files, oss_pkg_info, project, report = precheck_for_project(path_to_find)
326+
271327
if need_log_file:
272328
timer.stop = True
273329

@@ -279,7 +335,8 @@ def run_lint(target_path, disable, output_file_name, format='', need_log_file=Tr
279335
_result_log,
280336
_check_only_file_mode,
281337
file_to_check_list,
282-
error_items)
338+
error_items,
339+
DEFAULT_EXCLUDE_EXTENSION_FILES)
283340

284341
success, exit_code = write_result_file(result_file, output_extension, _exit_code,
285342
result_item, _result_log, project, path_to_find)

src/fosslight_prechecker/_result.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
import xml.etree.ElementTree as ET
1111
import logging
1212
import fosslight_util.constant as constant
13+
import re
1314
from pathlib import Path
1415
from reuse.project import Project
1516
from fosslight_prechecker._result_html import result_for_html
1617
from fosslight_util.parsing_yaml import find_sbom_yaml_files, parsing_yml
1718
from fosslight_util.output_format import check_output_format
18-
import re
1919

2020

2121
CUSTOMIZED_FORMAT_FOR_PRECHECKER = {'html': '.html', 'xml': '.xml', 'yaml': '.yaml'}
@@ -262,16 +262,22 @@ def exclude_file_in_yaml(path_to_find, yaml_files, license_missing_files, copyri
262262

263263

264264
def result_for_summary(path_to_find, oss_pkg_info_files, license_missing_files, copyright_missing_files,
265-
prj_report, _result_log, _check_only_file_mode, file_to_check_list, error_items):
265+
prj_report, _result_log, _check_only_file_mode, file_to_check_list, error_items, exclude_files):
266266
prechecker_compliant = False
267267
detected_lic = []
268268
missing_both_files = []
269-
file_total = ""
269+
file_total_num = ""
270+
total_files_exclude = ()
270271

271272
if _check_only_file_mode:
272-
file_total = len(file_to_check_list)
273+
file_total_num = len(file_to_check_list)
273274
else:
274-
file_total = len(prj_report.file_reports)
275+
if not path_to_find.endswith('/'):
276+
path_to_find += '/'
277+
total_files = [str(file_report.path).replace(path_to_find, '', 1) for file_report in prj_report.file_reports]
278+
total_files_exclude = set(total_files) - set(exclude_files)
279+
file_total_num = len(total_files_exclude)
280+
275281
# Get detected License
276282
for i, lic in enumerate(sorted(prj_report.used_licenses)):
277283
detected_lic.append(lic)
@@ -296,7 +302,7 @@ def result_for_summary(path_to_find, oss_pkg_info_files, license_missing_files,
296302
result_item.compliant_result = prechecker_compliant
297303
result_item._oss_pkg_files = oss_pkg_info_files
298304
result_item._detected_licenses = detected_lic
299-
result_item._count_total_files = file_total
305+
result_item._count_total_files = file_total_num
300306
result_item._count_without_both = str(len(missing_both_files))
301307
result_item._count_without_lic = str(len(license_missing_files) + len(missing_both_files))
302308
result_item._count_without_cop = str(len(copyright_missing_files) + len(missing_both_files))

0 commit comments

Comments
 (0)