1*2d1272b8SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*2d1272b8SAndroid Build Coastguard Worker 3*2d1272b8SAndroid Build Coastguard Workerfrom enum import Enum 4*2d1272b8SAndroid Build Coastguard Workerfrom pathlib import Path 5*2d1272b8SAndroid Build Coastguard Workerfrom typing import Sequence 6*2d1272b8SAndroid Build Coastguard Workerfrom typing import Tuple 7*2d1272b8SAndroid Build Coastguard Workerfrom fontTools import ttLib 8*2d1272b8SAndroid Build Coastguard Workerimport tempfile 9*2d1272b8SAndroid Build Coastguard Workerimport subprocess 10*2d1272b8SAndroid Build Coastguard Workerimport json 11*2d1272b8SAndroid Build Coastguard Workerimport argparse 12*2d1272b8SAndroid Build Coastguard Workerimport contextlib 13*2d1272b8SAndroid Build Coastguard Workerimport os 14*2d1272b8SAndroid Build Coastguard Workerimport re 15*2d1272b8SAndroid Build Coastguard Workerimport sys 16*2d1272b8SAndroid Build Coastguard Worker 17*2d1272b8SAndroid Build Coastguard Worker# list of specific files to be ignored. 18*2d1272b8SAndroid Build Coastguard WorkerIGNORE_FILE_NAME = [ 19*2d1272b8SAndroid Build Coastguard Worker # Exclude myself 20*2d1272b8SAndroid Build Coastguard Worker "generate_notice.py", 21*2d1272b8SAndroid Build Coastguard Worker 22*2d1272b8SAndroid Build Coastguard Worker # License files 23*2d1272b8SAndroid Build Coastguard Worker "LICENSE", 24*2d1272b8SAndroid Build Coastguard Worker "LICENSE_APACHE2.TXT", 25*2d1272b8SAndroid Build Coastguard Worker "LICENSE_FSFAP.TXT", 26*2d1272b8SAndroid Build Coastguard Worker "LICENSE_GPLv2.TXT", 27*2d1272b8SAndroid Build Coastguard Worker "LICENSE_GPLv2_WITH_AUTOCONF_EXCEPTION.TXT", 28*2d1272b8SAndroid Build Coastguard Worker "LICENSE_GPLv3_WITH_AUTOCONF_EXCEPTION.TXT", 29*2d1272b8SAndroid Build Coastguard Worker "LICENSE_HPND_SELL_VARIANT.TXT", 30*2d1272b8SAndroid Build Coastguard Worker "LICENSE_ISC.TXT", 31*2d1272b8SAndroid Build Coastguard Worker "LICENSE_MIT_MODERN_VARIANT.TXT", 32*2d1272b8SAndroid Build Coastguard Worker "LICENSE_OFL.TXT", 33*2d1272b8SAndroid Build Coastguard Worker "METADATA", 34*2d1272b8SAndroid Build Coastguard Worker "MODULE_LICENSE_MIT", 35*2d1272b8SAndroid Build Coastguard Worker "NOTICE", 36*2d1272b8SAndroid Build Coastguard Worker 37*2d1272b8SAndroid Build Coastguard Worker # dictionary which has Copyright word 38*2d1272b8SAndroid Build Coastguard Worker "perf/texts/en-words.txt", 39*2d1272b8SAndroid Build Coastguard Worker 40*2d1272b8SAndroid Build Coastguard Worker # broken unreadable font file for fuzzing target 41*2d1272b8SAndroid Build Coastguard Worker "test/fuzzing/fonts/sbix-extents.ttf", 42*2d1272b8SAndroid Build Coastguard Worker 43*2d1272b8SAndroid Build Coastguard Worker # ??? 44*2d1272b8SAndroid Build Coastguard Worker "xkcd.png", 45*2d1272b8SAndroid Build Coastguard Worker] 46*2d1272b8SAndroid Build Coastguard Worker 47*2d1272b8SAndroid Build Coastguard WorkerIGNORE_DIR_IF_NO_COPYRIGHT = [ 48*2d1272b8SAndroid Build Coastguard Worker "test", 49*2d1272b8SAndroid Build Coastguard Worker "perf", 50*2d1272b8SAndroid Build Coastguard Worker] 51*2d1272b8SAndroid Build Coastguard Worker 52*2d1272b8SAndroid Build Coastguard WorkerNO_COPYRIGHT_FILES = [ 53*2d1272b8SAndroid Build Coastguard Worker ".ci/build-win32.sh", 54*2d1272b8SAndroid Build Coastguard Worker ".ci/build-win64.sh", 55*2d1272b8SAndroid Build Coastguard Worker ".ci/deploy-docs.sh", 56*2d1272b8SAndroid Build Coastguard Worker ".ci/publish_release_artifact.sh", 57*2d1272b8SAndroid Build Coastguard Worker ".ci/requirements-fonttools.in", 58*2d1272b8SAndroid Build Coastguard Worker ".ci/requirements-fonttools.txt", 59*2d1272b8SAndroid Build Coastguard Worker ".ci/requirements.in", 60*2d1272b8SAndroid Build Coastguard Worker ".ci/requirements.txt", 61*2d1272b8SAndroid Build Coastguard Worker ".ci/win32-cross-file.txt", 62*2d1272b8SAndroid Build Coastguard Worker ".ci/win64-cross-file.txt", 63*2d1272b8SAndroid Build Coastguard Worker ".circleci/config.yml", 64*2d1272b8SAndroid Build Coastguard Worker ".clang-format", 65*2d1272b8SAndroid Build Coastguard Worker ".codecov.yml", 66*2d1272b8SAndroid Build Coastguard Worker ".editorconfig", 67*2d1272b8SAndroid Build Coastguard Worker ".github/dependabot.yml", 68*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/arm-ci.yml", 69*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/cifuzz.yml", 70*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/configs-build.yml", 71*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/coverity-scan.yml", 72*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/linux-ci.yml", 73*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/macos-ci.yml", 74*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/msvc-ci.yml", 75*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/msys2-ci.yml", 76*2d1272b8SAndroid Build Coastguard Worker ".github/workflows/scorecard.yml", 77*2d1272b8SAndroid Build Coastguard Worker "AUTHORS", 78*2d1272b8SAndroid Build Coastguard Worker "BUILD.md", 79*2d1272b8SAndroid Build Coastguard Worker "CMakeLists.txt", 80*2d1272b8SAndroid Build Coastguard Worker "CONFIG.md", 81*2d1272b8SAndroid Build Coastguard Worker "NEWS", 82*2d1272b8SAndroid Build Coastguard Worker "OWNERS", 83*2d1272b8SAndroid Build Coastguard Worker "README.android", 84*2d1272b8SAndroid Build Coastguard Worker "README.md", 85*2d1272b8SAndroid Build Coastguard Worker "README.python.md", 86*2d1272b8SAndroid Build Coastguard Worker "RELEASING.md", 87*2d1272b8SAndroid Build Coastguard Worker "SECURITY.md", 88*2d1272b8SAndroid Build Coastguard Worker "TESTING.md", 89*2d1272b8SAndroid Build Coastguard Worker "TEST_MAPPING", 90*2d1272b8SAndroid Build Coastguard Worker "THANKS", 91*2d1272b8SAndroid Build Coastguard Worker "docs/HarfBuzz.png", 92*2d1272b8SAndroid Build Coastguard Worker "docs/HarfBuzz.svg", 93*2d1272b8SAndroid Build Coastguard Worker "docs/features.dot", 94*2d1272b8SAndroid Build Coastguard Worker "docs/harfbuzz-docs.xml", 95*2d1272b8SAndroid Build Coastguard Worker "docs/harfbuzz-overrides.txt", 96*2d1272b8SAndroid Build Coastguard Worker "docs/harfbuzz-sections.txt", 97*2d1272b8SAndroid Build Coastguard Worker "docs/meson.build", 98*2d1272b8SAndroid Build Coastguard Worker "docs/repacker.md", 99*2d1272b8SAndroid Build Coastguard Worker "docs/serializer.md", 100*2d1272b8SAndroid Build Coastguard Worker "docs/subset-preprocessing.md", 101*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-buffers-language-script-and-direction.xml", 102*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-clusters.xml", 103*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-fonts-and-faces.xml", 104*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-getting-started.xml", 105*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-glyph-information.xml", 106*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-install-harfbuzz.xml", 107*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-integration.xml", 108*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-object-model.xml", 109*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-opentype-features.xml", 110*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-shaping-concepts.xml", 111*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-utilities.xml", 112*2d1272b8SAndroid Build Coastguard Worker "docs/usermanual-what-is-harfbuzz.xml", 113*2d1272b8SAndroid Build Coastguard Worker "docs/version.xml.in", 114*2d1272b8SAndroid Build Coastguard Worker "docs/wasm-shaper.md", 115*2d1272b8SAndroid Build Coastguard Worker "harfbuzz.doap", 116*2d1272b8SAndroid Build Coastguard Worker "meson.build", 117*2d1272b8SAndroid Build Coastguard Worker "meson_options.txt", 118*2d1272b8SAndroid Build Coastguard Worker "replace-enum-strings.cmake", 119*2d1272b8SAndroid Build Coastguard Worker "src/ArabicPUASimplified.txt", 120*2d1272b8SAndroid Build Coastguard Worker "src/ArabicPUATraditional.txt", 121*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/Anchor.hh", 122*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/AnchorFormat1.hh", 123*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/AnchorFormat2.hh", 124*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/AnchorFormat3.hh", 125*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/AnchorMatrix.hh", 126*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/ChainContextPos.hh", 127*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/Common.hh", 128*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/ContextPos.hh", 129*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/CursivePos.hh", 130*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/CursivePosFormat1.hh", 131*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/ExtensionPos.hh", 132*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/GPOS.hh", 133*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/LigatureArray.hh", 134*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkArray.hh", 135*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkBasePos.hh", 136*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkBasePosFormat1.hh", 137*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkLigPos.hh", 138*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkLigPosFormat1.hh", 139*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkMarkPos.hh", 140*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkMarkPosFormat1.hh", 141*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/MarkRecord.hh", 142*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PairPos.hh", 143*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PairPosFormat1.hh", 144*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PairPosFormat2.hh", 145*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PairSet.hh", 146*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PairValueRecord.hh", 147*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PosLookup.hh", 148*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/PosLookupSubTable.hh", 149*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/SinglePos.hh", 150*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/SinglePosFormat1.hh", 151*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/SinglePosFormat2.hh", 152*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GPOS/ValueFormat.hh", 153*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/AlternateSet.hh", 154*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/AlternateSubst.hh", 155*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/AlternateSubstFormat1.hh", 156*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/ChainContextSubst.hh", 157*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/Common.hh", 158*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/ContextSubst.hh", 159*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/ExtensionSubst.hh", 160*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/GSUB.hh", 161*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/Ligature.hh", 162*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/LigatureSet.hh", 163*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/LigatureSubst.hh", 164*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/LigatureSubstFormat1.hh", 165*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/MultipleSubst.hh", 166*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/MultipleSubstFormat1.hh", 167*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/ReverseChainSingleSubst.hh", 168*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh", 169*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/Sequence.hh", 170*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/SingleSubst.hh", 171*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/SingleSubstFormat1.hh", 172*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/SingleSubstFormat2.hh", 173*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/SubstLookup.hh", 174*2d1272b8SAndroid Build Coastguard Worker "src/OT/Layout/GSUB/SubstLookupSubTable.hh", 175*2d1272b8SAndroid Build Coastguard Worker "src/OT/Var/VARC/VARC.cc", 176*2d1272b8SAndroid Build Coastguard Worker "src/OT/Var/VARC/VARC.hh", 177*2d1272b8SAndroid Build Coastguard Worker "src/OT/Var/VARC/coord-setter.hh", 178*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/CompositeGlyph.hh", 179*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/Glyph.hh", 180*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/GlyphHeader.hh", 181*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/SimpleGlyph.hh", 182*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/SubsetGlyph.hh", 183*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/composite-iter.hh", 184*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/glyf-helpers.hh", 185*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/glyf.hh", 186*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/loca.hh", 187*2d1272b8SAndroid Build Coastguard Worker "src/OT/glyf/path-builder.hh", 188*2d1272b8SAndroid Build Coastguard Worker "src/addTable.py", 189*2d1272b8SAndroid Build Coastguard Worker "src/check-c-linkage-decls.py", 190*2d1272b8SAndroid Build Coastguard Worker "src/check-externs.py", 191*2d1272b8SAndroid Build Coastguard Worker "src/check-header-guards.py", 192*2d1272b8SAndroid Build Coastguard Worker "src/check-includes.py", 193*2d1272b8SAndroid Build Coastguard Worker "src/check-libstdc++.py", 194*2d1272b8SAndroid Build Coastguard Worker "src/check-static-inits.py", 195*2d1272b8SAndroid Build Coastguard Worker "src/check-symbols.py", 196*2d1272b8SAndroid Build Coastguard Worker "src/fix_get_types.py", 197*2d1272b8SAndroid Build Coastguard Worker "src/gen-arabic-joining-list.py", 198*2d1272b8SAndroid Build Coastguard Worker "src/gen-arabic-pua.py", 199*2d1272b8SAndroid Build Coastguard Worker "src/gen-arabic-table.py", 200*2d1272b8SAndroid Build Coastguard Worker "src/gen-def.py", 201*2d1272b8SAndroid Build Coastguard Worker "src/gen-emoji-table.py", 202*2d1272b8SAndroid Build Coastguard Worker "src/gen-harfbuzzcc.py", 203*2d1272b8SAndroid Build Coastguard Worker "src/gen-hb-version.py", 204*2d1272b8SAndroid Build Coastguard Worker "src/gen-indic-table.py", 205*2d1272b8SAndroid Build Coastguard Worker "src/gen-os2-unicode-ranges.py", 206*2d1272b8SAndroid Build Coastguard Worker "src/gen-ragel-artifacts.py", 207*2d1272b8SAndroid Build Coastguard Worker "src/gen-tag-table.py", 208*2d1272b8SAndroid Build Coastguard Worker "src/gen-ucd-table.py", 209*2d1272b8SAndroid Build Coastguard Worker "src/gen-use-table.py", 210*2d1272b8SAndroid Build Coastguard Worker "src/gen-vowel-constraints.py", 211*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-cairo.pc.in", 212*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-config.cmake.in", 213*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-gobject.pc.in", 214*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-icu.pc.in", 215*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-subset.cc", 216*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz-subset.pc.in", 217*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz.cc", 218*2d1272b8SAndroid Build Coastguard Worker "src/harfbuzz.pc.in", 219*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-arabic-joining-list.hh", 220*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-arabic-pua.hh", 221*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-arabic-table.hh", 222*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-indic-table.cc", 223*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-use-table.hh", 224*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-shaper-vowel-constraints.cc", 225*2d1272b8SAndroid Build Coastguard Worker "src/hb-ot-tag-table.hh", 226*2d1272b8SAndroid Build Coastguard Worker "src/hb-ucd-table.hh", 227*2d1272b8SAndroid Build Coastguard Worker "src/hb-unicode-emoji-table.hh", 228*2d1272b8SAndroid Build Coastguard Worker "src/justify.py", 229*2d1272b8SAndroid Build Coastguard Worker "src/meson.build", 230*2d1272b8SAndroid Build Coastguard Worker "src/ms-use/IndicPositionalCategory-Additional.txt", 231*2d1272b8SAndroid Build Coastguard Worker "src/ms-use/IndicShapingInvalidCluster.txt", 232*2d1272b8SAndroid Build Coastguard Worker "src/ms-use/IndicSyllabicCategory-Additional.txt", 233*2d1272b8SAndroid Build Coastguard Worker "src/relative_to.py", 234*2d1272b8SAndroid Build Coastguard Worker "src/sample.py", 235*2d1272b8SAndroid Build Coastguard Worker "src/test-use-table.cc", 236*2d1272b8SAndroid Build Coastguard Worker "src/update-unicode-tables.make", 237*2d1272b8SAndroid Build Coastguard Worker "src/wasm/graphite/Makefile", 238*2d1272b8SAndroid Build Coastguard Worker "src/wasm/graphite/shape.cc", 239*2d1272b8SAndroid Build Coastguard Worker "src/wasm/rust/harfbuzz-wasm/Cargo.toml", 240*2d1272b8SAndroid Build Coastguard Worker "src/wasm/rust/harfbuzz-wasm/src/lib.rs", 241*2d1272b8SAndroid Build Coastguard Worker "src/wasm/sample/c/Makefile", 242*2d1272b8SAndroid Build Coastguard Worker "src/wasm/sample/c/shape-fallback.cc", 243*2d1272b8SAndroid Build Coastguard Worker "src/wasm/sample/c/shape-ot.cc", 244*2d1272b8SAndroid Build Coastguard Worker "src/wasm/sample/rust/hello-wasm/Cargo.toml", 245*2d1272b8SAndroid Build Coastguard Worker "src/wasm/sample/rust/hello-wasm/src/lib.rs", 246*2d1272b8SAndroid Build Coastguard Worker "subprojects/.gitignore", 247*2d1272b8SAndroid Build Coastguard Worker "subprojects/cairo.wrap", 248*2d1272b8SAndroid Build Coastguard Worker "subprojects/freetype2.wrap", 249*2d1272b8SAndroid Build Coastguard Worker "subprojects/glib.wrap", 250*2d1272b8SAndroid Build Coastguard Worker "subprojects/google-benchmark.wrap", 251*2d1272b8SAndroid Build Coastguard Worker "subprojects/packagefiles/ragel/meson.build", 252*2d1272b8SAndroid Build Coastguard Worker "subprojects/ragel.wrap", 253*2d1272b8SAndroid Build Coastguard Worker "util/meson.build", 254*2d1272b8SAndroid Build Coastguard Worker "util/test-hb-subset-parsing.c", 255*2d1272b8SAndroid Build Coastguard Worker] 256*2d1272b8SAndroid Build Coastguard Worker 257*2d1272b8SAndroid Build Coastguard Workerclass CommentType(Enum): 258*2d1272b8SAndroid Build Coastguard Worker C_STYLE_BLOCK = 1 # /* ... */ 259*2d1272b8SAndroid Build Coastguard Worker C_STYLE_BLOCK_AS_LINE = 2 # /* ... */ but uses multiple lines of block comments. 260*2d1272b8SAndroid Build Coastguard Worker C_STYLE_LINE = 3 # // ... 261*2d1272b8SAndroid Build Coastguard Worker SCRIPT_STYLE_HASH = 4 # # ... 262*2d1272b8SAndroid Build Coastguard Worker OPENTYPE_NAME = 5 263*2d1272b8SAndroid Build Coastguard Worker OPENTYPE_COLLECTION_NAME = 6 264*2d1272b8SAndroid Build Coastguard Worker UNKNOWN = 10000 265*2d1272b8SAndroid Build Coastguard Worker 266*2d1272b8SAndroid Build Coastguard Worker 267*2d1272b8SAndroid Build Coastguard Worker# Helper function of showing error message and immediate exit. 268*2d1272b8SAndroid Build Coastguard Workerdef fatal(msg: str): 269*2d1272b8SAndroid Build Coastguard Worker sys.stderr.write(str(msg)) 270*2d1272b8SAndroid Build Coastguard Worker sys.stderr.write("\n") 271*2d1272b8SAndroid Build Coastguard Worker sys.exit(1) 272*2d1272b8SAndroid Build Coastguard Worker 273*2d1272b8SAndroid Build Coastguard Worker 274*2d1272b8SAndroid Build Coastguard Workerdef warn(msg: str): 275*2d1272b8SAndroid Build Coastguard Worker sys.stderr.write(str(msg)) 276*2d1272b8SAndroid Build Coastguard Worker sys.stderr.write("\n") 277*2d1272b8SAndroid Build Coastguard Worker 278*2d1272b8SAndroid Build Coastguard Workerdef debug(msg: str): 279*2d1272b8SAndroid Build Coastguard Worker # sys.stderr.write(str(msg)) 280*2d1272b8SAndroid Build Coastguard Worker # sys.stderr.write("\n") 281*2d1272b8SAndroid Build Coastguard Worker pass 282*2d1272b8SAndroid Build Coastguard Worker 283*2d1272b8SAndroid Build Coastguard Worker 284*2d1272b8SAndroid Build Coastguard Workerdef cleanup_and_join(out_lines: Sequence[str]): 285*2d1272b8SAndroid Build Coastguard Worker while not out_lines[-1].strip(): 286*2d1272b8SAndroid Build Coastguard Worker out_lines.pop(-1) 287*2d1272b8SAndroid Build Coastguard Worker 288*2d1272b8SAndroid Build Coastguard Worker # If all lines starts from empty space, strip it out. 289*2d1272b8SAndroid Build Coastguard Worker while all([len(x) == 0 or x[0] == ' ' for x in out_lines]): 290*2d1272b8SAndroid Build Coastguard Worker out_lines = [x[1:] for x in out_lines] 291*2d1272b8SAndroid Build Coastguard Worker 292*2d1272b8SAndroid Build Coastguard Worker if not out_lines: 293*2d1272b8SAndroid Build Coastguard Worker fatal("Failed to get copyright info") 294*2d1272b8SAndroid Build Coastguard Worker return "\n".join(out_lines) 295*2d1272b8SAndroid Build Coastguard Worker 296*2d1272b8SAndroid Build Coastguard Worker 297*2d1272b8SAndroid Build Coastguard Workerdef get_comment_type(copyright_line: str, path_str: str) -> CommentType: 298*2d1272b8SAndroid Build Coastguard Worker # vms_make.com contains multiple copyright header as a string constants. 299*2d1272b8SAndroid Build Coastguard Worker if copyright_line.startswith("#"): 300*2d1272b8SAndroid Build Coastguard Worker return CommentType.SCRIPT_STYLE_HASH 301*2d1272b8SAndroid Build Coastguard Worker if copyright_line.startswith("//"): 302*2d1272b8SAndroid Build Coastguard Worker return CommentType.C_STYLE_LINE 303*2d1272b8SAndroid Build Coastguard Worker return CommentType.C_STYLE_BLOCK 304*2d1272b8SAndroid Build Coastguard Worker 305*2d1272b8SAndroid Build Coastguard Workerdef extract_copyright_font(path_str: str) -> str: 306*2d1272b8SAndroid Build Coastguard Worker path = Path(path_str) 307*2d1272b8SAndroid Build Coastguard Worker if path.suffix in ['.ttf', '.otf', '.dfont']: 308*2d1272b8SAndroid Build Coastguard Worker return extract_from_opentype_name(path, 0) 309*2d1272b8SAndroid Build Coastguard Worker elif path.suffix in ['.ttc', '.otc']: 310*2d1272b8SAndroid Build Coastguard Worker return extract_from_opentype_collection_name(path) 311*2d1272b8SAndroid Build Coastguard Worker 312*2d1272b8SAndroid Build Coastguard Worker 313*2d1272b8SAndroid Build Coastguard Worker# Extract copyright notice and returns next index. 314*2d1272b8SAndroid Build Coastguard Workerdef extract_copyright_at(lines: Sequence[str], i: int, path: str) -> Tuple[str, int]: 315*2d1272b8SAndroid Build Coastguard Worker commentType = get_comment_type(lines[i], path) 316*2d1272b8SAndroid Build Coastguard Worker 317*2d1272b8SAndroid Build Coastguard Worker if commentType == CommentType.C_STYLE_BLOCK: 318*2d1272b8SAndroid Build Coastguard Worker return extract_from_c_style_block_at(lines, i, path) 319*2d1272b8SAndroid Build Coastguard Worker elif commentType == CommentType.C_STYLE_LINE: 320*2d1272b8SAndroid Build Coastguard Worker return extract_from_c_style_lines_at(lines, i, path) 321*2d1272b8SAndroid Build Coastguard Worker elif commentType == CommentType.SCRIPT_STYLE_HASH: 322*2d1272b8SAndroid Build Coastguard Worker return extract_from_script_hash_at(lines, i, path) 323*2d1272b8SAndroid Build Coastguard Worker else: 324*2d1272b8SAndroid Build Coastguard Worker fatal("Uknown comment style: %s" % lines[i]) 325*2d1272b8SAndroid Build Coastguard Worker 326*2d1272b8SAndroid Build Coastguard Workerdef extract_from_opentype_collection_name(path: str) -> str: 327*2d1272b8SAndroid Build Coastguard Worker 328*2d1272b8SAndroid Build Coastguard Worker with open(path, mode="rb") as f: 329*2d1272b8SAndroid Build Coastguard Worker head = f.read(12) 330*2d1272b8SAndroid Build Coastguard Worker 331*2d1272b8SAndroid Build Coastguard Worker if head[0:4].decode() != 'ttcf': 332*2d1272b8SAndroid Build Coastguard Worker fatal('Invalid magic number for TTC file: %s' % path) 333*2d1272b8SAndroid Build Coastguard Worker numFonts = int.from_bytes(head[8:12], byteorder="big") 334*2d1272b8SAndroid Build Coastguard Worker 335*2d1272b8SAndroid Build Coastguard Worker licenses = set() 336*2d1272b8SAndroid Build Coastguard Worker for i in range(0, numFonts): 337*2d1272b8SAndroid Build Coastguard Worker license = extract_from_opentype_name(path, i) 338*2d1272b8SAndroid Build Coastguard Worker licenses.add(license) 339*2d1272b8SAndroid Build Coastguard Worker 340*2d1272b8SAndroid Build Coastguard Worker return '\n\n'.join(licenses) 341*2d1272b8SAndroid Build Coastguard Worker 342*2d1272b8SAndroid Build Coastguard Workerdef extract_from_opentype_name(path: str, index: int) -> str: 343*2d1272b8SAndroid Build Coastguard Worker 344*2d1272b8SAndroid Build Coastguard Worker def get_preferred_name(nameID: int, ttf): 345*2d1272b8SAndroid Build Coastguard Worker def get_score(platID: int, encID: int): 346*2d1272b8SAndroid Build Coastguard Worker if platID == 3 and encID == 10: 347*2d1272b8SAndroid Build Coastguard Worker return 0 348*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 6: 349*2d1272b8SAndroid Build Coastguard Worker return 1 350*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 4: 351*2d1272b8SAndroid Build Coastguard Worker return 2 352*2d1272b8SAndroid Build Coastguard Worker elif platID == 3 and encID == 1: 353*2d1272b8SAndroid Build Coastguard Worker return 3 354*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 3: 355*2d1272b8SAndroid Build Coastguard Worker return 4 356*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 2: 357*2d1272b8SAndroid Build Coastguard Worker return 5 358*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 1: 359*2d1272b8SAndroid Build Coastguard Worker return 6 360*2d1272b8SAndroid Build Coastguard Worker elif platID == 0 and encID == 0: 361*2d1272b8SAndroid Build Coastguard Worker return 7 362*2d1272b8SAndroid Build Coastguard Worker else: 363*2d1272b8SAndroid Build Coastguard Worker return 10000 364*2d1272b8SAndroid Build Coastguard Worker 365*2d1272b8SAndroid Build Coastguard Worker best_score = 1000000 366*2d1272b8SAndroid Build Coastguard Worker best_name = None 367*2d1272b8SAndroid Build Coastguard Worker 368*2d1272b8SAndroid Build Coastguard Worker if 'name' not in ttf: 369*2d1272b8SAndroid Build Coastguard Worker return None 370*2d1272b8SAndroid Build Coastguard Worker 371*2d1272b8SAndroid Build Coastguard Worker for name in ttf['name'].names: 372*2d1272b8SAndroid Build Coastguard Worker if name.nameID != nameID: 373*2d1272b8SAndroid Build Coastguard Worker continue 374*2d1272b8SAndroid Build Coastguard Worker 375*2d1272b8SAndroid Build Coastguard Worker score = get_score(name.platformID, name.platEncID) 376*2d1272b8SAndroid Build Coastguard Worker if score < best_score: 377*2d1272b8SAndroid Build Coastguard Worker best_score = score 378*2d1272b8SAndroid Build Coastguard Worker best_name = name 379*2d1272b8SAndroid Build Coastguard Worker 380*2d1272b8SAndroid Build Coastguard Worker return best_name 381*2d1272b8SAndroid Build Coastguard Worker 382*2d1272b8SAndroid Build Coastguard Worker def get_notice_from_cff(ttf): 383*2d1272b8SAndroid Build Coastguard Worker if 'CFF ' not in ttf: 384*2d1272b8SAndroid Build Coastguard Worker return None 385*2d1272b8SAndroid Build Coastguard Worker 386*2d1272b8SAndroid Build Coastguard Worker # Looks like there is no way of getting Notice line in CFF table. 387*2d1272b8SAndroid Build Coastguard Worker # Use the line that has "Copyright" in the string pool. 388*2d1272b8SAndroid Build Coastguard Worker cff = ttf['CFF '].cff 389*2d1272b8SAndroid Build Coastguard Worker for string in cff.strings: 390*2d1272b8SAndroid Build Coastguard Worker if 'Copyright' in string: 391*2d1272b8SAndroid Build Coastguard Worker return string 392*2d1272b8SAndroid Build Coastguard Worker return None 393*2d1272b8SAndroid Build Coastguard Worker 394*2d1272b8SAndroid Build Coastguard Worker with contextlib.closing(ttLib.TTFont(path, 0, fontNumber=index)) as ttf: 395*2d1272b8SAndroid Build Coastguard Worker copyright = get_preferred_name(0, ttf) 396*2d1272b8SAndroid Build Coastguard Worker if not copyright: 397*2d1272b8SAndroid Build Coastguard Worker copyright = get_notice_from_cff(ttf) 398*2d1272b8SAndroid Build Coastguard Worker if not copyright: 399*2d1272b8SAndroid Build Coastguard Worker return None 400*2d1272b8SAndroid Build Coastguard Worker 401*2d1272b8SAndroid Build Coastguard Worker license_description = get_preferred_name(13, ttf) 402*2d1272b8SAndroid Build Coastguard Worker 403*2d1272b8SAndroid Build Coastguard Worker if license_description: 404*2d1272b8SAndroid Build Coastguard Worker copyright = str(copyright) + "\n\n" + str(license_description) 405*2d1272b8SAndroid Build Coastguard Worker else: 406*2d1272b8SAndroid Build Coastguard Worker copyright = str(copyright) 407*2d1272b8SAndroid Build Coastguard Worker 408*2d1272b8SAndroid Build Coastguard Worker license_url = get_preferred_name(14, ttf) 409*2d1272b8SAndroid Build Coastguard Worker 410*2d1272b8SAndroid Build Coastguard Worker if license_url: 411*2d1272b8SAndroid Build Coastguard Worker copyright = str(copyright) + "\n\n" + str(license_url) 412*2d1272b8SAndroid Build Coastguard Worker else: 413*2d1272b8SAndroid Build Coastguard Worker copyright = str(copyright) 414*2d1272b8SAndroid Build Coastguard Worker 415*2d1272b8SAndroid Build Coastguard Worker return copyright 416*2d1272b8SAndroid Build Coastguard Worker 417*2d1272b8SAndroid Build Coastguard Workerdef extract_from_c_style_lines_at( 418*2d1272b8SAndroid Build Coastguard Worker lines: Sequence[str], i: int, path: str) -> Tuple[str, int]: 419*2d1272b8SAndroid Build Coastguard Worker def is_copyright_end(line): 420*2d1272b8SAndroid Build Coastguard Worker if line.startswith("//"): 421*2d1272b8SAndroid Build Coastguard Worker return False 422*2d1272b8SAndroid Build Coastguard Worker else: 423*2d1272b8SAndroid Build Coastguard Worker return True 424*2d1272b8SAndroid Build Coastguard Worker start = i 425*2d1272b8SAndroid Build Coastguard Worker while i < len(lines): 426*2d1272b8SAndroid Build Coastguard Worker if is_copyright_end(lines[i]): 427*2d1272b8SAndroid Build Coastguard Worker break 428*2d1272b8SAndroid Build Coastguard Worker i += 1 429*2d1272b8SAndroid Build Coastguard Worker end = i 430*2d1272b8SAndroid Build Coastguard Worker 431*2d1272b8SAndroid Build Coastguard Worker if start == end: 432*2d1272b8SAndroid Build Coastguard Worker fatal("Failed to get copyright info") 433*2d1272b8SAndroid Build Coastguard Worker 434*2d1272b8SAndroid Build Coastguard Worker out_lines = [] 435*2d1272b8SAndroid Build Coastguard Worker for line in lines[start:end]: 436*2d1272b8SAndroid Build Coastguard Worker if line.startswith("//# "): # Andorid.bp uses //# style 437*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[4:]) 438*2d1272b8SAndroid Build Coastguard Worker elif line.startswith("//#"): # Andorid.bp uses //# style 439*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[3:]) 440*2d1272b8SAndroid Build Coastguard Worker elif line.startswith("// "): 441*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[3:]) 442*2d1272b8SAndroid Build Coastguard Worker elif line == "//": 443*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[2:]) 444*2d1272b8SAndroid Build Coastguard Worker else: 445*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line) 446*2d1272b8SAndroid Build Coastguard Worker 447*2d1272b8SAndroid Build Coastguard Worker return (cleanup_and_join(out_lines), i + 1) 448*2d1272b8SAndroid Build Coastguard Worker 449*2d1272b8SAndroid Build Coastguard Worker 450*2d1272b8SAndroid Build Coastguard Workerdef extract_from_script_hash_at( 451*2d1272b8SAndroid Build Coastguard Worker lines: Sequence[str], i: int, path: str) -> Tuple[str, int]: 452*2d1272b8SAndroid Build Coastguard Worker if lines[i].strip()[0] != "#": 453*2d1272b8SAndroid Build Coastguard Worker return (None, i + 1) 454*2d1272b8SAndroid Build Coastguard Worker def is_copyright_end(lines: str, i: int) -> bool: 455*2d1272b8SAndroid Build Coastguard Worker if "#" not in lines[i]: 456*2d1272b8SAndroid Build Coastguard Worker return True 457*2d1272b8SAndroid Build Coastguard Worker # treat double spacing as end of license header 458*2d1272b8SAndroid Build Coastguard Worker if lines[i] == "#" and lines[i+1] == "#": 459*2d1272b8SAndroid Build Coastguard Worker return True 460*2d1272b8SAndroid Build Coastguard Worker return False 461*2d1272b8SAndroid Build Coastguard Worker 462*2d1272b8SAndroid Build Coastguard Worker start = i 463*2d1272b8SAndroid Build Coastguard Worker while i < len(lines): 464*2d1272b8SAndroid Build Coastguard Worker if is_copyright_end(lines, i): 465*2d1272b8SAndroid Build Coastguard Worker break 466*2d1272b8SAndroid Build Coastguard Worker i += 1 467*2d1272b8SAndroid Build Coastguard Worker end = i 468*2d1272b8SAndroid Build Coastguard Worker 469*2d1272b8SAndroid Build Coastguard Worker if start == end: 470*2d1272b8SAndroid Build Coastguard Worker fatal("Failed to get copyright info") 471*2d1272b8SAndroid Build Coastguard Worker 472*2d1272b8SAndroid Build Coastguard Worker out_lines = [] 473*2d1272b8SAndroid Build Coastguard Worker for line in lines[start:end]: 474*2d1272b8SAndroid Build Coastguard Worker if line.startswith("# "): 475*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[2:]) 476*2d1272b8SAndroid Build Coastguard Worker elif line == "#": 477*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line[1:]) 478*2d1272b8SAndroid Build Coastguard Worker else: 479*2d1272b8SAndroid Build Coastguard Worker out_lines.append(line) 480*2d1272b8SAndroid Build Coastguard Worker 481*2d1272b8SAndroid Build Coastguard Worker return (cleanup_and_join(out_lines), i + 1) 482*2d1272b8SAndroid Build Coastguard Worker 483*2d1272b8SAndroid Build Coastguard Worker 484*2d1272b8SAndroid Build Coastguard Workerdef extract_from_c_style_block_at( 485*2d1272b8SAndroid Build Coastguard Worker lines: Sequence[str], i: int, path: str) -> Tuple[str, int]: 486*2d1272b8SAndroid Build Coastguard Worker 487*2d1272b8SAndroid Build Coastguard Worker def is_copyright_end(lines: str, i: int) -> bool: 488*2d1272b8SAndroid Build Coastguard Worker if "*/" in lines[i]: 489*2d1272b8SAndroid Build Coastguard Worker return True 490*2d1272b8SAndroid Build Coastguard Worker if lines[i] == " *" and lines[i + 1] == " *": 491*2d1272b8SAndroid Build Coastguard Worker return True 492*2d1272b8SAndroid Build Coastguard Worker if lines[i] == "" and lines[i + 1] == "": 493*2d1272b8SAndroid Build Coastguard Worker return True 494*2d1272b8SAndroid Build Coastguard Worker return False 495*2d1272b8SAndroid Build Coastguard Worker 496*2d1272b8SAndroid Build Coastguard Worker start = i 497*2d1272b8SAndroid Build Coastguard Worker i += 1 # include at least one line 498*2d1272b8SAndroid Build Coastguard Worker while i < len(lines): 499*2d1272b8SAndroid Build Coastguard Worker if is_copyright_end(lines, i): 500*2d1272b8SAndroid Build Coastguard Worker break 501*2d1272b8SAndroid Build Coastguard Worker i += 1 502*2d1272b8SAndroid Build Coastguard Worker end = i + 1 503*2d1272b8SAndroid Build Coastguard Worker 504*2d1272b8SAndroid Build Coastguard Worker out_lines = [] 505*2d1272b8SAndroid Build Coastguard Worker for line in lines[start:end]: 506*2d1272b8SAndroid Build Coastguard Worker clean_line = line 507*2d1272b8SAndroid Build Coastguard Worker 508*2d1272b8SAndroid Build Coastguard Worker # Strip begining "/*" chars 509*2d1272b8SAndroid Build Coastguard Worker if clean_line.startswith("/* "): 510*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[3:] 511*2d1272b8SAndroid Build Coastguard Worker if clean_line == "/*": 512*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[2:] 513*2d1272b8SAndroid Build Coastguard Worker 514*2d1272b8SAndroid Build Coastguard Worker # Strip ending "*/" chars 515*2d1272b8SAndroid Build Coastguard Worker if clean_line.endswith(" */"): 516*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[:-3] 517*2d1272b8SAndroid Build Coastguard Worker if clean_line.endswith("*/"): 518*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[:-2] 519*2d1272b8SAndroid Build Coastguard Worker 520*2d1272b8SAndroid Build Coastguard Worker # Strip starting " *" chars 521*2d1272b8SAndroid Build Coastguard Worker if clean_line.startswith(" * "): 522*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[3:] 523*2d1272b8SAndroid Build Coastguard Worker if clean_line == " *": 524*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line[2:] 525*2d1272b8SAndroid Build Coastguard Worker 526*2d1272b8SAndroid Build Coastguard Worker # hb-aots-tester.cpp has underline separater which can be dropped. 527*2d1272b8SAndroid Build Coastguard Worker if path.endswith("test/shape/data/aots/hb-aots-tester.cpp"): 528*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line.replace("_", "") 529*2d1272b8SAndroid Build Coastguard Worker 530*2d1272b8SAndroid Build Coastguard Worker # Strip trailing spaces 531*2d1272b8SAndroid Build Coastguard Worker clean_line = clean_line.rstrip() 532*2d1272b8SAndroid Build Coastguard Worker 533*2d1272b8SAndroid Build Coastguard Worker out_lines.append(clean_line) 534*2d1272b8SAndroid Build Coastguard Worker 535*2d1272b8SAndroid Build Coastguard Worker return (cleanup_and_join(out_lines), i + 1) 536*2d1272b8SAndroid Build Coastguard Worker 537*2d1272b8SAndroid Build Coastguard Worker 538*2d1272b8SAndroid Build Coastguard Worker# Returns true if the line shows the start of copyright notice. 539*2d1272b8SAndroid Build Coastguard Workerdef is_copyright_line(line: str, path: str) -> bool: 540*2d1272b8SAndroid Build Coastguard Worker if "Copyright" not in line: 541*2d1272b8SAndroid Build Coastguard Worker return False 542*2d1272b8SAndroid Build Coastguard Worker 543*2d1272b8SAndroid Build Coastguard Worker # For avoiding unexpected mismatches, exclude quoted Copyright string. 544*2d1272b8SAndroid Build Coastguard Worker if "`Copyright'" in line: 545*2d1272b8SAndroid Build Coastguard Worker return False 546*2d1272b8SAndroid Build Coastguard Worker if "\"Copyright\"" in line: 547*2d1272b8SAndroid Build Coastguard Worker return False 548*2d1272b8SAndroid Build Coastguard Worker 549*2d1272b8SAndroid Build Coastguard Worker if "OpCode_Copyright" in line: 550*2d1272b8SAndroid Build Coastguard Worker return False 551*2d1272b8SAndroid Build Coastguard Worker 552*2d1272b8SAndroid Build Coastguard Worker if path.endswith("src/hb-ot-name.h") and "HB_OT_NAME_ID_COPYRIGHT" in line: 553*2d1272b8SAndroid Build Coastguard Worker return False 554*2d1272b8SAndroid Build Coastguard Worker 555*2d1272b8SAndroid Build Coastguard Worker return True 556*2d1272b8SAndroid Build Coastguard Worker 557*2d1272b8SAndroid Build Coastguard Workerdef assert_mandatory_copyright(path_str: str): 558*2d1272b8SAndroid Build Coastguard Worker path = Path(path_str) 559*2d1272b8SAndroid Build Coastguard Worker toplevel_dir = str(path).split(os.sep)[0] 560*2d1272b8SAndroid Build Coastguard Worker 561*2d1272b8SAndroid Build Coastguard Worker if toplevel_dir in IGNORE_DIR_IF_NO_COPYRIGHT: 562*2d1272b8SAndroid Build Coastguard Worker return 563*2d1272b8SAndroid Build Coastguard Worker 564*2d1272b8SAndroid Build Coastguard Worker fatal("%s does not contain Copyright line" % path) 565*2d1272b8SAndroid Build Coastguard Worker 566*2d1272b8SAndroid Build Coastguard Worker 567*2d1272b8SAndroid Build Coastguard Worker# Extract the copyright notice and put it into copyrights arg. 568*2d1272b8SAndroid Build Coastguard Workerdef do_file(path: str, copyrights: set, no_copyright_files: set): 569*2d1272b8SAndroid Build Coastguard Worker raw = Path(path).read_bytes() 570*2d1272b8SAndroid Build Coastguard Worker basename = os.path.basename(path) 571*2d1272b8SAndroid Build Coastguard Worker dirname = os.path.dirname(path) 572*2d1272b8SAndroid Build Coastguard Worker 573*2d1272b8SAndroid Build Coastguard Worker is_font = (dirname.endswith('./test/fuzzing/fonts') or 574*2d1272b8SAndroid Build Coastguard Worker Path(path).suffix in ['.ttf', '.otf', '.dfont', '.ttc', '.otc']) 575*2d1272b8SAndroid Build Coastguard Worker 576*2d1272b8SAndroid Build Coastguard Worker if is_font: 577*2d1272b8SAndroid Build Coastguard Worker notice = extract_copyright_font(path) 578*2d1272b8SAndroid Build Coastguard Worker if not notice: 579*2d1272b8SAndroid Build Coastguard Worker assert_mandatory_copyright(path) 580*2d1272b8SAndroid Build Coastguard Worker return 581*2d1272b8SAndroid Build Coastguard Worker 582*2d1272b8SAndroid Build Coastguard Worker if not notice in copyrights: 583*2d1272b8SAndroid Build Coastguard Worker copyrights[notice] = [] 584*2d1272b8SAndroid Build Coastguard Worker copyrights[notice].append(path) 585*2d1272b8SAndroid Build Coastguard Worker else: 586*2d1272b8SAndroid Build Coastguard Worker try: 587*2d1272b8SAndroid Build Coastguard Worker content = raw.decode("utf-8") 588*2d1272b8SAndroid Build Coastguard Worker except UnicodeDecodeError: 589*2d1272b8SAndroid Build Coastguard Worker content = raw.decode("iso-8859-1") 590*2d1272b8SAndroid Build Coastguard Worker 591*2d1272b8SAndroid Build Coastguard Worker if not "Copyright" in content: 592*2d1272b8SAndroid Build Coastguard Worker if path in no_copyright_files: 593*2d1272b8SAndroid Build Coastguard Worker no_copyright_files.remove(path) 594*2d1272b8SAndroid Build Coastguard Worker else: 595*2d1272b8SAndroid Build Coastguard Worker assert_mandatory_copyright(path) 596*2d1272b8SAndroid Build Coastguard Worker return 597*2d1272b8SAndroid Build Coastguard Worker 598*2d1272b8SAndroid Build Coastguard Worker lines = content.splitlines() 599*2d1272b8SAndroid Build Coastguard Worker 600*2d1272b8SAndroid Build Coastguard Worker # The COPYING in the in-house dir has full OFL license with description. 601*2d1272b8SAndroid Build Coastguard Worker # Use the OFL license description body. 602*2d1272b8SAndroid Build Coastguard Worker if path.endswith("test/shape/data/in-house/COPYING") or path.endswith("test/COPYING"): 603*2d1272b8SAndroid Build Coastguard Worker notice = cleanup_and_join(lines[9:]) 604*2d1272b8SAndroid Build Coastguard Worker copyrights.setdefault(notice, []) 605*2d1272b8SAndroid Build Coastguard Worker copyrights[notice].append(path) 606*2d1272b8SAndroid Build Coastguard Worker return 607*2d1272b8SAndroid Build Coastguard Worker 608*2d1272b8SAndroid Build Coastguard Worker # The COPYING in the top dir has MIT-Modern-Variant license with description. 609*2d1272b8SAndroid Build Coastguard Worker # Use the entire file as a license notice. 610*2d1272b8SAndroid Build Coastguard Worker if path.endswith("COPYING") and str(Path(path)) == 'COPYING': 611*2d1272b8SAndroid Build Coastguard Worker notice = cleanup_and_join(lines) 612*2d1272b8SAndroid Build Coastguard Worker copyrights.setdefault(notice, []) 613*2d1272b8SAndroid Build Coastguard Worker copyrights[notice].append(path) 614*2d1272b8SAndroid Build Coastguard Worker return 615*2d1272b8SAndroid Build Coastguard Worker 616*2d1272b8SAndroid Build Coastguard Worker i = 0 617*2d1272b8SAndroid Build Coastguard Worker license_found = False 618*2d1272b8SAndroid Build Coastguard Worker while i < len(lines): 619*2d1272b8SAndroid Build Coastguard Worker if is_copyright_line(lines[i], path): 620*2d1272b8SAndroid Build Coastguard Worker (notice, nexti) = extract_copyright_at(lines, i, path) 621*2d1272b8SAndroid Build Coastguard Worker if notice: 622*2d1272b8SAndroid Build Coastguard Worker copyrights.setdefault(notice, []) 623*2d1272b8SAndroid Build Coastguard Worker copyrights[notice].append(path) 624*2d1272b8SAndroid Build Coastguard Worker license_found = True 625*2d1272b8SAndroid Build Coastguard Worker 626*2d1272b8SAndroid Build Coastguard Worker i = nexti 627*2d1272b8SAndroid Build Coastguard Worker else: 628*2d1272b8SAndroid Build Coastguard Worker i += 1 629*2d1272b8SAndroid Build Coastguard Worker 630*2d1272b8SAndroid Build Coastguard Worker if not license_found: 631*2d1272b8SAndroid Build Coastguard Worker assert_mandatory_copyright(path) 632*2d1272b8SAndroid Build Coastguard Worker 633*2d1272b8SAndroid Build Coastguard Workerdef do_check(path, format): 634*2d1272b8SAndroid Build Coastguard Worker if not path.endswith('/'): # make sure the path ends with slash 635*2d1272b8SAndroid Build Coastguard Worker path = path + '/' 636*2d1272b8SAndroid Build Coastguard Worker 637*2d1272b8SAndroid Build Coastguard Worker file_to_ignore = set([os.path.join(path, x) for x in IGNORE_FILE_NAME]) 638*2d1272b8SAndroid Build Coastguard Worker no_copyright_files = set([os.path.join(path, x) for x in NO_COPYRIGHT_FILES]) 639*2d1272b8SAndroid Build Coastguard Worker copyrights = {} 640*2d1272b8SAndroid Build Coastguard Worker 641*2d1272b8SAndroid Build Coastguard Worker for directory, sub_directories, filenames in os.walk(path): 642*2d1272b8SAndroid Build Coastguard Worker # skip .git directory 643*2d1272b8SAndroid Build Coastguard Worker if ".git" in sub_directories: 644*2d1272b8SAndroid Build Coastguard Worker sub_directories.remove(".git") 645*2d1272b8SAndroid Build Coastguard Worker 646*2d1272b8SAndroid Build Coastguard Worker for fname in filenames: 647*2d1272b8SAndroid Build Coastguard Worker fpath = os.path.join(directory, fname) 648*2d1272b8SAndroid Build Coastguard Worker if fpath in file_to_ignore: 649*2d1272b8SAndroid Build Coastguard Worker file_to_ignore.remove(fpath) 650*2d1272b8SAndroid Build Coastguard Worker continue 651*2d1272b8SAndroid Build Coastguard Worker 652*2d1272b8SAndroid Build Coastguard Worker do_file(fpath, copyrights, no_copyright_files) 653*2d1272b8SAndroid Build Coastguard Worker 654*2d1272b8SAndroid Build Coastguard Worker if len(file_to_ignore) != 0: 655*2d1272b8SAndroid Build Coastguard Worker fatal("Following files are listed in IGNORE_FILE_NAME but doesn't exists,.\n" 656*2d1272b8SAndroid Build Coastguard Worker + "\n".join(file_to_ignore)) 657*2d1272b8SAndroid Build Coastguard Worker 658*2d1272b8SAndroid Build Coastguard Worker if len(no_copyright_files) != 0: 659*2d1272b8SAndroid Build Coastguard Worker fatal("Following files are listed in NO_COPYRIGHT_FILES but doesn't exists.\n" 660*2d1272b8SAndroid Build Coastguard Worker + "\n".join(no_copyright_files)) 661*2d1272b8SAndroid Build Coastguard Worker 662*2d1272b8SAndroid Build Coastguard Worker if format == Format.notice: 663*2d1272b8SAndroid Build Coastguard Worker print_notice(copyrights, False) 664*2d1272b8SAndroid Build Coastguard Worker elif format == Format.notice_with_filename: 665*2d1272b8SAndroid Build Coastguard Worker print_notice(copyrights, True) 666*2d1272b8SAndroid Build Coastguard Worker elif format == Format.html: 667*2d1272b8SAndroid Build Coastguard Worker print_html(copyrights) 668*2d1272b8SAndroid Build Coastguard Worker elif format == Format.json: 669*2d1272b8SAndroid Build Coastguard Worker print_json(copyrights) 670*2d1272b8SAndroid Build Coastguard Worker 671*2d1272b8SAndroid Build Coastguard Workerdef print_html(copyrights): 672*2d1272b8SAndroid Build Coastguard Worker print('<html>') 673*2d1272b8SAndroid Build Coastguard Worker print(""" 674*2d1272b8SAndroid Build Coastguard Worker <head> 675*2d1272b8SAndroid Build Coastguard Worker <style> 676*2d1272b8SAndroid Build Coastguard Worker table { 677*2d1272b8SAndroid Build Coastguard Worker font-family: monospace 678*2d1272b8SAndroid Build Coastguard Worker } 679*2d1272b8SAndroid Build Coastguard Worker 680*2d1272b8SAndroid Build Coastguard Worker table tr td { 681*2d1272b8SAndroid Build Coastguard Worker padding: 10px 10px 10px 10px 682*2d1272b8SAndroid Build Coastguard Worker } 683*2d1272b8SAndroid Build Coastguard Worker </style> 684*2d1272b8SAndroid Build Coastguard Worker </head> 685*2d1272b8SAndroid Build Coastguard Worker """) 686*2d1272b8SAndroid Build Coastguard Worker print('<body>') 687*2d1272b8SAndroid Build Coastguard Worker print('<table border="1" style="border-collapse:collapse">') 688*2d1272b8SAndroid Build Coastguard Worker for notice in sorted(copyrights.keys()): 689*2d1272b8SAndroid Build Coastguard Worker files = sorted(copyrights[notice]) 690*2d1272b8SAndroid Build Coastguard Worker 691*2d1272b8SAndroid Build Coastguard Worker print('<tr>') 692*2d1272b8SAndroid Build Coastguard Worker print('<td>') 693*2d1272b8SAndroid Build Coastguard Worker print('<ul>') 694*2d1272b8SAndroid Build Coastguard Worker for file in files: 695*2d1272b8SAndroid Build Coastguard Worker print('<li>%s</li>' % file) 696*2d1272b8SAndroid Build Coastguard Worker print('</ul>') 697*2d1272b8SAndroid Build Coastguard Worker print('</td>') 698*2d1272b8SAndroid Build Coastguard Worker 699*2d1272b8SAndroid Build Coastguard Worker print('<td>') 700*2d1272b8SAndroid Build Coastguard Worker print('<p>%s</p>' % notice.replace('\n', '<br>')) 701*2d1272b8SAndroid Build Coastguard Worker print('</td>') 702*2d1272b8SAndroid Build Coastguard Worker 703*2d1272b8SAndroid Build Coastguard Worker print('</tr>') 704*2d1272b8SAndroid Build Coastguard Worker 705*2d1272b8SAndroid Build Coastguard Worker 706*2d1272b8SAndroid Build Coastguard Worker print('</table>') 707*2d1272b8SAndroid Build Coastguard Worker print('</body></html>') 708*2d1272b8SAndroid Build Coastguard Worker 709*2d1272b8SAndroid Build Coastguard Workerdef print_notice(copyrights, print_file): 710*2d1272b8SAndroid Build Coastguard Worker # print the copyright in sorted order for stable output. 711*2d1272b8SAndroid Build Coastguard Worker for notice in sorted(copyrights.keys()): 712*2d1272b8SAndroid Build Coastguard Worker if print_file: 713*2d1272b8SAndroid Build Coastguard Worker files = sorted(copyrights[notice]) 714*2d1272b8SAndroid Build Coastguard Worker print("\n".join(files)) 715*2d1272b8SAndroid Build Coastguard Worker print() 716*2d1272b8SAndroid Build Coastguard Worker print(notice) 717*2d1272b8SAndroid Build Coastguard Worker print() 718*2d1272b8SAndroid Build Coastguard Worker print("-" * 67) 719*2d1272b8SAndroid Build Coastguard Worker print() 720*2d1272b8SAndroid Build Coastguard Worker 721*2d1272b8SAndroid Build Coastguard Workerdef print_json(copyrights): 722*2d1272b8SAndroid Build Coastguard Worker print(json.dumps(copyrights)) 723*2d1272b8SAndroid Build Coastguard Worker 724*2d1272b8SAndroid Build Coastguard Workerclass Format(Enum): 725*2d1272b8SAndroid Build Coastguard Worker notice = 'notice' 726*2d1272b8SAndroid Build Coastguard Worker notice_with_filename = 'notice_with_filename' 727*2d1272b8SAndroid Build Coastguard Worker html = 'html' 728*2d1272b8SAndroid Build Coastguard Worker json = 'json' 729*2d1272b8SAndroid Build Coastguard Worker 730*2d1272b8SAndroid Build Coastguard Worker def __str__(self): 731*2d1272b8SAndroid Build Coastguard Worker return self.value 732*2d1272b8SAndroid Build Coastguard Worker 733*2d1272b8SAndroid Build Coastguard Workerdef main(): 734*2d1272b8SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description="Collect notice headers.") 735*2d1272b8SAndroid Build Coastguard Worker parser.add_argument("--format", dest="format", type=Format, choices=list(Format), 736*2d1272b8SAndroid Build Coastguard Worker default=Format.notice, help="print filename before the license notice") 737*2d1272b8SAndroid Build Coastguard Worker parser.add_argument("--target", dest="target", action='store', 738*2d1272b8SAndroid Build Coastguard Worker required=True, help="target directory to collect notice headers") 739*2d1272b8SAndroid Build Coastguard Worker res = parser.parse_args() 740*2d1272b8SAndroid Build Coastguard Worker do_check(res.target, res.format) 741*2d1272b8SAndroid Build Coastguard Worker 742*2d1272b8SAndroid Build Coastguard Workerif __name__ == "__main__": 743*2d1272b8SAndroid Build Coastguard Worker main() 744*2d1272b8SAndroid Build Coastguard Worker 745