1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Conversion script to change LICENSE entries to SPDX identifiers 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Copyright (C) 2021-2022 Richard Purdie 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunimport re 11*4882a593Smuzhiyunimport os 12*4882a593Smuzhiyunimport sys 13*4882a593Smuzhiyunimport tempfile 14*4882a593Smuzhiyunimport shutil 15*4882a593Smuzhiyunimport mimetypes 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunif len(sys.argv) < 2: 18*4882a593Smuzhiyun print("Please specify a directory to run the conversion script against.") 19*4882a593Smuzhiyun sys.exit(1) 20*4882a593Smuzhiyun 21*4882a593Smuzhiyunlicense_map = { 22*4882a593Smuzhiyun"AGPL-3" : "AGPL-3.0-only", 23*4882a593Smuzhiyun"AGPL-3+" : "AGPL-3.0-or-later", 24*4882a593Smuzhiyun"AGPLv3" : "AGPL-3.0-only", 25*4882a593Smuzhiyun"AGPLv3+" : "AGPL-3.0-or-later", 26*4882a593Smuzhiyun"AGPLv3.0" : "AGPL-3.0-only", 27*4882a593Smuzhiyun"AGPLv3.0+" : "AGPL-3.0-or-later", 28*4882a593Smuzhiyun"AGPL-3.0" : "AGPL-3.0-only", 29*4882a593Smuzhiyun"AGPL-3.0+" : "AGPL-3.0-or-later", 30*4882a593Smuzhiyun"BSD-0-Clause" : "0BSD", 31*4882a593Smuzhiyun"GPL-1" : "GPL-1.0-only", 32*4882a593Smuzhiyun"GPL-1+" : "GPL-1.0-or-later", 33*4882a593Smuzhiyun"GPLv1" : "GPL-1.0-only", 34*4882a593Smuzhiyun"GPLv1+" : "GPL-1.0-or-later", 35*4882a593Smuzhiyun"GPLv1.0" : "GPL-1.0-only", 36*4882a593Smuzhiyun"GPLv1.0+" : "GPL-1.0-or-later", 37*4882a593Smuzhiyun"GPL-1.0" : "GPL-1.0-only", 38*4882a593Smuzhiyun"GPL-1.0+" : "GPL-1.0-or-later", 39*4882a593Smuzhiyun"GPL-2" : "GPL-2.0-only", 40*4882a593Smuzhiyun"GPL-2+" : "GPL-2.0-or-later", 41*4882a593Smuzhiyun"GPLv2" : "GPL-2.0-only", 42*4882a593Smuzhiyun"GPLv2+" : "GPL-2.0-or-later", 43*4882a593Smuzhiyun"GPLv2.0" : "GPL-2.0-only", 44*4882a593Smuzhiyun"GPLv2.0+" : "GPL-2.0-or-later", 45*4882a593Smuzhiyun"GPL-2.0" : "GPL-2.0-only", 46*4882a593Smuzhiyun"GPL-2.0+" : "GPL-2.0-or-later", 47*4882a593Smuzhiyun"GPL-3" : "GPL-3.0-only", 48*4882a593Smuzhiyun"GPL-3+" : "GPL-3.0-or-later", 49*4882a593Smuzhiyun"GPLv3" : "GPL-3.0-only", 50*4882a593Smuzhiyun"GPLv3+" : "GPL-3.0-or-later", 51*4882a593Smuzhiyun"GPLv3.0" : "GPL-3.0-only", 52*4882a593Smuzhiyun"GPLv3.0+" : "GPL-3.0-or-later", 53*4882a593Smuzhiyun"GPL-3.0" : "GPL-3.0-only", 54*4882a593Smuzhiyun"GPL-3.0+" : "GPL-3.0-or-later", 55*4882a593Smuzhiyun"LGPLv2" : "LGPL-2.0-only", 56*4882a593Smuzhiyun"LGPLv2+" : "LGPL-2.0-or-later", 57*4882a593Smuzhiyun"LGPLv2.0" : "LGPL-2.0-only", 58*4882a593Smuzhiyun"LGPLv2.0+" : "LGPL-2.0-or-later", 59*4882a593Smuzhiyun"LGPL-2.0" : "LGPL-2.0-only", 60*4882a593Smuzhiyun"LGPL-2.0+" : "LGPL-2.0-or-later", 61*4882a593Smuzhiyun"LGPL2.1" : "LGPL-2.1-only", 62*4882a593Smuzhiyun"LGPL2.1+" : "LGPL-2.1-or-later", 63*4882a593Smuzhiyun"LGPLv2.1" : "LGPL-2.1-only", 64*4882a593Smuzhiyun"LGPLv2.1+" : "LGPL-2.1-or-later", 65*4882a593Smuzhiyun"LGPL-2.1" : "LGPL-2.1-only", 66*4882a593Smuzhiyun"LGPL-2.1+" : "LGPL-2.1-or-later", 67*4882a593Smuzhiyun"LGPLv3" : "LGPL-3.0-only", 68*4882a593Smuzhiyun"LGPLv3+" : "LGPL-3.0-or-later", 69*4882a593Smuzhiyun"LGPL-3.0" : "LGPL-3.0-only", 70*4882a593Smuzhiyun"LGPL-3.0+" : "LGPL-3.0-or-later", 71*4882a593Smuzhiyun"MPL-1" : "MPL-1.0", 72*4882a593Smuzhiyun"MPLv1" : "MPL-1.0", 73*4882a593Smuzhiyun"MPLv1.1" : "MPL-1.1", 74*4882a593Smuzhiyun"MPLv2" : "MPL-2.0", 75*4882a593Smuzhiyun"MIT-X" : "MIT", 76*4882a593Smuzhiyun"MIT-style" : "MIT", 77*4882a593Smuzhiyun"openssl" : "OpenSSL", 78*4882a593Smuzhiyun"PSF" : "PSF-2.0", 79*4882a593Smuzhiyun"PSFv2" : "PSF-2.0", 80*4882a593Smuzhiyun"Python-2" : "Python-2.0", 81*4882a593Smuzhiyun"Apachev2" : "Apache-2.0", 82*4882a593Smuzhiyun"Apache-2" : "Apache-2.0", 83*4882a593Smuzhiyun"Artisticv1" : "Artistic-1.0", 84*4882a593Smuzhiyun"Artistic-1" : "Artistic-1.0", 85*4882a593Smuzhiyun"AFL-2" : "AFL-2.0", 86*4882a593Smuzhiyun"AFL-1" : "AFL-1.2", 87*4882a593Smuzhiyun"AFLv2" : "AFL-2.0", 88*4882a593Smuzhiyun"AFLv1" : "AFL-1.2", 89*4882a593Smuzhiyun"CDDLv1" : "CDDL-1.0", 90*4882a593Smuzhiyun"CDDL-1" : "CDDL-1.0", 91*4882a593Smuzhiyun"EPLv1.0" : "EPL-1.0", 92*4882a593Smuzhiyun"FreeType" : "FTL", 93*4882a593Smuzhiyun"Nauman" : "Naumen", 94*4882a593Smuzhiyun"tcl" : "TCL", 95*4882a593Smuzhiyun"vim" : "Vim", 96*4882a593Smuzhiyun"SGIv1" : "SGI-1", 97*4882a593Smuzhiyun} 98*4882a593Smuzhiyun 99*4882a593Smuzhiyundef processfile(fn): 100*4882a593Smuzhiyun print("processing file '%s'" % fn) 101*4882a593Smuzhiyun try: 102*4882a593Smuzhiyun fh, abs_path = tempfile.mkstemp() 103*4882a593Smuzhiyun modified = False 104*4882a593Smuzhiyun with os.fdopen(fh, 'w') as new_file: 105*4882a593Smuzhiyun with open(fn, "r") as old_file: 106*4882a593Smuzhiyun for line in old_file: 107*4882a593Smuzhiyun if not line.startswith("LICENSE"): 108*4882a593Smuzhiyun new_file.write(line) 109*4882a593Smuzhiyun continue 110*4882a593Smuzhiyun orig = line 111*4882a593Smuzhiyun for license in sorted(license_map, key=len, reverse=True): 112*4882a593Smuzhiyun for ending in ['"', "'", " ", ")"]: 113*4882a593Smuzhiyun line = line.replace(license + ending, license_map[license] + ending) 114*4882a593Smuzhiyun if orig != line: 115*4882a593Smuzhiyun modified = True 116*4882a593Smuzhiyun new_file.write(line) 117*4882a593Smuzhiyun new_file.close() 118*4882a593Smuzhiyun if modified: 119*4882a593Smuzhiyun shutil.copymode(fn, abs_path) 120*4882a593Smuzhiyun os.remove(fn) 121*4882a593Smuzhiyun shutil.move(abs_path, fn) 122*4882a593Smuzhiyun except UnicodeDecodeError: 123*4882a593Smuzhiyun pass 124*4882a593Smuzhiyun 125*4882a593Smuzhiyunourname = os.path.basename(sys.argv[0]) 126*4882a593Smuzhiyunourversion = "0.01" 127*4882a593Smuzhiyun 128*4882a593Smuzhiyunif os.path.isfile(sys.argv[1]): 129*4882a593Smuzhiyun processfile(sys.argv[1]) 130*4882a593Smuzhiyun sys.exit(0) 131*4882a593Smuzhiyun 132*4882a593Smuzhiyunfor targetdir in sys.argv[1:]: 133*4882a593Smuzhiyun print("processing directory '%s'" % targetdir) 134*4882a593Smuzhiyun for root, dirs, files in os.walk(targetdir): 135*4882a593Smuzhiyun for name in files: 136*4882a593Smuzhiyun if name == ourname: 137*4882a593Smuzhiyun continue 138*4882a593Smuzhiyun fn = os.path.join(root, name) 139*4882a593Smuzhiyun if os.path.islink(fn): 140*4882a593Smuzhiyun continue 141*4882a593Smuzhiyun if "/.git/" in fn or fn.endswith(".html") or fn.endswith(".patch") or fn.endswith(".m4") or fn.endswith(".diff") or fn.endswith(".orig"): 142*4882a593Smuzhiyun continue 143*4882a593Smuzhiyun processfile(fn) 144*4882a593Smuzhiyun 145*4882a593Smuzhiyunprint("All files processed with version %s" % ourversion) 146