diff --git a/src/licensedcode/detection.py b/src/licensedcode/detection.py index fcba1525f8..ec99622c25 100644 --- a/src/licensedcode/detection.py +++ b/src/licensedcode/detection.py @@ -334,6 +334,25 @@ def identifier_with_expression(self): id_safe_expression = python_safe_name(s=str(self.license_expression)) return "{}-{}".format(id_safe_expression, self._identifier) + @property + def is_unknown(self): + """ + Return True if there are unknown license keys in the license expression + for this detection, return False otherwise. + """ + unknown_license_keys = [ + "unknown-license-reference", + "unknown-spdx", + "unknown", + "free-unknown" + ] + + for license_key in unknown_license_keys: + if license_key in self.license_expression: + return True + + return False + def get_start_end_line(self): """ Return start and end line for a license detection issue, from the @@ -1356,6 +1375,61 @@ def has_references_to_local_files(license_matches): ) +def use_referenced_license_expression(referenced_license_expression, license_detection, licensing=Licensing()): + """ + Return True if the ``license_detection`` LicenseDetection should include + the matches represented by the ``referenced_license_expression`` string. + Return False otherwise. + + Used when we have a ``license_detection`` with a match to a license rule like + "See license in COPYING" and where the ``referenced_license_expression`` is the + expression found in the "COPYING" file, which is the combined expression from + all license detections found in "COPYING" (or multiple referenced files). + + Reference: https://github.com/nexB/scancode-toolkit/issues/3547 + """ + #TODO: Also determing if referenced matches could be added but + # resulting license expression should not be modified. + + if not referenced_license_expression or not license_detection: + return False + + # We should always include referenced license matches to resolve an unknown + # license reference + if license_detection.is_unknown: + return True + + # We should always include referenced license matches when the license + # expression from the referenced license matches match the license + # expression for the detection + if referenced_license_expression == license_detection.license_expression: + return True + + license_keys = set( + licensing.license_keys(expression=license_detection.license_expression) + ) + referenced_license_keys = set( + licensing.license_keys(expression=referenced_license_expression) + ) + same_expression = referenced_license_expression == license_detection.license_expression + same_license_keys = license_keys == referenced_license_keys + + # If we have the same license keys but not the same license expression then + # the reference could merely be pointing to notices, combining which produces + # a different expression, and the original detection is correct + if same_license_keys and not same_expression: + return False + + # when there are many license keys in an expression, and there are no + # unknown or other cases, we cannot safely conclude that we should + # follow the license in the referenced filenames. This is likely + # a case where we have larger notices and several combined expressions, + if len(referenced_license_keys) > 5: + return False + + return True + + def get_detected_license_expression( analysis, license_matches=None, diff --git a/src/licensedcode/plugin_license.py b/src/licensedcode/plugin_license.py index a2e3b0638d..d7837f4e0b 100644 --- a/src/licensedcode/plugin_license.py +++ b/src/licensedcode/plugin_license.py @@ -15,6 +15,7 @@ from commoncode.cliutils import PluggableCommandLineOption from commoncode.cliutils import SCAN_GROUP from commoncode.cliutils import SCAN_OPTIONS_GROUP +from license_expression import combine_expressions from plugincode.scan import ScanPlugin from plugincode.scan import scan_impl @@ -30,10 +31,12 @@ from licensedcode.detection import LicenseDetectionFromResult from licensedcode.detection import sort_unique_detections from licensedcode.detection import UniqueDetection +from licensedcode.detection import use_referenced_license_expression from packagedcode.utils import combine_expressions from scancode.api import SCANCODE_LICENSEDB_URL TRACE = os.environ.get('SCANCODE_DEBUG_PLUGIN_LICENSE', False) +TRACE_REFERENCE = os.environ.get('SCANCODE_DEBUG_PLUGIN_LICENSE_REFERENCE', False) def logger_debug(*args): @@ -42,7 +45,7 @@ def logger_debug(*args): logger = logging.getLogger(__name__) -if TRACE: +if TRACE or TRACE_REFERENCE: import sys logging.basicConfig(stream=sys.stdout) logger.setLevel(logging.DEBUG) @@ -214,6 +217,8 @@ def process_codebase(self, codebase, license_text=False, license_diagnostics=Fal f'before: {license_expressions_before}\n' f'after : {license_expressions_after}' ) + + #raise Exception() license_detections = collect_license_detections( codebase=codebase, @@ -259,20 +264,28 @@ def add_referenced_filenames_license_matches_for_detections(resource, codebase): modified = False + if TRACE_REFERENCE: + logger_debug( + f'add_referenced_license_matches: resource_path: {resource.path}', + ) + for license_detection_mapping in license_detection_mappings: license_detection = LicenseDetectionFromResult.from_license_detection_mapping( license_detection_mapping=license_detection_mapping, file_path=resource.path, ) - detection_modified = False - detections_added = [] license_match_mappings = license_detection_mapping["matches"] referenced_filenames = get_referenced_filenames(license_detection.matches) if not referenced_filenames: + if TRACE_REFERENCE: + logger_debug( + f'No references at license detection with expression: {license_detection.license_expression}', + ) continue + referenced_detections = [] for referenced_filename in referenced_filenames: referenced_resource = find_referenced_resource( referenced_filename=referenced_filename, @@ -281,26 +294,53 @@ def add_referenced_filenames_license_matches_for_detections(resource, codebase): ) if referenced_resource and referenced_resource.license_detections: - modified = True - detection_modified = True - detections_added.extend(referenced_resource.license_detections) - matches_to_extend = get_matches_from_detection_mappings( - license_detections=referenced_resource.license_detections + referenced_detections.extend( + referenced_resource.license_detections ) - populate_matches_with_path( - matches=matches_to_extend, - path=referenced_resource.path - ) - license_match_mappings.extend(matches_to_extend) - if not detection_modified: + for detection in referenced_resource.license_detections: + populate_matches_with_path( + matches=detection["matches"], + path=referenced_resource.path + ) + + referenced_license_expression = combine_expressions( + expressions=[ + detection["license_expression"] + for detection in referenced_detections + ], + ) + if not use_referenced_license_expression( + referenced_license_expression=referenced_license_expression, + license_detection=license_detection, + ): + if TRACE_REFERENCE: + logger_debug( + f'use_referenced_license_expression: False for ' + f'resource: {referenced_resource.path} and ' + f'license_expression: {referenced_license_expression}', + ) continue + if TRACE_REFERENCE: + logger_debug( + f'use_referenced_license_expression: True for ' + f'resource: {referenced_resource.path} and ' + f'license_expression: {referenced_license_expression}', + ) + + modified = True + matches_to_extend = get_matches_from_detection_mappings( + license_detections=referenced_detections + ) + license_match_mappings.extend(matches_to_extend) + detection_log, license_expression = get_detected_license_expression( license_match_mappings=license_match_mappings, analysis=DetectionCategory.UNKNOWN_FILE_REFERENCE_LOCAL.value, post_scan=True, ) + license_expression_spdx = build_spdx_license_expression( license_expression=str(license_expression), licensing=get_cache().licensing, @@ -310,7 +350,7 @@ def add_referenced_filenames_license_matches_for_detections(resource, codebase): license_detection_mapping["detection_log"] = detection_log license_detection_mapping["identifier"] = get_new_identifier_from_detections( initial_detection=license_detection_mapping, - detections_added=detections_added, + detections_added=referenced_detections, license_expression=license_expression, ) diff --git a/src/packagedcode/licensing.py b/src/packagedcode/licensing.py index ffd683a83f..d639962646 100644 --- a/src/packagedcode/licensing.py +++ b/src/packagedcode/licensing.py @@ -26,6 +26,7 @@ from licensedcode.detection import detect_licenses from licensedcode.detection import LicenseDetectionFromResult from licensedcode.detection import populate_matches_with_path +from licensedcode.detection import use_referenced_license_expression from licensedcode.spans import Span from licensedcode import query @@ -93,12 +94,13 @@ def add_referenced_license_matches_for_package(resource, codebase): file_path=resource.path, ) - detection_modified = False + detections_added = [] license_match_mappings = license_detection_mapping["matches"] referenced_filenames = get_referenced_filenames(license_detection_object.matches) if not referenced_filenames: continue + referenced_detections = [] for referenced_filename in referenced_filenames: referenced_resource = find_referenced_resource( referenced_filename=referenced_filename, @@ -106,28 +108,38 @@ def add_referenced_license_matches_for_package(resource, codebase): codebase=codebase, ) - if not referenced_resource: - continue - - referenced_license_detections = referenced_resource.license_detections - - if referenced_license_detections: - modified = True - detection_modified = True - matches_to_extend = get_matches_from_detection_mappings( - license_detections=referenced_license_detections + if referenced_resource and referenced_resource.license_detections: + referenced_detections.extend( + referenced_resource.license_detections ) + # For LicenseMatches with different resources as origin, add the # resource path to these matches as origin info - populate_matches_with_path( - matches=matches_to_extend, - path=referenced_resource.path - ) - license_match_mappings.extend(matches_to_extend) - - if not detection_modified: + for detection in referenced_resource.license_detections: + populate_matches_with_path( + matches=detection["matches"], + path=referenced_resource.path + ) + + referenced_license_expression = combine_expressions( + expressions=[ + detection["license_expression"] + for detection in referenced_detections + ], + ) + if not use_referenced_license_expression( + referenced_license_expression=referenced_license_expression, + license_detection=license_detection_object, + ): continue + modified = True + detections_added.extend(referenced_resource.license_detections) + matches_to_extend = get_matches_from_detection_mappings( + license_detections=referenced_resource.license_detections, + ) + license_match_mappings.extend(matches_to_extend) + detection_log, license_expression = get_detected_license_expression( license_match_mappings=license_match_mappings, analysis=DetectionCategory.PACKAGE_UNKNOWN_FILE_REFERENCE_LOCAL.value, @@ -142,7 +154,7 @@ def add_referenced_license_matches_for_package(resource, codebase): license_detection_mapping["detection_log"] = detection_log license_detection_mapping["identifier"] = get_new_identifier_from_detections( initial_detection=license_detection_mapping, - detections_added=referenced_license_detections, + detections_added=detections_added, license_expression=license_expression, ) @@ -223,7 +235,20 @@ def add_referenced_license_detection_from_package(resource, codebase): f'sibling_license_detections: {sibling_license_detections}' ) + referenced_license_expression = combine_expressions( + expressions=[ + detection["license_expression"] + for detection in sibling_license_detections + ], + ) + if not use_referenced_license_expression( + referenced_license_expression=referenced_license_expression, + license_detection=license_detection_object, + ): + continue + for sibling_detection in sibling_license_detections: + modified = True detection_modified = True license_match_mappings.extend(sibling_detection["matches"]) @@ -239,6 +264,21 @@ def add_referenced_license_detection_from_package(resource, codebase): break pkg_detections = codebase_package["license_detections"] + if not pkg_detections: + continue + + referenced_license_expression = combine_expressions( + expressions=[ + detection["license_expression"] + for detection in pkg_detections + ], + ) + if not use_referenced_license_expression( + referenced_license_expression=referenced_license_expression, + license_detection=license_detection_object, + ): + continue + for pkg_detection in pkg_detections: modified = True detection_modified = True diff --git a/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem.expected.json b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem.expected.json new file mode 100644 index 0000000000..a04913b28a --- /dev/null +++ b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem.expected.json @@ -0,0 +1,196 @@ +{ + "license_detections": [ + { + "identifier": "lgpl_2_1-be3f3949-802d-9c3e-b5f0-b2466a0bd98b", + "license_expression": "lgpl-2.1", + "license_expression_spdx": "LGPL-2.1-only", + "detection_count": 1, + "detection_log": [], + "reference_matches": [ + { + "license_expression": "lgpl-2.1", + "license_expression_spdx": "LGPL-2.1-only", + "from_file": "or_and_problem/COPYING-LGPL-2.1", + "start_line": 2, + "end_line": 3, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 8, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "lgpl-2.1_36.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/lgpl-2.1_36.RULE", + "matched_text": " GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1, February 1999", + "matched_text_diagnostics": "GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1," + } + ] + }, + { + "identifier": "lgpl_2_1_or_mpl_1_1-2d702372-2b26-f1b1-7ebf-c9865d7bcfd0", + "license_expression": "lgpl-2.1 OR mpl-1.1", + "license_expression_spdx": "LGPL-2.1-only OR MPL-1.1", + "detection_count": 1, + "detection_log": [], + "reference_matches": [ + { + "license_expression": "lgpl-2.1 OR mpl-1.1", + "license_expression_spdx": "LGPL-2.1-only OR MPL-1.1", + "from_file": "or_and_problem/src/cairo-analysis-surface-private.h", + "start_line": 4, + "end_line": 29, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 222, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "lgpl-2.1_or_mpl-1.1_4.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/lgpl-2.1_or_mpl-1.1_4.RULE", + "matched_text": " * This library is free software; you can redistribute it and/or\n * modify it either under the terms of the GNU Lesser General Public\n * License version 2.1 as published by the Free Software Foundation\n * (the \"LGPL\") or, at your option, under the terms of the Mozilla\n * Public License Version 1.1 (the \"MPL\"). If you do not alter this\n * notice, a recipient may use your version of this file under either\n * the MPL or the LGPL.\n *\n * You should have received a copy of the LGPL along with this library\n * in the file COPYING-LGPL-2.1; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA\n * You should have received a copy of the MPL along with this library\n * in the file COPYING-MPL-1.1\n *\n * The contents of this file are subject to the Mozilla Public License\n * Version 1.1 (the \"License\"); you may not use this file except in\n * compliance with the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY\n * OF ANY KIND, either express or implied. See the LGPL or the MPL for\n * the specific language governing rights and limitations.\n *\n * The Original Code is the cairo graphics library.\n *\n * The Initial Developer of the Original Code is Keith Packard", + "matched_text_diagnostics": "This library is free software; you can redistribute it and/or\n * modify it either under the terms of the GNU Lesser General Public\n * License version 2.1 as published by the Free Software Foundation\n * (the \"LGPL\") or, at your option, under the terms of the Mozilla\n * Public License Version 1.1 (the \"MPL\"). If you do not alter this\n * notice, a recipient may use your version of this file under either\n * the MPL or the LGPL.\n *\n * You should have received a copy of the LGPL along with this library\n * in the file COPYING-LGPL-2.1; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA\n * You should have received a copy of the MPL along with this library\n * in the file COPYING-MPL-1.1\n *\n * The contents of this file are subject to the Mozilla Public License\n * Version 1.1 (the \"License\"); you may not use this file except in\n * compliance with the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY\n * OF ANY KIND, either express or implied. See the LGPL or the MPL for\n * the specific language governing rights and limitations.\n *\n * The Original Code is the cairo graphics library.\n *\n * The Initial Developer of the Original Code is" + } + ] + }, + { + "identifier": "mpl_1_1-bda94646-bce9-7c88-28d3-e530599274c6", + "license_expression": "mpl-1.1", + "license_expression_spdx": "MPL-1.1", + "detection_count": 1, + "detection_log": [], + "reference_matches": [ + { + "license_expression": "mpl-1.1", + "license_expression_spdx": "MPL-1.1", + "from_file": "or_and_problem/COPYING-MPL-1.1", + "start_line": 1, + "end_line": 2, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 6, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "mpl-1.1_16.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mpl-1.1_16.RULE", + "matched_text": " MOZILLA PUBLIC LICENSE\n Version 1.1", + "matched_text_diagnostics": "MOZILLA PUBLIC LICENSE\n Version 1.1" + } + ] + } + ], + "files": [ + { + "path": "COPYING-LGPL-2.1", + "type": "file", + "detected_license_expression": "lgpl-2.1", + "detected_license_expression_spdx": "LGPL-2.1-only", + "license_detections": [ + { + "license_expression": "lgpl-2.1", + "license_expression_spdx": "LGPL-2.1-only", + "matches": [ + { + "license_expression": "lgpl-2.1", + "spdx_license_expression": "LGPL-2.1-only", + "from_file": "or_and_problem/COPYING-LGPL-2.1", + "start_line": 2, + "end_line": 3, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 8, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "lgpl-2.1_36.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/lgpl-2.1_36.RULE", + "matched_text": " GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1, February 1999", + "matched_text_diagnostics": "GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1," + } + ], + "detection_log": [], + "identifier": "lgpl_2_1-be3f3949-802d-9c3e-b5f0-b2466a0bd98b" + } + ], + "license_clues": [], + "percentage_of_license_text": 80.0, + "scan_errors": [] + }, + { + "path": "COPYING-MPL-1.1", + "type": "file", + "detected_license_expression": "mpl-1.1", + "detected_license_expression_spdx": "MPL-1.1", + "license_detections": [ + { + "license_expression": "mpl-1.1", + "license_expression_spdx": "MPL-1.1", + "matches": [ + { + "license_expression": "mpl-1.1", + "spdx_license_expression": "MPL-1.1", + "from_file": "or_and_problem/COPYING-MPL-1.1", + "start_line": 1, + "end_line": 2, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 6, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "mpl-1.1_16.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mpl-1.1_16.RULE", + "matched_text": " MOZILLA PUBLIC LICENSE\n Version 1.1", + "matched_text_diagnostics": "MOZILLA PUBLIC LICENSE\n Version 1.1" + } + ], + "detection_log": [], + "identifier": "mpl_1_1-bda94646-bce9-7c88-28d3-e530599274c6" + } + ], + "license_clues": [], + "percentage_of_license_text": 100.0, + "scan_errors": [] + }, + { + "path": "src", + "type": "directory", + "detected_license_expression": null, + "detected_license_expression_spdx": null, + "license_detections": [], + "license_clues": [], + "percentage_of_license_text": 0, + "scan_errors": [] + }, + { + "path": "src/cairo-analysis-surface-private.h", + "type": "file", + "detected_license_expression": "lgpl-2.1 OR mpl-1.1", + "detected_license_expression_spdx": "LGPL-2.1-only OR MPL-1.1", + "license_detections": [ + { + "license_expression": "lgpl-2.1 OR mpl-1.1", + "license_expression_spdx": "LGPL-2.1-only OR MPL-1.1", + "matches": [ + { + "license_expression": "lgpl-2.1 OR mpl-1.1", + "spdx_license_expression": "LGPL-2.1-only OR MPL-1.1", + "from_file": "or_and_problem/src/cairo-analysis-surface-private.h", + "start_line": 4, + "end_line": 29, + "matcher": "2-aho", + "score": 100.0, + "matched_length": 222, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "lgpl-2.1_or_mpl-1.1_4.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/lgpl-2.1_or_mpl-1.1_4.RULE", + "matched_text": " * This library is free software; you can redistribute it and/or\n * modify it either under the terms of the GNU Lesser General Public\n * License version 2.1 as published by the Free Software Foundation\n * (the \"LGPL\") or, at your option, under the terms of the Mozilla\n * Public License Version 1.1 (the \"MPL\"). If you do not alter this\n * notice, a recipient may use your version of this file under either\n * the MPL or the LGPL.\n *\n * You should have received a copy of the LGPL along with this library\n * in the file COPYING-LGPL-2.1; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA\n * You should have received a copy of the MPL along with this library\n * in the file COPYING-MPL-1.1\n *\n * The contents of this file are subject to the Mozilla Public License\n * Version 1.1 (the \"License\"); you may not use this file except in\n * compliance with the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY\n * OF ANY KIND, either express or implied. See the LGPL or the MPL for\n * the specific language governing rights and limitations.\n *\n * The Original Code is the cairo graphics library.\n *\n * The Initial Developer of the Original Code is Keith Packard", + "matched_text_diagnostics": "This library is free software; you can redistribute it and/or\n * modify it either under the terms of the GNU Lesser General Public\n * License version 2.1 as published by the Free Software Foundation\n * (the \"LGPL\") or, at your option, under the terms of the Mozilla\n * Public License Version 1.1 (the \"MPL\"). If you do not alter this\n * notice, a recipient may use your version of this file under either\n * the MPL or the LGPL.\n *\n * You should have received a copy of the LGPL along with this library\n * in the file COPYING-LGPL-2.1; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA\n * You should have received a copy of the MPL along with this library\n * in the file COPYING-MPL-1.1\n *\n * The contents of this file are subject to the Mozilla Public License\n * Version 1.1 (the \"License\"); you may not use this file except in\n * compliance with the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY\n * OF ANY KIND, either express or implied. See the LGPL or the MPL for\n * the specific language governing rights and limitations.\n *\n * The Original Code is the cairo graphics library.\n *\n * The Initial Developer of the Original Code is" + } + ], + "detection_log": [], + "identifier": "lgpl_2_1_or_mpl_1_1-2d702372-2b26-f1b1-7ebf-c9865d7bcfd0" + } + ], + "license_clues": [], + "percentage_of_license_text": 54.55, + "scan_errors": [] + } + ] +} \ No newline at end of file diff --git a/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-LGPL-2.1 b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-LGPL-2.1 new file mode 100644 index 0000000000..9dfae90a93 --- /dev/null +++ b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-LGPL-2.1 @@ -0,0 +1,3 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 diff --git a/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-MPL-1.1 b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-MPL-1.1 new file mode 100644 index 0000000000..7a78c8ca89 --- /dev/null +++ b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/COPYING-MPL-1.1 @@ -0,0 +1,2 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 diff --git a/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/src/cairo-analysis-surface-private.h b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/src/cairo-analysis-surface-private.h new file mode 100644 index 0000000000..1e054c209a --- /dev/null +++ b/tests/licensedcode/data/plugin_license/ignored_reference/or_and_problem/src/cairo-analysis-surface-private.h @@ -0,0 +1,74 @@ +/* + * Copyright © 2005 Keith Packard + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Keith Packard + * + * Contributor(s): + * Keith Packard + */ + +#ifndef CAIRO_ANALYSIS_SURFACE_H +#define CAIRO_ANALYSIS_SURFACE_H + +#include "cairoint.h" + +cairo_private cairo_surface_t * +_cairo_analysis_surface_create (cairo_surface_t *target); + +cairo_private void +_cairo_analysis_surface_set_ctm (cairo_surface_t *surface, + const cairo_matrix_t *ctm); + +cairo_private void +_cairo_analysis_surface_get_ctm (cairo_surface_t *surface, + cairo_matrix_t *ctm); + +cairo_private cairo_region_t * +_cairo_analysis_surface_get_supported (cairo_surface_t *surface); + +cairo_private cairo_region_t * +_cairo_analysis_surface_get_unsupported (cairo_surface_t *surface); + +cairo_private cairo_bool_t +_cairo_analysis_surface_has_supported (cairo_surface_t *surface); + +cairo_private cairo_bool_t +_cairo_analysis_surface_has_unsupported (cairo_surface_t *surface); + +cairo_private void +_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface, + cairo_box_t *bbox); + +cairo_private cairo_int_status_t +_cairo_analysis_surface_merge_status (cairo_int_status_t status_a, + cairo_int_status_t status_b); + +cairo_private cairo_surface_t * +_cairo_null_surface_create (cairo_content_t content); + +#endif /* CAIRO_ANALYSIS_SURFACE_H */ diff --git a/tests/licensedcode/test_plugin_license_detection.py b/tests/licensedcode/test_plugin_license_detection.py index 945c00e116..8effb385f9 100644 --- a/tests/licensedcode/test_plugin_license_detection.py +++ b/tests/licensedcode/test_plugin_license_detection.py @@ -183,6 +183,24 @@ def test_license_match_unknown_license_with_license_reference(): check_json_scan(test_loc, result_file, regen=REGEN_TEST_FIXTURES) +def test_license_detection_with_ignorable_reference_different_expression(): + test_dir = test_env.get_test_loc('plugin_license/ignored_reference/or_and_problem/', copy=True) + result_file = test_env.get_temp_file('json') + args = [ + '--license', + '--license-text', + '--license-text-diagnostics', + '--license-diagnostics', + '--strip-root', + '--verbose', + '--json', result_file, + test_dir, + ] + run_scan_click(args) + test_loc = test_env.get_test_loc('plugin_license/ignored_reference/or_and_problem.expected.json') + check_json_scan(test_loc, result_file, regen=REGEN_TEST_FIXTURES) + + def test_license_match_unknown_license_without_license_reference(): test_dir = test_env.get_test_loc('plugin_license/license_reference/scan/license-ref-see-copying', copy=True) result_file = test_env.get_temp_file('json') diff --git a/tests/packagedcode/test_license_detection.py b/tests/packagedcode/test_license_detection.py index ffced68a1f..f4bbf54094 100644 --- a/tests/packagedcode/test_license_detection.py +++ b/tests/packagedcode/test_license_detection.py @@ -38,7 +38,7 @@ def test_license_reference_detection_in_manifest_unknown_with_license(): check_json_scan(test_loc, result_file, regen=REGEN_TEST_FIXTURES) -def test_license_reference_detection_in_manifest_known(): +def test_license_reference_detection_in_manifest_known_with_license(): test_dir = test_env.get_test_loc('license_detection/reference-at-manifest/nanopb/', copy=True) result_file = test_env.get_temp_file('json') args = [