Scancode: Fix false positive reported by scancode output analyser script

ScanCode can possibly return many licenses found for a single file scanned.
This commit ensures that the file is not reported as lacking a permissive license
if at least one license found in it is permissive.
Previously the script was reporting an issue if it found at least one license
in a file that was not permissive.

Additionally catch more errors and provide specific details about failures.
Provide unitest.
pull/13745/head
Hugues Kamba 2020-10-07 21:18:07 +01:00
parent 6fa88f4247
commit 4ce6c8ac62
7 changed files with 1277 additions and 1244 deletions

View File

@ -70,7 +70,7 @@ matrix:
| ( grep -v '^tools/test/toolchains/api_test.py' || true ) \
| while read file; do cp --parents "${file}" SCANCODE; done
- scancode -l --json-pp scancode.json SCANCODE
- python ./tools/test/travis-ci/scancode-evaluate.py -f scancode.json || true
- python ./tools/test/travis-ci/scancode-evaluate.py scancode.json || true
# run the same but for new files. All new files must have SPDX
- >-
git diff --name-only --diff-filter=A FETCH_HEAD..HEAD \
@ -78,10 +78,10 @@ matrix:
| ( grep -v '^tools/test/toolchains/api_test.py' || true ) \
| while read file; do cp --parents "${file}" SCANCODE_NEW_FILES; done
- scancode -l --json-pp scancode_new_files.json SCANCODE_NEW_FILES
- python ./tools/test/travis-ci/scancode-evaluate.py -f scancode_new_files.json || true
- python ./tools/test/travis-ci/scancode-evaluate.py scancode_new_files.json || true
- cat scancode-evaluate.log
- COUNT=$(cat scancode-evaluate.log | grep 'File:' | wc -l) || true
- python ./tools/test/travis-ci/scancode-evaluate.py -f scancode_new_files.json
- python ./tools/test/travis-ci/scancode-evaluate.py scancode_new_files.json
- cat scancode-evaluate.log
- COUNT_NEW_FILES=$(cat scancode-evaluate.log | grep 'File:' | wc -l) || true
- |

View File

@ -13,137 +13,152 @@ Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations
limitations
"""
# Asumptions for this script:
# 1. directory_name is scanned directory.
# Files are copied to this directory with full tree. As result, if we find
# license offender, we can have full path (just scrape directory_name). We do this
# magic because scancode allows to scan directories/one file.
# 2. SPDX and license text is a must for all code files
import json
import argparse
import sys
import os.path
import json
import logging
import os.path
import re
userlog = logging.getLogger("scancode-evaluate")
userlog.setLevel(logging.INFO)
logfile = os.path.join(os.getcwd(), 'scancode-evaluate.log')
log_file_handler = logging.FileHandler(logfile, mode='w')
userlog.addHandler(log_file_handler)
import sys
from enum import Enum
MISSING_LICENSE_TEXT = "Missing license header"
MISSING_PERMISIVE_LICENSE_TEXT = "Non-permissive license"
MISSING_PERMISSIVE_LICENSE_TEXT = "Non-permissive license"
MISSING_SPDX_TEXT = "Missing SPDX license identifier"
def license_check(directory_name, file):
""" Check licenses in the scancode json file for specified directory
userlog = logging.getLogger("scancode-evaluate")
class ReturnCode(Enum):
"""Return codes."""
SUCCESS = 0
ERROR = -1
def init_logger():
"""Initialise the logger."""
userlog.setLevel(logging.INFO)
userlog.addHandler(
logging.FileHandler(
os.path.join(os.getcwd(), 'scancode-evaluate.log'), mode='w'
)
)
def path_leaf(path):
"""Return the leaf of a path."""
head, tail = os.path.split(path)
# Ensure the correct file name is returned if the file ends with a slash
return tail or os.path.basename(head)
def has_permissive_text_in_scancode_output(scancode_output_data_file_licenses):
"""Returns true if at list one license in the scancode output is permissive."""
return any(
scancode_output_data_file_license['category'] == 'Permissive'
for scancode_output_data_file_license in scancode_output_data_file_licenses
)
def has_spdx_text_in_scancode_output(scancode_output_data_file_licenses):
"""Returns true if at least one license in the scancode output has the spdx identifier."""
return any(
'spdx' in scancode_output_data_file_license['matched_rule']['identifier']
for scancode_output_data_file_license in scancode_output_data_file_licenses
)
def has_spdx_text_in_analysed_file(scanned_file_content):
"""Returns true if the file analysed by ScanCode contains SPDX identifier."""
return bool(re.findall("SPDX-License-Identifier:?", scanned_file_content))
def license_check(scancode_output_path):
"""Check licenses in the scancode json file for specified directory.
This function does not verify if file exists, should be done prior the call.
Args:
directory_name - where scancode was run, used to scrape this from paths
file - scancode json output file (output from scancode --license --json-pp)
scancode_output_path: path to the scancode json output file (output from scancode --license --json-pp)
Returns:
0 if nothing found
>0 - count how many license isses found
-1 if any error in file licenses found
ReturnCode.ERROR.value if any error in file licenses found
"""
offenders = []
try:
# find all licenses in the files, must be licensed and permissive
with open(file, 'r') as scancode_output:
results = json.load(scancode_output)
except ValueError:
userlog.warning("JSON could not be decoded")
return -1
with open(scancode_output_path, 'r') as read_file:
scancode_output_data = json.load(read_file)
except json.JSONDecodeError as jex:
userlog.warning("JSON could not be decoded, Invalid JSON in body: %s", jex)
return ReturnCode.ERROR.value
try:
for file in results['files']:
license_offender = {}
license_offender['file'] = file
# ignore directory, not relevant here
if license_offender['file']['type'] == 'directory':
continue
if not license_offender['file']['licenses']:
license_offender['reason'] = MISSING_LICENSE_TEXT
offenders.append(license_offender.copy())
if 'files' not in scancode_output_data:
userlog.warning("Missing `files` attribute in %s" % (scancode_output_path))
return ReturnCode.ERROR.value
for scancode_output_data_file in scancode_output_data['files']:
if scancode_output_data_file['type'] != 'file':
continue
if not scancode_output_data_file['licenses']:
scancode_output_data_file['fail_reason'] = MISSING_LICENSE_TEXT
offenders.append(scancode_output_data_file)
# check the next file in the scancode output
continue
if not has_permissive_text_in_scancode_output(scancode_output_data_file['licenses']):
scancode_output_data_file['fail_reason'] = MISSING_PERMISSIVE_LICENSE_TEXT
offenders.append(scancode_output_data_file)
if not has_spdx_text_in_scancode_output(scancode_output_data_file['licenses']):
# Scancode does not recognize license notice in Python file headers.
# Issue: https://github.com/nexB/scancode-toolkit/issues/1913
# Therefore check if the file tested by ScanCode actually has a licence notice.
file_path = os.path.abspath(scancode_output_data_file['path'])
try:
with open(file_path, 'r') as read_file:
scanned_file_content = read_file.read()
except UnicodeDecodeError:
userlog.warning("Unable to look for SPDX text in `{}`:".format(file_path))
# Ignore files that cannot be decoded
# check the next file in the scancode output
continue
found_spdx = spdx_check(offenders, license_offender)
if not found_spdx:
try:
# Issue reported here https://github.com/nexB/scancode-toolkit/issues/1913
# We verify here if SPDX is not really there as SDPX is part of the license text
# scancode has some problems detecting it properly
with open(os.path.join(os.path.abspath(license_offender['file']['path'])), 'r') as spdx_file_check:
filetext = spdx_file_check.read()
matches = re.findall("SPDX-License-Identifier:?", filetext)
if matches:
continue
license_offender['reason'] = MISSING_SPDX_TEXT
offenders.append(license_offender.copy())
except UnicodeDecodeError:
# not valid file for license check
continue
except KeyError:
userlog.warning("Invalid scancode json file")
return -1
if not has_spdx_text_in_analysed_file(scanned_file_content):
scancode_output_data_file['fail_reason'] = MISSING_SPDX_TEXT
offenders.append(scancode_output_data_file)
if offenders:
userlog.warning("Found files with missing license details, please review and fix")
for offender in offenders:
userlog.warning("File: " + offender['file']['path'][len(directory_name):] + " " + "reason: " + offender['reason'])
userlog.warning("File: %s reason: %s" % (path_leaf(offender['path']), offender['fail_reason']))
return len(offenders)
def spdx_check(offenders, license_offender):
""" Parse through list of licenses to determine whether licenses are permissive
@input list of offender, individual offender dict
@output none
"""
found_spdx = False
# iterate through licenses, stop once permissive license has been found
for i in range(len(license_offender['file']['licenses'])):
# is any of the licenses permissive ?
if license_offender['file']['licenses'][i]['category'] == 'Permissive':
# confirm that it has spdx license key
if license_offender['file']['licenses'][i]['matched_rule']['identifier'].find("spdx") != -1:
found_spdx = True
# if no spdx found return anyway
return found_spdx
# otherwise file is missing permissive license
license_offender['reason'] = MISSING_PERMISIVE_LICENSE_TEXT
offenders.append(license_offender.copy())
# missing spdx and permissive license
return found_spdx
def parse_args():
parser = argparse.ArgumentParser(
description="License check.")
parser.add_argument('-f', '--file',
help="scancode-toolkit output json file")
parser.add_argument('-d', '--directory_name', default="SCANCODE",
help='Directory name where are files being checked')
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description="License check.")
parser.add_argument(
'scancode_output_path',
help="scancode-toolkit output json file"
)
return parser.parse_args()
if __name__ == "__main__":
init_logger()
args = parse_args()
if args.file and os.path.isfile(args.file):
count = license_check(args.directory_name, args.file)
if count == 0:
sys.exit(0)
else:
sys.exit(-1)
if os.path.isfile(args.scancode_output_path):
sys.exit(
ReturnCode.SUCCESS.value
if license_check(args.scancode_output_path) == 0
else ReturnCode.ERROR.value
)
else:
userlog.warning("Could not find the scancode json file")
sys.exit(-1)
sys.exit(ReturnCode.ERROR.value)

View File

@ -4,29 +4,23 @@
# SPDX-License-Identifier: Apache-2.0
import importlib
import os
import sys
from unittest import TestCase
import pytest
# TODO: fix scancode to match python naming conventROOTi
SCANCODE_EVALUATE = importlib.import_module("scancode-evaluate")
license_check = SCANCODE_EVALUATE.license_check
license_check = importlib.import_module("scancode-evaluate").license_check
ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__))
STUBS_PATH = os.path.join(
os.path.abspath(os.path.join(os.path.dirname(__file__))), "scancode_test"
)
# path to stub files
stub_path = ROOT + "/scancode_test/"
# template copyright notices
invalid_header_1 = "/* Copyright (C) Arm Limited, Inc - All Rights Reserved\
HEADER_WITHOUT_SPDX = "/* Copyright (C) Arm Limited, Inc - All Rights Reserved\
* Unauthorized copying of this. file, via any medium is strictly prohibited\
* Proprietary and confidential\
*/"
invalid_header_2 = "/* mbed Microcontroller Library\
HEADER_WITH_SPDX = "/* mbed Microcontroller Library\
* Copyright (c) 2006-2013 ARM Limited\
*\
* SPDX-License-Identifier: Apache-2.0\
* Licensed under the Apache License, Version 2.0 (the \"License\");\
* you may not use this file except in compliance with the License.\
* You may obtain a copy of the License at\
@ -40,67 +34,62 @@ invalid_header_2 = "/* mbed Microcontroller Library\
* limitations under the License.\
*/"
@pytest.fixture()
def create_scanned_files():
"""Create stub files.
test3.h missing license notice
test4.h with license notice
test5.h with license notice
"""
file_paths = [
os.path.join(STUBS_PATH, "test3.h"),
os.path.join(STUBS_PATH, "test4.h"),
os.path.join(STUBS_PATH, "test5.h")
]
for file_path in file_paths:
with open(file_path, "w") as new_file:
if file_path in [os.path.join(STUBS_PATH, "test3.h")]:
new_file.write(HEADER_WITHOUT_SPDX)
else:
new_file.write(HEADER_WITH_SPDX)
yield
for file_path in file_paths:
os.remove(file_path)
# implement test class
class TestScancodeEvaluate(TestCase):
""" Test scancode evaluation script """
def test_scancode_case_1(self):
""" Test Case 1 -- faulty json file
@inputs scancode_test_1.json
@outputs -1 if any error in file licenses found
"""
expected_result = -1
test_json = ROOT + "/scancode_test/scancode_test_1.json"
class TestScancodeEvaluate:
# pass json path to test function
result = license_check(ROOT, test_json)
def test_missing_files_attribute(self):
""" Missing `files` attribute in JSON.
@inputs scancode_test/scancode_test_1.json
@outputs -1
"""
assert license_check(os.path.join(STUBS_PATH, "scancode_test_1.json")) == -1
self.assertEqual(expected_result, result)
def test_various_combinations_permissive_license_with_spdx(self):
""" Various combinations where at least one license in
a file is permissive and has spdx in the match.identifier
attribute.
@inputs scancode_test/scancode_test_2.json
@outputs 0
"""
assert license_check(os.path.join(STUBS_PATH, "scancode_test_2.json")) == 0
def test_scancode_case_2(self):
""" Test Case 2 -- no errors in license headers, try multiple types i.e Apache-2.0, BSD3
@inputs scancode_test_2.json [4 Apache-2.0, 4 BSD-3.0]
@outputs 0
"""
expected_result = 0
test_json = ROOT + "/scancode_test/scancode_test_2.json"
def test_missing_license_permissive_license_and_spdx(self, create_scanned_files):
""" Test four files scanned with various issues.
test.h: Missing license text (error count += 1)
test3.h: Missing `Permissive` license text and `spdx` in match.identifier and not in file tested by ScanCode (error count += 2)
test4.h: Missing `Permissive` license text and `spdx` in match.identifier but found in file tested by ScanCode (error count += 1)
test5.h: Missing `spdx` in match.identifier but found in file tested by ScanCode. (error count += 0)
@inputs scancode_test/scancode_test_2.json
@output 4
"""
assert license_check(os.path.join(STUBS_PATH, "scancode_test_3.json")) == 4
result = license_check(ROOT, test_json)
self.assertEqual(expected_result, result, "False Negative(s)")
def test_scancode_case_3(self):
""" Test Case 3 -- all files containing errors
@inputs scancode_test_3.json [2 no header, 2 non-permissive + spdx, 1 missing SPDX]
@output 5
"""
# create stub files with a non-permissive license and missing spdx
for i in range(3, 6):
with open(stub_path + "test" + str(i) + ".h", "w") as file:
if i == 5:
file.write(invalid_header_2)
else:
file.write(invalid_header_1)
expected_result = 7
test_json = ROOT + "/scancode_test/scancode_test_3.json"
result = license_check(ROOT, test_json)
self.assertEqual(expected_result, result, "False Positive(s)")
# delete stub files
os.remove(stub_path + "test3.h")
os.remove(stub_path + "test4.h")
os.remove(stub_path + "test5.h")
def test_scancode_case_4(self):
""" Test Case 4 -- license header permissive and non-permissive 'license' [FP]
@inputs scancode_test_4.json
@outputs 0
"""
expected_result = 0
test_json = ROOT + "/scancode_test/scancode_test_4.json"
result = license_check(ROOT, test_json)
self.assertEqual(expected_result, result, "Non-Permissive Header False Positive")
def test_permissive_license_no_spdx(self, create_scanned_files):
""" Multiple `Permissive` licenses in one file but none with `spdx` in
match.identifier and not in file tested by ScanCode (error count += 1)
@inputs scancode_test/scancode_test_2.json
@outputs 1
"""
assert license_check(os.path.join(STUBS_PATH, "scancode_test_4.json")) == 1

View File

@ -1,7 +1,7 @@
{
"headers": [
{
"tool_name": "scancode test fail"
}
]
}
"headers": [
{
"tool_name": "scancode test fail"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,169 +1,176 @@
{
"headers": [
{
"tool_name": "scancode-toolkit",
"tool_version": "3.1.1",
"options": {
"input": [
"tools/test/travis-ci/scancode_test/test.h",
"tools/test/travis-ci/scancode_test/test2.h",
"tools/test/travis-ci/scancode_test/test3.h",
"tools/test/travis-ci/scancode_test/test4.h",
"tools/test/travis-ci/scancode_test/test5.h"
"headers":[
{
"tool_name":"scancode-toolkit",
"tool_version":"3.1.1",
"options":{
"input":[
"tools/test/travis-ci/scancode_test/test.h",
"tools/test/travis-ci/scancode_test/test2.h",
"tools/test/travis-ci/scancode_test/test3.h",
"tools/test/travis-ci/scancode_test/test4.h",
"tools/test/travis-ci/scancode_test/test5.h"
],
"--json-pp":"scancode.json",
"--license":true
},
"notice":"Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
"start_timestamp":"2020-10-01T135040.106260",
"end_timestamp":"2020-10-01T135047.793497",
"message":null,
"errors":[
],
"--json-pp": "scancode.json",
"--license": true
},
"notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
"start_timestamp": "2020-10-01T135040.106260",
"end_timestamp": "2020-10-01T135047.793497",
"message": null,
"errors": [],
"extra_data": {
"files_count": 5
}
}
"extra_data":{
"files_count":5
}
}
],
"files": [
{
"path": "tools/test/travis-ci/scancode_test/test.h",
"type": "file",
"licenses": [],
"license_expressions": [],
"scan_errors": []
},
{
"path": "tools/test/travis-ci/scancode_test/test2.h",
"type": "file",
"licenses": [],
"license_expressions": [],
"scan_errors": []
},
{
"path": "tools/test/travis-ci/scancode_test/test3.h",
"type": "file",
"licenses": [
{
"key": "proprietary-license",
"score": 77.0,
"name": "Proprietary License",
"short_name": "Proprietary License",
"category": "Proprietary Free",
"is_exception": false,
"owner": "Unspecified",
"homepage_url": null,
"text_url": "",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:proprietary-license",
"spdx_license_key": null,
"spdx_url": "",
"start_line": 2,
"end_line": 3,
"matched_rule": {
"identifier": "proprietary_12.RULE",
"license_expression": "proprietary-license",
"licenses": [
"proprietary-license"
],
"is_license_text": false,
"is_license_notice": true,
"is_license_reference": false,
"is_license_tag": false,
"matcher": "2-aho",
"rule_length": 14,
"matched_length": 14,
"match_coverage": 100.0,
"rule_relevance": 77
}
}
],
"license_expressions": [
"proprietary-license"
],
"scan_errors": []
},
{
"path": "tools/test/travis-ci/scancode_test/test4.h",
"type": "file",
"licenses": [
{
"key": "proprietary-license",
"score": 77.0,
"name": "Proprietary License",
"short_name": "Proprietary License",
"category": "Proprietary Free",
"is_exception": false,
"owner": "Unspecified",
"homepage_url": null,
"text_url": "",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:proprietary-license",
"spdx_license_key": null,
"spdx_url": "",
"start_line": 2,
"end_line": 3,
"matched_rule": {
"identifier": "proprietary_12.RULE",
"license_expression": "proprietary-license",
"licenses": [
"proprietary-license"
],
"is_license_text": false,
"is_license_notice": true,
"is_license_reference": false,
"is_license_tag": false,
"matcher": "2-aho",
"rule_length": 14,
"matched_length": 14,
"match_coverage": 100.0,
"rule_relevance": 77
}
}
],
"license_expressions": [
"proprietary-license"
],
"scan_errors": []
},
{
"path": "tools/test/travis-ci/scancode_test/test5.h",
"type": "file",
"licenses": [
{
"key": "apache-2.0",
"score": 100.0,
"name": "Apache License 2.0",
"short_name": "Apache 2.0",
"category": "Permissive",
"is_exception": false,
"owner": "Apache Software Foundation",
"homepage_url": "http://www.apache.org/licenses/",
"text_url": "http://www.apache.org/licenses/LICENSE-2.0",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:apache-2.0",
"spdx_license_key": "Apache-2.0",
"spdx_url": "https://spdx.org/licenses/Apache-2.0",
"start_line": 4,
"end_line": 14,
"matched_rule": {
"identifier": "apache-2.0_7.RULE",
"license_expression": "apache-2.0",
"licenses": [
"apache-2.0"
],
"is_license_text": false,
"is_license_notice": true,
"is_license_reference": false,
"is_license_tag": false,
"matcher": "2-aho",
"rule_length": 85,
"matched_length": 85,
"match_coverage": 100.0,
"rule_relevance": 100
"files":[
{
"path":"tools/test/travis-ci/scancode_test/test.h",
"type":"file",
"licenses":[
],
"license_expressions":[
],
"scan_errors":[
]
},
{
"path":"tools/test/travis-ci/scancode_test/test3.h",
"type":"file",
"licenses":[
{
"key":"proprietary-license",
"score":77.0,
"name":"Proprietary License",
"short_name":"Proprietary License",
"category":"Proprietary Free",
"is_exception":false,
"owner":"Unspecified",
"homepage_url":null,
"text_url":"",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:proprietary-license",
"spdx_license_key":null,
"spdx_url":"",
"start_line":2,
"end_line":3,
"matched_rule":{
"identifier":"proprietary_12.RULE",
"license_expression":"proprietary-license",
"licenses":[
"proprietary-license"
],
"is_license_text":false,
"is_license_notice":true,
"is_license_reference":false,
"is_license_tag":false,
"matcher":"2-aho",
"rule_length":14,
"matched_length":14,
"match_coverage":100.0,
"rule_relevance":77
}
}
],
"license_expressions":[
"proprietary-license"
],
"scan_errors":[
]
},
{
"path":"tools/test/travis-ci/scancode_test/test4.h",
"type":"file",
"licenses":[
{
"key":"proprietary-license",
"score":77.0,
"name":"Proprietary License",
"short_name":"Proprietary License",
"category":"Proprietary Free",
"is_exception":false,
"owner":"Unspecified",
"homepage_url":null,
"text_url":"",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:proprietary-license",
"spdx_license_key":null,
"spdx_url":"",
"start_line":2,
"end_line":3,
"matched_rule":{
"identifier":"proprietary_12.RULE",
"license_expression":"proprietary-license",
"licenses":[
"proprietary-license"
],
"is_license_text":false,
"is_license_notice":true,
"is_license_reference":false,
"is_license_tag":false,
"matcher":"2-aho",
"rule_length":14,
"matched_length":14,
"match_coverage":100.0,
"rule_relevance":77
}
}
],
"license_expressions":[
"proprietary-license"
],
"scan_errors":[
]
},
{
"path":"tools/test/travis-ci/scancode_test/test5.h",
"type":"file",
"licenses":[
{
"key":"apache-2.0",
"score":100.0,
"name":"Apache License 2.0",
"short_name":"Apache 2.0",
"category":"Permissive",
"is_exception":false,
"owner":"Apache Software Foundation",
"homepage_url":"http://www.apache.org/licenses/",
"text_url":"http://www.apache.org/licenses/LICENSE-2.0",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:apache-2.0",
"spdx_license_key":"Apache-2.0",
"spdx_url":"https://spdx.org/licenses/Apache-2.0",
"start_line":4,
"end_line":14,
"matched_rule":{
"identifier":"apache-2.0_7.RULE",
"license_expression":"apache-2.0",
"licenses":[
"apache-2.0"
],
"is_license_text":false,
"is_license_notice":true,
"is_license_reference":false,
"is_license_tag":false,
"matcher":"2-aho",
"rule_length":85,
"matched_length":85,
"match_coverage":100.0,
"rule_relevance":100
}
}
],
"license_expressions": [
"apache-2.0"
],
"scan_errors": []
}
}
],
"license_expressions":[
"apache-2.0"
],
"scan_errors":[
]
}
]
}

View File

@ -1,166 +1,170 @@
{
"headers": [
{
"tool_name": "scancode-toolkit",
"tool_version": "3.1.1",
"options": {
"input": [
"test.h"
],
"--json-pp": "scancode.json",
"--license": true
"headers":[
{
"tool_name":"scancode-toolkit",
"tool_version":"3.1.1",
"options":{
"input":[
"test4.h"
],
"--json-pp":"scancode.json",
"--license":true
},
"notice": "Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
"start_timestamp": "2020-10-01T135040.106260",
"end_timestamp": "2020-10-01T135047.793497",
"message": null,
"errors": [],
"extra_data": {
"files_count": 1
"notice":"Generated with ScanCode and provided on an \"AS IS\" BASIS, WITHOUT WARRANTIES\nOR CONDITIONS OF ANY KIND, either express or implied. No content created from\nScanCode should be considered or used as legal advice. Consult an Attorney\nfor any legal advice.\nScanCode is a free software code scanning tool from nexB Inc. and others.\nVisit https://github.com/nexB/scancode-toolkit/ for support and download.",
"start_timestamp":"2020-10-01T135040.106260",
"end_timestamp":"2020-10-01T135047.793497",
"message":null,
"errors":[
],
"extra_data":{
"files_count":1
}
}
],
"files": [
{
"path": "tools/test/travis-ci/scancode_test/test.h",
"type": "file",
"licenses": [
{
"key": "bsd-new",
"score": 100.0,
"name": "BSD-3-Clause",
"short_name": "BSD-3-Clause",
"category": "Permissive",
"is_exception": false,
"owner": "Regents of the University of California",
"homepage_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"text_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key": "BSD-3-Clause",
"spdx_url": "https://spdx.org/licenses/BSD-3-Clause",
"start_line": 2,
"end_line": 2,
"matched_rule": {
"identifier": "spdx-license-identifier: bsd-new",
"license_expression": "bsd-new",
"licenses": [
"bsd-new"
],
"is_license_text": false,
"is_license_notice": false,
"is_license_reference": false,
"is_license_tag": true,
"matcher": "1-spdx-id",
"rule_length": 3,
"matched_length": 3,
"match_coverage": 100.0,
"rule_relevance": 100
}
},
{
"key": "bsd-new",
"score": 100.0,
"name": "BSD-3-Clause",
"short_name": "BSD-3-Clause",
"category": "Permissive",
"is_exception": false,
"owner": "Regents of the University of California",
"homepage_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"text_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key": "BSD-3-Clause",
"spdx_url": "https://spdx.org/licenses/BSD-3-Clause",
"start_line": 8,
"end_line": 8,
"matched_rule": {
"identifier": "bsd-new_360.RULE",
"license_expression": "bsd-new",
"licenses": [
"bsd-new"
],
"is_license_text": false,
"is_license_notice": false,
"is_license_reference": true,
"is_license_tag": false,
"matcher": "2-aho",
"rule_length": 4,
"matched_length": 4,
"match_coverage": 100.0,
"rule_relevance": 100.0
}
},
{
"key": "elastic-license-2018",
"score": 72.22,
"name": "Elastic License Agreement 2018",
"short_name": "Elastic License 2018",
"category": "Source-available",
"is_exception": false,
"owner": "Elastic",
"homepage_url": "https://github.com/elastic/elasticsearch/blob/0d8aa7527e242fbda9d84867ab8bc955758eebce/licenses/ELASTIC-LICENSE.txt",
"text_url": "https://github.com/elastic/elasticsearch/blob/0d8aa7527e242fbda9d84867ab8bc955758eebce/licenses/ELASTIC-LICENSE.txt",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:elastic-license-2018",
"spdx_license_key": null,
"spdx_url": "",
"start_line": 9,
"end_line": 10,
"matched_rule": {
"identifier": "elastic_1.RULE",
"license_expression": "elastic-license-2018",
"licenses": [
"elastic-license-2018"
],
"is_license_text": false,
"is_license_notice": true,
"is_license_reference": false,
"is_license_tag": false,
"matcher": "3-seq",
"rule_length": 18,
"matched_length": 13,
"match_coverage": 72.22,
"rule_relevance": 100.0
}
},
{
"key": "bsd-new",
"score": 100.0,
"name": "BSD-3-Clause",
"short_name": "BSD-3-Clause",
"category": "Permissive",
"is_exception": false,
"owner": "Regents of the University of California",
"homepage_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"text_url": "http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url": "https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key": "BSD-3-Clause",
"spdx_url": "https://spdx.org/licenses/BSD-3-Clause",
"start_line": 11,
"end_line": 11,
"matched_rule": {
"identifier": "bsd-new_10.RULE",
"license_expression": "bsd-new",
"licenses": [
"bsd-new"
],
"is_license_text": false,
"is_license_notice": false,
"is_license_reference": true,
"is_license_tag": false,
"matcher": "2-aho",
"rule_length": 3,
"matched_length": 3,
"match_coverage": 100.0,
"rule_relevance": 100.0
}
}
}
],
"files":[
{
"path":"tools/test/travis-ci/scancode_test/test3.h",
"type":"file",
"licenses":[
{
"key":"bsd-new",
"score":100.0,
"name":"BSD-3-Clause",
"short_name":"BSD-3-Clause",
"category":"Permissive",
"is_exception":false,
"owner":"Regents of the University of California",
"homepage_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"text_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key":"BSD-3-Clause",
"spdx_url":"https://spdx.org/licenses/BSD-3-Clause",
"start_line":2,
"end_line":2,
"matched_rule":{
"identifier":"sprdx-license-identifier: bsd-new",
"license_expression":"bsd-new",
"licenses":[
"bsd-new"
],
"is_license_text":false,
"is_license_notice":false,
"is_license_reference":false,
"is_license_tag":true,
"matcher":"1-spdx-id",
"rule_length":3,
"matched_length":3,
"match_coverage":100.0,
"rule_relevance":100
}
},
{
"key":"bsd-new",
"score":100.0,
"name":"BSD-3-Clause",
"short_name":"BSD-3-Clause",
"category":"Permissive",
"is_exception":false,
"owner":"Regents of the University of California",
"homepage_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"text_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key":"BSD-3-Clause",
"spdx_url":"https://spdx.org/licenses/BSD-3-Clause",
"start_line":8,
"end_line":8,
"matched_rule":{
"identifier":"bsd-new_360.RULE",
"license_expression":"bsd-new",
"licenses":[
"bsd-new"
],
"is_license_text":false,
"is_license_notice":false,
"is_license_reference":true,
"is_license_tag":false,
"matcher":"2-aho",
"rule_length":4,
"matched_length":4,
"match_coverage":100.0,
"rule_relevance":100.0
}
},
{
"key":"elastic-license-2018",
"score":72.22,
"name":"Elastic License Agreement 2018",
"short_name":"Elastic License 2018",
"category":"Source-available",
"is_exception":false,
"owner":"Elastic",
"homepage_url":"https://github.com/elastic/elasticsearch/blob/0d8aa7527e242fbda9d84867ab8bc955758eebce/licenses/ELASTIC-LICENSE.txt",
"text_url":"https://github.com/elastic/elasticsearch/blob/0d8aa7527e242fbda9d84867ab8bc955758eebce/licenses/ELASTIC-LICENSE.txt",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:elastic-license-2018",
"spdx_license_key":null,
"spdx_url":"",
"start_line":9,
"end_line":10,
"matched_rule":{
"identifier":"elastic_1.RULE",
"license_expression":"elastic-license-2018",
"licenses":[
"elastic-license-2018"
],
"is_license_text":false,
"is_license_notice":true,
"is_license_reference":false,
"is_license_tag":false,
"matcher":"3-seq",
"rule_length":18,
"matched_length":13,
"match_coverage":72.22,
"rule_relevance":100.0
}
},
{
"key":"bsd-new",
"score":100.0,
"name":"BSD-3-Clause",
"short_name":"BSD-3-Clause",
"category":"Permissive",
"is_exception":false,
"owner":"Regents of the University of California",
"homepage_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"text_url":"http://www.opensource.org/licenses/BSD-3-Clause",
"reference_url":"https://enterprise.dejacode.com/urn/urn:dje:license:bsd-new",
"spdx_license_key":"BSD-3-Clause",
"spdx_url":"https://spdx.org/licenses/BSD-3-Clause",
"start_line":11,
"end_line":11,
"matched_rule":{
"identifier":"bsd-new_10.RULE",
"license_expression":"bsd-new",
"licenses":[
"bsd-new"
],
"is_license_text":false,
"is_license_notice":false,
"is_license_reference":true,
"is_license_tag":false,
"matcher":"2-aho",
"rule_length":3,
"matched_length":3,
"match_coverage":100.0,
"rule_relevance":100.0
}
}
],
"license_expressions": [
"bsd-new",
"bsd-new",
"elastic-license-2018",
"bsd-new"
"license_expressions":[
"bsd-new",
"bsd-new",
"elastic-license-2018",
"bsd-new"
],
"scan_errors": []
}
]
"scan_errors":[
]
}
]
}