convert-spdx-licenses.py 4.1 KB

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