def update(self, fname, basedir, miss):
self.total += 1
self.missing += miss if miss:
fname = './' + fname
bdir = os.path.dirname(fname) if bdir == basedir.rstrip('/'):
self.files.append(fname)
# Read the spdx data from the LICENSES directory def read_spdxdata(repo):
# The subdirectories of LICENSES in the kernel source # Note: exceptions needs to be parsed as last directory.
license_dirs = [ "preferred", "dual", "deprecated", "exceptions" ]
lictree = repo.head.commit.tree['LICENSES']
spdx = SPDXdata()
for d in license_dirs: for el in lictree[d].traverse(): ifnot os.path.isfile(el.path): continue
exception = None for l in open(el.path, encoding="utf-8").readlines(): if l.startswith('Valid-License-Identifier:'):
lid = l.split(':')[1].strip().upper() if lid in spdx.licenses: raise SPDXException(el, 'Duplicate License Identifier: %s' %lid) else:
spdx.licenses.append(lid)
def parse_lines(self, fd, maxlines, fname):
self.checked += 1
self.curline = 0
fail = 1 try: for line in fd:
line = line.decode(locale.getpreferredencoding(False), errors='ignore')
self.curline += 1 if self.curline > maxlines: break
self.lines_checked += 1 if line.find("SPDX-License-Identifier:") < 0: continue
expr = line.split(':')[1].strip() # Remove trailing comment closure if line.strip().endswith('*/'):
expr = expr.rstrip('*/').strip() # Remove trailing xml comment closure if line.strip().endswith('-->'):
expr = expr.rstrip('-->').strip() # Remove trailing Jinja2 comment closure if line.strip().endswith('#}'):
expr = expr.rstrip('#}').strip() # Special case for SH magic boot code files if line.startswith('LIST \"'):
expr = expr.rstrip('\"').strip() # Remove j2 comment closure if line.startswith('{#'):
expr = expr.rstrip('#}').strip()
self.parse(expr)
self.spdx_valid += 1 # # Should we check for more SPDX ids in the same file and # complain if there are any? #
fail = 0 break
except ParserException as pe: if pe.tok:
col = line.find(expr) + pe.tok.lexpos
tok = pe.tok.value
sys.stdout.write('%s: %d:%d %s: %s\n' %(fname, self.curline, col, pe.txt, tok)) else:
sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, pe.txt))
self.spdx_errors += 1
if fname == '-': return
base = os.path.dirname(fname) if self.dirdepth > 0:
parts = base.split('/')
i = 0
base = '.' while i < self.dirdepth and i < len(parts) and len(parts[i]):
base += '/' + parts[i]
i += 1 elif self.dirdepth == 0:
base = self.basedir else:
base = './' + base.rstrip('/')
base += '/'
di = self.spdx_dirs.get(base, dirinfo())
di.update(fname, base, fail)
self.spdx_dirs[base] = di
class pattern(object): def __init__(self, line):
self.pattern = line
self.match = self.match_file if line == '.*':
self.match = self.match_dot elif line.endswith('/'):
self.pattern = line[:-1]
self.match = self.match_dir elif line.startswith('/'):
self.pattern = line[1:]
self.match = self.match_fn
def match_dir(self, fpath): if self.match_fn(os.path.dirname(fpath)): returnTrue return fpath.startswith(self.pattern)
def exclude_file(fpath): for rule in exclude_rules: if rule.match(fpath): returnTrue returnFalse
def scan_git_tree(tree, basedir, dirdepth):
parser.set_dirinfo(basedir, dirdepth) for el in tree.traverse(): ifnot os.path.isfile(el.path): continue if exclude_file(el.path):
parser.excluded += 1 continue with open(el.path, 'rb') as fd:
parser.parse_lines(fd, args.maxlines, el.path)
def scan_git_subtree(tree, path, dirdepth): for p in path.strip('/').split('/'):
tree = tree[p]
scan_git_tree(tree, path.strip('/'), dirdepth)
def read_exclude_file(fname):
rules = [] ifnot fname: return rules with open(fname) as fd: for line in fd:
line = line.strip() if line.startswith('#'): continue ifnot len(line): continue
rules.append(pattern(line)) return rules
if __name__ == '__main__':
ap = ArgumentParser(description='SPDX expression checker')
ap.add_argument('path', nargs='*', help='Check path or file. If not given full git tree scan. For stdin use "-"')
ap.add_argument('-d', '--dirs', action='store_true',
help='Show [sub]directory statistics.')
ap.add_argument('-D', '--depth', type=int, default=-1,
help='Directory depth for -d statistics. Default: unlimited')
ap.add_argument('-e', '--exclude',
help='File containing file patterns to exclude. Default: scripts/spdxexclude')
ap.add_argument('-f', '--files', action='store_true',
help='Show files without SPDX.')
ap.add_argument('-m', '--maxlines', type=int, default=15,
help='Maximum number of lines to scan in a file. Default 15')
ap.add_argument('-v', '--verbose', action='store_true', help='Verbose statistics output')
args = ap.parse_args()
# Sanity check path arguments if'-'in args.path and len(args.path) > 1:
sys.stderr.write('stdin input "-" must be the only path argument\n')
sys.exit(1)
try: # Use git to get the valid license expressions
repo = git.Repo(os.getcwd()) assertnot repo.bare
# Initialize SPDX data
spdx = read_spdxdata(repo)
# Initialize the parser
parser = id_parser(spdx)
except SPDXException as se: if se.el:
sys.stderr.write('%s: %s\n' %(se.el.path, se.txt)) else:
sys.stderr.write('%s\n' %se.txt)
sys.exit(1)
except Exception as ex:
sys.stderr.write('FAIL: %s\n' %ex)
sys.stderr.write('%s\n' %traceback.format_exc())
sys.exit(1)
try: if len(args.path) and args.path[0] == '-':
stdin = os.fdopen(sys.stdin.fileno(), 'rb')
parser.parse_lines(stdin, args.maxlines, '-') else: if args.path: for p in args.path: if os.path.isfile(p):
parser.parse_lines(open(p, 'rb'), args.maxlines, p) elif os.path.isdir(p):
scan_git_subtree(repo.head.reference.commit.tree, p,
args.depth) else:
sys.stderr.write('path %s does not exist\n' %p)
sys.exit(1) else: # Full git tree scan
scan_git_tree(repo.head.commit.tree, '.', args.depth)
ndirs = len(parser.spdx_dirs)
dirsok = 0 if ndirs: for di in parser.spdx_dirs.values(): ifnot di.missing:
dirsok += 1
if ndirs and ndirs != dirsok and args.dirs: if args.verbose:
sys.stderr.write('\n')
sys.stderr.write('Incomplete directories: SPDX in Files\n') for f in sorted(parser.spdx_dirs.keys()):
di = parser.spdx_dirs[f] if di.missing:
valid = di.total - di.missing
pc = int(100 * valid / di.total)
sys.stderr.write(' %-80s: %5d of %5d %3d%%\n' %(f, valid, di.total, pc))
if ndirs and ndirs != dirsok and args.files: if args.verbose or args.dirs:
sys.stderr.write('\n')
sys.stderr.write('Files without SPDX:\n') for f in sorted(parser.spdx_dirs.keys()):
di = parser.spdx_dirs[f] for f in sorted(di.files):
sys.stderr.write(' %s\n' %f)
sys.exit(0)
except Exception as ex:
sys.stderr.write('FAIL: %s\n' %ex)
sys.stderr.write('%s\n' %traceback.format_exc())
sys.exit(1)
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.