Skip to content

Commit 26070ab

Browse files
committed
Fixed #22 - Add support to collect redistributable sources
1 parent f65d6a4 commit 26070ab

File tree

10 files changed

+97
-23
lines changed

10 files changed

+97
-23
lines changed

docs/CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Release 5.1.0
33

44
* Add support for `package_url` #396
5+
* Add support to collect redistributable sources #22
56

67
2020-08-11
78
Release 5.0.0

src/attributecode/model.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,9 @@ def process(self, fields, about_file_path, running_inventory=False,
935935
errors = self.hydrate(fields)
936936
# We want to copy the license_files before the validation
937937
if reference_dir:
938-
copy_license_notice_files(
938+
copy_err = copy_license_notice_files(
939939
fields, base_dir, reference_dir, afp)
940+
errors.extend(copy_err)
940941

941942
# TODO: why? we validate all fields, not only these hydrated
942943
validation_errors = validate_fields(
@@ -1278,21 +1279,26 @@ def copy_redist_src(abouts, location, output):
12781279
errors = []
12791280
for about in abouts:
12801281
if about.redistribute.value:
1282+
file_exist = True
12811283
for e in about.errors:
12821284
if 'Field about_resource' in e.message and 'not found' in e.message:
12831285
msg = e.message + u' and cannot be copied.'
12841286
errors.append(Error(CRITICAL, msg))
1287+
file_exist = False
12851288
continue
1286-
for k in about.about_resource.value:
1287-
from_path = about.about_resource.value.get(k)
1288-
norm_from_path = norm(from_path)
1289-
relative_from_path = norm_from_path.partition(util.norm(location))[2]
1290-
# Need to strip the '/' to use the join
1291-
if relative_from_path.startswith('/'):
1292-
relative_from_path = relative_from_path.partition('/')[2]
1293-
# Get the directory name of the output path
1294-
output_dir = os.path.dirname(os.path.join(output, util.norm(relative_from_path)))
1295-
copy_file(from_path, output_dir)
1289+
if file_exist:
1290+
for k in about.about_resource.value:
1291+
from_path = about.about_resource.value.get(k)
1292+
norm_from_path = norm(from_path)
1293+
relative_from_path = norm_from_path.partition(util.norm(location))[2]
1294+
# Need to strip the '/' to use the join
1295+
if relative_from_path.startswith('/'):
1296+
relative_from_path = relative_from_path.partition('/')[2]
1297+
# Get the directory name of the output path
1298+
output_dir = os.path.dirname(os.path.join(output, util.norm(relative_from_path)))
1299+
err = copy_file(from_path, output_dir)
1300+
if err:
1301+
errors.extend(err)
12961302
return errors
12971303

12981304

src/attributecode/util.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ def copy_license_notice_files(fields, base_dir, reference_dir, afp):
436436
about_file_path value, this function will copy to the base_dir the
437437
license_file or notice_file if found in the reference_dir
438438
"""
439+
errors = []
439440
copy_file_name = ''
440441
for key, value in fields:
441442
if key == 'license_file' or key == 'notice_file':
@@ -470,13 +471,16 @@ def copy_license_notice_files(fields, base_dir, reference_dir, afp):
470471
about_file_dir = os.path.dirname(to_posix(afp)).lstrip('/')
471472
to_lic_path = posixpath.join(to_posix(base_dir), about_file_dir)
472473

473-
copy_file(from_lic_path, to_lic_path)
474+
err = copy_file(from_lic_path, to_lic_path)
475+
if err:
476+
errors.append(err)
477+
return errors
474478

475479

476480
def copy_file(from_path, to_path):
477481
# Return if the from_path is empty or None.
478482
if not from_path:
479-
return
483+
return []
480484

481485
if on_windows:
482486
if not from_path.startswith(UNC_PREFIXES):
@@ -490,7 +494,7 @@ def copy_file(from_path, to_path):
490494

491495
# Errors will be captured when doing the validation
492496
if not posixpath.exists(from_path):
493-
return
497+
return []
494498

495499
if not posixpath.exists(to_path):
496500
os.makedirs(to_path)
@@ -501,14 +505,17 @@ def copy_file(from_path, to_path):
501505
to_path = os.path.join(to_path, folder_name)
502506
# Since we need to copy everything along with the directory structure,
503507
# making sure the directory does not exist will not hurt.
504-
shutil.rmtree(to_path)
508+
if os.path.exists(to_path):
509+
shutil.rmtree(to_path)
505510
# Copy the directory recursively along with its structure
506511
shutil.copytree(from_path, to_path)
507512
else:
508513
shutil.copy2(from_path, to_path)
514+
return []
509515
except Exception as e:
510-
print(repr(e))
511-
print('Cannot copy file at %(from_path)r.' % locals())
516+
msg = 'Cannot copy file at %(from_path)r.' % locals()
517+
error = [Error(CRITICAL, msg)]
518+
return error
512519

513520

514521
# FIXME: we should use a license object instead

tests/test_model.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,21 @@ def test_collect_inventory_does_not_convert_lf_to_crlf_from_directory(self):
12101210
expected = get_test_loc('test_model/crlf/expected.csv')
12111211
check_csv(expected, result, fix_cell_linesep=True, regen=False)
12121212

1213+
def test_copy_redist_src(self):
1214+
test_loc = get_test_loc('test_model/redistribution')
1215+
output = get_temp_dir()
1216+
errors, abouts = model.collect_inventory(test_loc)
1217+
expected_file = ['this.c']
1218+
1219+
err = model.copy_redist_src(abouts, test_loc, output)
1220+
assert err == []
1221+
1222+
from os import listdir
1223+
copied_files = listdir(output)
1224+
assert len(expected_file) == len(copied_files)
1225+
assert err == []
1226+
for file in expected_file:
1227+
assert file in copied_files
12131228

12141229
class FetchLicenseTest(unittest.TestCase):
12151230

tests/test_util.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,3 +628,37 @@ def test_copy_license_notice_files(self):
628628
assert len(licenses) == len(copied_files)
629629
for license in licenses:
630630
assert license in copied_files
631+
632+
def test_copy_file(self):
633+
des = get_temp_dir()
634+
test_file = get_test_loc('test_util/licenses/mit.LICENSE')
635+
licenses = ['mit.LICENSE']
636+
err = util.copy_file(test_file, des)
637+
from os import listdir
638+
copied_files = listdir(des)
639+
assert len(licenses) == len(copied_files)
640+
assert err == []
641+
for license in licenses:
642+
assert license in copied_files
643+
644+
def test_copy_file_with_dir(self):
645+
des = get_temp_dir()
646+
test_dir = get_test_loc('test_util/licenses/')
647+
licenses = ['mit.LICENSE', 'mit2.LICENSE', 'public-domain.LICENSE']
648+
err = util.copy_file(test_dir, des)
649+
assert err == []
650+
651+
import os
652+
files_list = []
653+
dir_list = []
654+
# Get the directories and files in the 'des' recursively
655+
for root, dir, files in os.walk(des):
656+
for d in dir:
657+
dir_list.append(d)
658+
for f in files:
659+
files_list.append(f)
660+
661+
assert dir_list == [u'licenses']
662+
assert len(licenses) == len(files_list)
663+
for license in licenses:
664+
assert license in files_list

tests/testdata/test_cmd/help/about_help.txt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ Options:
1313
-h, --help Show this message and exit.
1414

1515
Commands:
16-
attrib Generate an attribution document from .ABOUT files.
17-
check Validate that the format of .ABOUT files is correct and report
18-
errors and warnings.
19-
gen Generate .ABOUT files from an inventory as CSV or JSON.
20-
inventory Collect the inventory of .ABOUT files to a CSV or JSON file.
21-
transform Transform a CSV/JSON by applying renamings, filters and checks.
16+
attrib Generate an attribution document from .ABOUT files.
17+
check Validate that the format of .ABOUT files is correct and
18+
report errors and warnings.
19+
collect_redist_src Collect redistributable sources.
20+
gen Generate .ABOUT files from an inventory as CSV or JSON.
21+
inventory Collect the inventory of .ABOUT files to a CSV or JSON
22+
file.
23+
transform Transform a CSV/JSON by applying renamings, filters and
24+
checks.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
about_resource: this.c
2+
name: this.c
3+
version: 0.11.0
4+
redistribute: x

tests/testdata/test_model/redistribution/this.c

Whitespace-only changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
about_resource: this.c
2+
name: this.c
3+
version: 0.11.0
4+
redistribute: N

tests/testdata/test_model/redistribution/this2.c

Whitespace-only changes.

0 commit comments

Comments
 (0)