#!/usr/bin/env python # coding: utf8 # ## Idempotently add copyright headers to source files. # # To check that all files have required headers: # $ copyright-headers check # # To add/update the copyright headers: # $ copyright-headers update # # To ignore files under a certain directory and below: # $ touch some/directory/.autocopyrightignore # $ git add some/directory/.autocopyrightignore # Originally from https://github.com/ghuntley/ghuntley/blob/trunk/third_party/copyright-headers/copyright-headers. # SPDX-License import os import re import string import subprocess import sys ######################### # File-type configuration # start: The start marker of the block. # line: The prefix for the notice text. # end: The end marker of the block. # skip: Optional prefix for lines to skip when adding header initially. filetypes = \ { 'hs' : { 'start' : '-' * 80 , 'line' : '--' , 'end' : '' , 'empty_line' : '', 'skip' : '#!' } , 'lhs' : { 'start' : '-' * 80 , 'line' : '--' , 'end' : '' , 'empty_line' : '' } , 'chs' : { 'start' : '-' * 80 , 'line' : '--' , 'end' : '' , 'empty_line' : '' } , 'js' : { 'start' : '' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'ts' : { 'start' : '' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'tsx' : { 'start' : '' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'java' : { 'start' : '' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'scala' : { 'start' : '' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'rst' : { 'start' : '' , 'line' : '..' , 'end' : '' , 'empty_line' : '' } , 'tex' : { 'start' : '%' * 80 , 'line' : '%' , 'end' : '' , 'empty_line' : '' } , 'py' : { 'start' : '#' * 80 , 'line' : '#' , 'end' : '' , 'empty_line' : '', 'skip' : '#!' } , 'proto' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'c' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'cpp' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'cc' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'h' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'hpp' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'hh' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'groovy' : { 'start' : '/*' , 'line' : '//' , 'end' : '' , 'empty_line' : '' } , 'sql' : { 'start' : '/*' , 'line' : '--' , 'end' : '' , 'empty_line' : '' } , 'sh' : { 'start' : '#' * 80 , 'line' : '#' , 'end' : '' , 'empty_line' : '', 'skip' : '#!' } , 'bats' : { 'start' : '#' * 80 , 'line' : '#' , 'end' : '' , 'empty_line' : '', 'skip' : '#!' } , 'html' : { 'start' : '' , 'skip' : ' [DIRECTORY]") print(" If DIRECTORY is provided, checks only in that directory") print(" Otherwise, checks in 'pkgs'.") print(" Note that the provided directory must be relative to the") print(" root of the git repository.") sys.exit(1) chdir_to_toplevel() with open('.copyrightheader', 'r') as f: LEGAL_NOTICES = list(map(lambda x: x.strip(), f.readlines())) if len(sys.argv) != 2 and len(sys.argv) != 3: usage() if sys.argv[1] == "update": check_only = False elif sys.argv[1] == "check": check_only = True else: usage() dir = None if len(sys.argv) > 2: dir = sys.argv[2] failed=False for file in list_files(dir): if not process_file(file, check_only): failed=True if failed and check_only: print("\nCopyright header check failed.\nPlease update copyright headers by running 'copyright-headers update'") sys.exit(failed)