[neon/qt/qtwebengine/Neon/testing] debian: Add a script to update debian/copyright file.
Dmitry Shachnev
null at kde.org
Wed May 19 11:53:42 BST 2021
Git commit 008ebcfc46e6283e068cd97511b69b13b86f5b87 by Dmitry Shachnev.
Committed on 22/09/2020 at 11:39.
Pushed by sitter into branch 'Neon/testing'.
Add a script to update debian/copyright file.
Based on upstream qt_attribution.json and README.chromium files.
M +2 -0 debian/changelog
A +233 -0 debian/scripts/update-copyright
https://invent.kde.org/neon/qt/qtwebengine/commit/008ebcfc46e6283e068cd97511b69b13b86f5b87
diff --git a/debian/changelog b/debian/changelog
index 7810764..ff13ace 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -25,6 +25,8 @@ qtwebengine-opensource-src (5.15.1+dfsg-1) UNRELEASED; urgency=medium
* Temporarily build without system opus/ffmpeg until opus is updated to
version 1.3.1 (see #934809).
* Update debian/source/lintian-overrides for path changes.
+ * Add a script to update debian/copyright file based on upstream
+ qt_attribution.json and README.chromium files.
-- Debian Qt/KDE Maintainers <debian-qt-kde at lists.debian.org> Tue, 08 Sep 2020 20:31:58 +0300
diff --git a/debian/scripts/update-copyright b/debian/scripts/update-copyright
new file mode 100755
index 0000000..030a376
--- /dev/null
+++ b/debian/scripts/update-copyright
@@ -0,0 +1,233 @@
+#!/usr/bin/python3
+
+"""A script to automatically update debian/copyright file based on upstream
+README.chromium (and similar README.*), and qt_attribution.json files.
+
+It should be run in an unpacked tarball, to which the debian/ directory is
+copied.
+
+It changes only code between BEGIN/END AUTO GENERATED BLOCK lines.
+
+If this script complains about unknown license, add it to LICENSE_VARIATIONS
+dictionary (or add the corresponding directory to IGNORED_DIRECTORIES or
+LICENSE_OVERRIDES).
+
+Author: 2020 Dmitry Shachnev <mitya57 at debian.org>
+"""
+
+import json
+import glob
+import sys
+
+from os.path import dirname, join
+
+
+LICENSE_VARIATIONS = (
+ # Common licenses, sorted alphabetically
+ ("Apache-2.0", ["Apache 2.0", "Apache Version 2.0", "Apache-2.0",
+ "Apache License, Version 2.0", "Apache License 2.0",
+ "License: Apache Version 2.0", "Apache2"]),
+ ("APSL-2.0", ["Apple Public Source License 2.0", "APSL 2.0"]),
+ ("BSD-2-clause", ["BSD 2-Clause License", "2-Clause BSD", "BSD-2-Clause",
+ "2-clause BSD"]),
+ ("BSD-3-clause", ["BSD", "BSD 3-Clause", "BSD 3-clause", "3-clause BSD",
+ "BSD 3-clause License", "New BSD", "Chromium"]),
+ ("BSL-1.0", ["BSL (v 1.0)"]),
+ ("ClArtistic", ["Clarified-Artistic"]),
+ ("EPL-1.0", ["EPL 1.0"]),
+ ("FTL", ["FreeType License (FTL)"]),
+ ("GPL-2", ["GPL v2", "GPL 2.0"]),
+ ("GPL-3", ["GPL", "GPL v3"]),
+ ("ISC", ["ISC"]),
+ ("LGPL-2.1", ["LGPL 2.1", "GNU LGPL 2.1"]),
+ ("LGPL-3", ["LGPL 3"]),
+ ("libpng-2.0", ["libpng", "libpng license"]),
+ ("MIT", ["MIT", "MIT License", "NodeJS"]),
+ ("MPL-2.0", ["MPL 2.0", "MPL 2"]),
+ ("MS-PL", ["Microsoft Permissive License"]),
+ ("NCSA", ["University of Illinois/NCSA Open Source License",
+ "University of Illinois Open Source License."]),
+ ("OFL-1.1", ["SIL Open Font License, Version 1.1."]),
+ ("public-domain",
+ ["Public domain", "Public Domain",
+ "Public Domain: United States Government Work under 17 U.S.C. 105"]),
+ ("Unicode", "Unicode"),
+ ("Zlib", ["Zlib", "zlib"]),
+ # Some license combinations
+ ("AFL-2.0 or LGPL-2", ["Academic Free License version 2.0 or LGPL v2"]),
+ ("Apache-2.0 and MIT and GPL-2", ["Apache 2, MIT and GPL v2"]),
+ ("BSD-3-clause and APSL-2.0 and Apache-2.0",
+ ["New BSD, Apple PSL 2.0 and Apache 2.0"]),
+ ("BSD-3-clause and MIT and GPL-2", ["BSD 3-Clause, MIT, GPL v2"]),
+ ("MIT and GPL-2", ["MIT, GPL"]),
+ ("MIT and public-domain", ["MIT, Public Domain"]),
+ ("MIT and SGI-B-2.0", ["MIT and SGI Free Software B License Version 2.0"]),
+ ("MIT/X11 and SGI-B-2.0", ["MIT/X11, SGI Free Software License B"]),
+ ("MPL-1.1 or GPL-2 or LGPL-2.1", ["MPL 1.1/GPL 2.0/LGPL 2.1",
+ "MPL 1.1 / GPL 2.0 / LGPL 2.1"]),
+ ("MPL-1.1 or GPL-2 or LGPL-2.1, and BSD-3-clause",
+ ["BSD and MPL 1.1/GPL 2.0/LGPL 2.1"]),
+ ("MPL-1.1 or GPL-2 or LGPL-2.1, and BSD-3-clause and BSD-2-clause",
+ ["MPL-1.1/GPL-2.0/LGPL-2.1 + BSD-3-Clause + BSD-2-Clause"]),
+ ("OFL-1.1 and GPL-2 and bitstream-vera",
+ ["SIL OPEN FONT LICENSE, GPL v2, Bitstream Vera Fonts Copyright"]),
+ ("public-domain and BSD-3-clause", ["Public domain and BSD"]),
+)
+
+# These directories don't actually have source code.
+IGNORED_DIRECTORIES = (
+ "chromium/buildtools/clang_format",
+ "chromium/third_party/adobe",
+ "chromium/third_party/libovr",
+ "chromium/third_party/widevine",
+)
+
+LICENSE_OVERRIDES = {
+ "chromium/third_party/boringssl":
+ "OpenSSL and SSLeay and ISC and MIT and BSD-3-clause",
+ "chromium/third_party/catapult/tracing/third_party/jszip": "MIT or GPL-3",
+ "chromium/third_party/freetype": "FTL",
+ "chromium/third_party/iccjpeg": "IJG",
+ "chromium/third_party/libjpeg": "IJG",
+ "chromium/third_party/libjpeg_turbo": "IJG and BSD-3-clause and Zlib",
+ "chromium/third_party/minizip": "Zlib",
+ "chromium/third_party/pdfium/third_party/yasm":
+ "BSD-2-clause or BSD-3-clause, and GPL-2",
+ "chromium/third_party/webrtc/common_audio/third_party/spl_sqrt_floor":
+ "public-domain",
+ "chromium/third_party/yasm": "BSD-2-clause or BSD-3-clause, and GPL-2",
+ "chromium/third_party/zlib": "Zlib",
+}
+
+START_HEADER = '## BEGIN AUTO GENERATED BLOCK'
+END_HEADER = '## END AUTO GENERATED BLOCK'
+
+
+class CopyrightBuilder:
+ def __init__(self, filename):
+ self.filename = filename
+ with open(filename) as copyright_file:
+ current_copyright = copyright_file.read()
+ start_pos = current_copyright.find(START_HEADER)
+ self.start_data = current_copyright[:start_pos + len(START_HEADER) + 1]
+ end_pos = current_copyright.find(END_HEADER) - 1
+ self.end_data = current_copyright[end_pos:]
+
+ @staticmethod
+ def dump_section(section):
+ text = "\n"
+ text += f"Files: {section['files']}\n"
+ for i, line in enumerate(section["copyright"].split("\n")):
+ if i == 0:
+ text += f"Copyright: {line}\n"
+ else:
+ text += f" {line}\n"
+ text += f"License: {section['license']}\n"
+ if section["license_text"] is not None:
+ for line in section["license_text"].strip().split("\n"):
+ line = line.strip()
+ if not line:
+ text += " .\n"
+ else:
+ text += f" {line}\n"
+ return text
+
+ @staticmethod
+ def fixup_license(license_name, readme_file):
+ for canonical_name, variations in LICENSE_VARIATIONS:
+ if license_name in variations:
+ return canonical_name
+ if (license_name.startswith("Custom") or
+ license_name in ("Non-standard", "BSDish", "BSD-like")):
+ return "custom"
+ sys.exit(f"Error: unknown license in {readme_file}: {license_name}")
+ return license_name
+
+ def process_readme_file(self, readme_file):
+ headers = {}
+ with open(readme_file) as readme:
+ for line in readme:
+ if not line.strip():
+ break
+ if ": " not in line:
+ continue
+ header, content = line.split(": ", maxsplit=1)
+ headers[header.lower()] = content.rstrip()
+ if "license" not in headers:
+ return None
+ directory = dirname(readme_file)
+ files = join(directory, "*")
+ relative_name = directory[len("src/3rdparty/"):]
+ if relative_name in LICENSE_OVERRIDES:
+ license_name = LICENSE_OVERRIDES[relative_name]
+ else:
+ license_name = self.fixup_license(headers["license"], readme_file)
+ license_text = None
+ path_component = readme_file.split("/")[-2]
+ name = headers.get("short name", headers.get("name", path_component))
+ if license_name == "custom":
+ license_name += "-" + name.replace(" ", "-")
+ with open(join(directory, headers["license file"])) as license_txt:
+ license_text = license_txt.read()
+ return {
+ "files": files,
+ "copyright": name + " developers",
+ "license": license_name,
+ "license_text": license_text,
+ }
+
+ @staticmethod
+ def process_attribution_entry(entry, directory):
+ copyright_lines = [
+ line.replace("Copyright ", "").replace("(c)", "").lstrip()
+ for line in entry["Copyright"].split("\n")
+ ]
+ return {
+ "files": join(directory, entry.get("Files", "*")),
+ "copyright": "\n".join(copyright_lines),
+ "license": ("public-domain"
+ if entry["LicenseId"] == "DocumentRef-PublicDomain"
+ else entry["LicenseId"]),
+ "license_text": None,
+ }
+
+ def process_attribution_file(self, attribution_file):
+ with open(attribution_file) as attribution:
+ data = json.load(attribution, strict=False)
+ directory = dirname(attribution_file)
+ if isinstance(data, list):
+ for entry in data:
+ yield self.process_attribution_entry(entry, directory)
+ else:
+ yield self.process_attribution_entry(data, directory)
+
+ def get_sections_for_readme_files(self):
+ glob_result = glob.iglob("**/README.*", recursive=True)
+ for readme_file in sorted(glob_result):
+ if readme_file.endswith((".TXT", "chromium.template")):
+ continue
+ relative_name = dirname(readme_file)[len("src/3rdparty/"):]
+ if relative_name in IGNORED_DIRECTORIES:
+ continue
+ section = self.process_readme_file(readme_file)
+ if section is not None:
+ yield section
+
+ def get_sections_for_attribution_files(self):
+ glob_result = glob.iglob("**/qt_attribution.json", recursive=True)
+ for attribution_file in sorted(glob_result):
+ yield from self.process_attribution_file(attribution_file)
+
+ def update(self):
+ with open(self.filename, "w") as copyright_file:
+ copyright_file.write(self.start_data)
+ for section in self.get_sections_for_attribution_files():
+ copyright_file.write(self.dump_section(section))
+ for section in self.get_sections_for_readme_files():
+ copyright_file.write(self.dump_section(section))
+ copyright_file.write(self.end_data)
+
+
+if __name__ == "__main__":
+ builder = CopyrightBuilder("debian/copyright")
+ builder.update()
More information about the Neon-commits
mailing list