mirror of
				https://github.com/facebook/zstd.git
				synced 2025-11-04 00:02:59 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
 | 
						|
# ################################################################
 | 
						|
# Copyright (c) Meta Platforms, Inc. and affiliates.
 | 
						|
# All rights reserved.
 | 
						|
#
 | 
						|
# This source code is licensed under both the BSD-style license (found in the
 | 
						|
# LICENSE file in the root directory of this source tree) and the GPLv2 (found
 | 
						|
# in the COPYING file in the root directory of this source tree).
 | 
						|
# You may select, at your option, one of the above-listed licenses.
 | 
						|
# ################################################################
 | 
						|
 | 
						|
import enum
 | 
						|
import glob
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sys
 | 
						|
 | 
						|
ROOT = os.path.join(os.path.dirname(__file__), "..")
 | 
						|
 | 
						|
RELDIRS = [
 | 
						|
    "doc",
 | 
						|
    "examples",
 | 
						|
    "lib",
 | 
						|
    "programs",
 | 
						|
    "tests",
 | 
						|
    "contrib/linux-kernel",
 | 
						|
]
 | 
						|
 | 
						|
REL_EXCLUDES = [
 | 
						|
    "contrib/linux-kernel/test/include",
 | 
						|
]
 | 
						|
 | 
						|
def to_abs(d):
 | 
						|
    return os.path.normpath(os.path.join(ROOT, d)) + "/"
 | 
						|
 | 
						|
DIRS = [to_abs(d) for d in RELDIRS]
 | 
						|
EXCLUDES = [to_abs(d) for d in REL_EXCLUDES]
 | 
						|
 | 
						|
SUFFIXES = [
 | 
						|
    ".c",
 | 
						|
    ".h",
 | 
						|
    "Makefile",
 | 
						|
    ".mk",
 | 
						|
    ".py",
 | 
						|
    ".S",
 | 
						|
]
 | 
						|
 | 
						|
# License should certainly be in the first 10 KB.
 | 
						|
MAX_BYTES = 10000
 | 
						|
MAX_LINES = 50
 | 
						|
 | 
						|
LICENSE_LINES = [
 | 
						|
    "This source code is licensed under both the BSD-style license (found in the",
 | 
						|
    "LICENSE file in the root directory of this source tree) and the GPLv2 (found",
 | 
						|
    "in the COPYING file in the root directory of this source tree).",
 | 
						|
    "You may select, at your option, one of the above-listed licenses.",
 | 
						|
]
 | 
						|
 | 
						|
COPYRIGHT_EXCEPTIONS = {
 | 
						|
    # From zstdmt
 | 
						|
    "threading.c",
 | 
						|
    "threading.h",
 | 
						|
    # From divsufsort
 | 
						|
    "divsufsort.c",
 | 
						|
    "divsufsort.h",
 | 
						|
}
 | 
						|
 | 
						|
LICENSE_EXCEPTIONS = {
 | 
						|
    # From divsufsort
 | 
						|
    "divsufsort.c",
 | 
						|
    "divsufsort.h",
 | 
						|
    # License is slightly different because it references GitHub
 | 
						|
    "linux_zstd.h",
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
def valid_copyright(lines):
 | 
						|
    YEAR_REGEX = re.compile("\d\d\d\d|present")
 | 
						|
    for line in lines:
 | 
						|
        line = line.strip()
 | 
						|
        if "Copyright" not in line:
 | 
						|
            continue
 | 
						|
        if "present" in line:
 | 
						|
            return (False, f"Copyright line '{line}' contains 'present'!")
 | 
						|
        if "Meta Platforms, Inc" not in line:
 | 
						|
            return (False, f"Copyright line '{line}' does not contain 'Meta Platforms, Inc'")
 | 
						|
        year = YEAR_REGEX.search(line)
 | 
						|
        if year is not None:
 | 
						|
            return (False, f"Copyright line '{line}' contains {year.group(0)}; it should be yearless")
 | 
						|
        if " (c) " not in line:
 | 
						|
            return (False, f"Copyright line '{line}' does not contain ' (c) '!")
 | 
						|
        return (True, "")
 | 
						|
    return (False, "Copyright not found!")
 | 
						|
 | 
						|
 | 
						|
def valid_license(lines):
 | 
						|
    for b in range(len(lines)):
 | 
						|
        if LICENSE_LINES[0] not in lines[b]:
 | 
						|
            continue
 | 
						|
        for l in range(len(LICENSE_LINES)):
 | 
						|
            if LICENSE_LINES[l] not in lines[b + l]:
 | 
						|
                message = f"""Invalid license line found starting on line {b + l}!
 | 
						|
Expected: '{LICENSE_LINES[l]}'
 | 
						|
Actual: '{lines[b + l]}'"""
 | 
						|
                return (False, message)
 | 
						|
        return (True, "")
 | 
						|
    return (False, "License not found!")
 | 
						|
 | 
						|
 | 
						|
def valid_file(filename):
 | 
						|
    with open(filename, "r") as f:
 | 
						|
        lines = f.readlines(MAX_BYTES)
 | 
						|
    lines = lines[:min(len(lines), MAX_LINES)]
 | 
						|
 | 
						|
    ok = True
 | 
						|
    if os.path.basename(filename) not in COPYRIGHT_EXCEPTIONS:
 | 
						|
        c_ok, c_msg = valid_copyright(lines)
 | 
						|
        if not c_ok:
 | 
						|
            print(f"{filename}: {c_msg}", file=sys.stderr)
 | 
						|
            ok = False
 | 
						|
    if os.path.basename(filename) not in LICENSE_EXCEPTIONS:
 | 
						|
        l_ok, l_msg = valid_license(lines)
 | 
						|
        if not l_ok:
 | 
						|
            print(f"{filename}: {l_msg}", file=sys.stderr)
 | 
						|
            ok = False
 | 
						|
    return ok
 | 
						|
 | 
						|
 | 
						|
def exclude(filename):
 | 
						|
    for x in EXCLUDES:
 | 
						|
        if filename.startswith(x):
 | 
						|
            return True
 | 
						|
    return False
 | 
						|
 | 
						|
def main():
 | 
						|
    invalid_files = []
 | 
						|
    for directory in DIRS:
 | 
						|
        for suffix in SUFFIXES:
 | 
						|
            files = set(glob.glob(f"{directory}/**/*{suffix}", recursive=True))
 | 
						|
            for filename in files:
 | 
						|
                if exclude(filename):
 | 
						|
                    continue
 | 
						|
                if not valid_file(filename):
 | 
						|
                    invalid_files.append(filename)
 | 
						|
    if len(invalid_files) > 0:
 | 
						|
        print("Fail!", file=sys.stderr)
 | 
						|
        for f in invalid_files:
 | 
						|
            print(f)
 | 
						|
        return 1
 | 
						|
    else:
 | 
						|
        print("Pass!", file=sys.stderr)
 | 
						|
        return 0
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    sys.exit(main())
 |