def pkg(parser, args): if not spack_is_git_repo(): tty.die("This spack is not a git clone. Can't use 'spack pkg'") action = {'add': pkg_add, 'diff': pkg_diff, 'list': pkg_list, 'removed': pkg_removed, 'added': pkg_added} action[args.pkg_command](args)
def pkg(parser, args): if not spack_is_git_repo(): tty.die("This spack is not a git clone. Can't use 'spack pkg'") action = { 'add': pkg_add, 'diff': pkg_diff, 'list': pkg_list, 'removed': pkg_removed, 'added': pkg_added } action[args.pkg_command](args)
def blame(parser, args): # make sure this is a git repo if not spack_is_git_repo(): tty.die("This spack is not a git clone. Can't use 'spack blame'") git = which('git', required=True) # Get name of file to blame blame_file = None if os.path.isfile(args.package_name): path = os.path.realpath(args.package_name) if path.startswith(spack.paths.prefix): blame_file = path if not blame_file: pkg = spack.repo.get(args.package_name) blame_file = pkg.module.__file__.rstrip('c') # .pyc -> .py # get git blame for the package with working_dir(spack.paths.prefix): if args.view == 'git': git('blame', blame_file) return else: output = git('blame', '--line-porcelain', blame_file, output=str) lines = output.split('\n') # Histogram authors counts = {} emails = {} last_mod = {} total_lines = 0 for line in lines: match = re.match(r'^author (.*)', line) if match: author = match.group(1) match = re.match(r'^author-mail (.*)', line) if match: email = match.group(1) match = re.match(r'^author-time (.*)', line) if match: mod = int(match.group(1)) last_mod[author] = max(last_mod.setdefault(author, 0), mod) # ignore comments if re.match(r'^\t[^#]', line): counts[author] = counts.setdefault(author, 0) + 1 emails.setdefault(author, email) total_lines += 1 if args.view == 'time': rows = sorted( counts.items(), key=lambda t: last_mod[t[0]], reverse=True) else: # args.view == 'percent' rows = sorted(counts.items(), key=lambda t: t[1], reverse=True) # Print a nice table with authors and emails table = [['LAST_COMMIT', 'LINES', '%', 'AUTHOR', 'EMAIL']] for author, nlines in rows: table += [[ pretty_date(last_mod[author]), nlines, round(nlines / float(total_lines) * 100, 1), author, emails[author]]] table += [[''] * 5] table += [[pretty_date(max(last_mod.values())), total_lines, '100.0'] + [''] * 3] colify_table(table)
def git_case_consistency_check(path): """Re-sync case of files in a directory with git. On case-insensitive but case-preserving filesystems like Mac OS X, Git doesn't properly rename files that only had their case changed. This checks files in a directory against git and does a case-restoring rename (actually two renames, e.g.:: name -> tmp -> NAME We use this in Spack to ensure package directories are named correctly. TODO: this check can probably be removed once package names have been TODO: lowercase for a long while. """ # Don't bother fixing case if Spack isn't in a git repository if not spack_is_git_repo(): return git = which('git', required=False) if not git: return with working_dir(path): try: git_filenames = git('ls-tree', '--name-only', 'HEAD', output=str) git_filenames = set(re.split(r'\s+', git_filenames.strip())) except ProcessError: return # Ignore errors calling git lower_to_mixed = {} for fn in git_filenames: lower = fn.lower() mixed = lower_to_mixed.setdefault(lower, []) mixed.append(fn) # Iterate through all actual files and make sure their names are # the same as corresponding names in git actual_filenames = os.listdir('.') for actual in actual_filenames: lower = actual.lower() # not tracked by git if lower not in lower_to_mixed: continue # Don't know what to do with multiple matches if len(lower_to_mixed[lower]) != 1: continue # Skip if case is already correct git_name = lower_to_mixed[lower][0] if git_name == actual: continue # restore case with two renames tmp_name = actual + '.spack.tmp' os.rename(actual, tmp_name) os.rename(tmp_name, git_name)
def blame(parser, args): # make sure this is a git repo if not spack_is_git_repo(): tty.die("This spack is not a git clone. Can't use 'spack blame'") git = which('git', required=True) # Get name of file to blame blame_file = None if os.path.isfile(args.package_or_file): path = os.path.realpath(args.package_or_file) if path.startswith(spack.paths.prefix): blame_file = path if not blame_file: pkg = spack.repo.get(args.package_or_file) blame_file = pkg.module.__file__.rstrip('c') # .pyc -> .py # get git blame for the package with working_dir(spack.paths.prefix): if args.view == 'git': git('blame', blame_file) return else: output = git('blame', '--line-porcelain', blame_file, output=str) lines = output.split('\n') # Histogram authors counts = {} emails = {} last_mod = {} total_lines = 0 for line in lines: match = re.match(r'^author (.*)', line) if match: author = match.group(1) match = re.match(r'^author-mail (.*)', line) if match: email = match.group(1) match = re.match(r'^author-time (.*)', line) if match: mod = int(match.group(1)) last_mod[author] = max(last_mod.setdefault(author, 0), mod) # ignore comments if re.match(r'^\t[^#]', line): counts[author] = counts.setdefault(author, 0) + 1 emails.setdefault(author, email) total_lines += 1 if args.view == 'time': rows = sorted(counts.items(), key=lambda t: last_mod[t[0]], reverse=True) else: # args.view == 'percent' rows = sorted(counts.items(), key=lambda t: t[1], reverse=True) # Print a nice table with authors and emails table = [['LAST_COMMIT', 'LINES', '%', 'AUTHOR', 'EMAIL']] for author, nlines in rows: table += [[ pretty_date(last_mod[author]), nlines, round(nlines / float(total_lines) * 100, 1), author, emails[author] ]] table += [[''] * 5] table += [[pretty_date(max(last_mod.values())), total_lines, '100.0'] + [''] * 3] colify_table(table)
def blame(parser, args): # make sure this is a git repo if not spack_is_git_repo(): tty.die("This spack is not a git clone. Can't use 'spack blame'") git = which('git', required=True) # Get name of file to blame blame_file = None if os.path.isfile(args.package_or_file): path = os.path.realpath(args.package_or_file) if path.startswith(spack.paths.prefix): blame_file = path if not blame_file: pkg = spack.repo.get(args.package_or_file) blame_file = pkg.module.__file__.rstrip('c') # .pyc -> .py # get git blame for the package with working_dir(spack.paths.prefix): if args.view == 'git': git('blame', blame_file) return else: output = git('blame', '--line-porcelain', blame_file, output=str) lines = output.split('\n') # Histogram authors counts = {} emails = {} last_mod = {} total_lines = 0 for line in lines: match = re.match(r'^author (.*)', line) if match: author = match.group(1) match = re.match(r'^author-mail (.*)', line) if match: email = match.group(1) match = re.match(r'^author-time (.*)', line) if match: mod = int(match.group(1)) last_mod[author] = max(last_mod.setdefault(author, 0), mod) # ignore comments if re.match(r'^\t[^#]', line): counts[author] = counts.setdefault(author, 0) + 1 emails.setdefault(author, email) total_lines += 1 if args.view == 'time': rows = sorted(counts.items(), key=lambda t: last_mod[t[0]], reverse=True) else: # args.view == 'percent' rows = sorted(counts.items(), key=lambda t: t[1], reverse=True) # Dump as json if args.json: dump_json(rows, last_mod, total_lines, emails) # Print a nice table with authors and emails else: print_table(rows, last_mod, total_lines, emails)