|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 | """Update and sort the creators list of the zenodo record."""
|
3 |
| -import sys |
4 |
| -import shutil |
5 |
| -from pathlib import Path |
| 3 | +import git |
6 | 4 | import json
|
| 5 | +from subprocess import run, PIPE |
| 6 | +from pathlib import Path |
7 | 7 | from fuzzywuzzy import fuzz, process
|
8 |
| -import subprocess as sp |
9 | 8 |
|
10 |
| -# These names should go last |
11 |
| -CREATORS_LAST = ["Gorgolewski, Krzysztof J.", "Ghosh, Satrajit"] |
12 | 9 |
|
13 |
| -if __name__ == "__main__": |
14 |
| - contrib_file = Path("line-contributors.txt") |
15 |
| - lines = [] |
16 |
| - if contrib_file.exists(): |
17 |
| - print("WARNING: Reusing existing line-contributors.txt file.", file=sys.stderr) |
18 |
| - lines = contrib_file.read_text().splitlines() |
19 |
| - |
20 |
| - git_line_summary_path = shutil.which("git-line-summary") |
21 |
| - if not lines and git_line_summary_path: |
22 |
| - print("Running git-line-summary on nipype repo") |
23 |
| - lines = sp.check_output([git_line_summary_path]).decode().splitlines() |
24 |
| - contrib_file.write_text("\n".join(lines)) |
25 |
| - |
26 |
| - if not lines: |
27 |
| - raise RuntimeError( |
28 |
| - """\ |
29 |
| -Could not find line-contributors from git repository.%s""" |
30 |
| - % """ \ |
31 |
| -git-line-summary not found, please install git-extras. """ |
32 |
| - * (git_line_summary_path is None) |
33 |
| - ) |
| 10 | +def decommify(name): |
| 11 | + return " ".join(name.split(", ")[::-1]) |
34 | 12 |
|
35 |
| - data = [" ".join(line.strip().split()[1:-1]) for line in lines if "%" in line] |
36 | 13 |
|
37 |
| - # load zenodo from master |
38 |
| - zenodo_file = Path(".zenodo.json") |
39 |
| - zenodo = json.loads(zenodo_file.read_text()) |
40 |
| - zen_names = [ |
41 |
| - " ".join(val["name"].split(",")[::-1]).strip() for val in zenodo["creators"] |
42 |
| - ] |
43 |
| - total_names = len(zen_names) |
| 14 | +# These names should go last |
| 15 | +CREATORS_LAST = ["Krzysztof J. Gorgolewski", "Satrajit Ghosh"] |
44 | 16 |
|
45 |
| - name_matches = [] |
46 |
| - position = 1 |
47 |
| - for ele in data: |
48 |
| - matches = process.extract(ele, zen_names, scorer=fuzz.token_sort_ratio, limit=2) |
49 |
| - # matches is a list [('First match', % Match), ('Second match', % Match)] |
| 17 | +if __name__ == "__main__": |
| 18 | + git_root = Path(git.Repo(".", search_parent_directories=True).working_dir) |
| 19 | + zenodo_file = git_root / ".zenodo.json" |
| 20 | + |
| 21 | + zenodo = json.loads(zenodo_file.read_text()) if zenodo_file.exists() else {} |
| 22 | + |
| 23 | + creator_map = { |
| 24 | + decommify(creator["name"]): creator for creator in zenodo.get("creators", []) |
| 25 | + } |
| 26 | + |
| 27 | + shortlog = run(["git", "shortlog", "-ns"], stdout=PIPE) |
| 28 | + commit_counts = dict( |
| 29 | + line.split("\t", 1)[::-1] |
| 30 | + for line in shortlog.stdout.decode().split("\n") |
| 31 | + if line |
| 32 | + ) |
| 33 | + |
| 34 | + committers = [] |
| 35 | + |
| 36 | + # Stable sort: |
| 37 | + # Number of commits in descending order |
| 38 | + # Ties broken by alphabetical order of first name |
| 39 | + for committer, _ in sorted(commit_counts.items(), key=lambda x: (-int(x[1]), x[0])): |
| 40 | + matches = process.extract( |
| 41 | + committer, creator_map.keys(), scorer=fuzz.token_sort_ratio, limit=2 |
| 42 | + ) |
50 | 43 | if matches[0][1] <= 80:
|
51 | 44 | # skip unmatched names
|
52 |
| - print("No entry to sort:", ele) |
| 45 | + print("No entry to sort:", committer) |
53 | 46 | continue
|
| 47 | + committers.append(matches[0][0]) |
54 | 48 |
|
55 |
| - idx = zen_names.index(matches[0][0]) |
56 |
| - val = zenodo["creators"][idx] |
57 |
| - |
58 |
| - if val not in name_matches: |
59 |
| - if val["name"] not in CREATORS_LAST: |
60 |
| - val["position"] = position |
61 |
| - position += 1 |
62 |
| - else: |
63 |
| - val["position"] = total_names + CREATORS_LAST.index(val["name"]) |
64 |
| - name_matches.append(val) |
| 49 | + for last_author in CREATORS_LAST: |
| 50 | + if committers[-1] != last_author: |
| 51 | + committers.remove(last_author) |
| 52 | + committers.append(last_author) |
65 | 53 |
|
66 |
| - for missing in zenodo["creators"]: |
67 |
| - if "position" not in missing: |
68 |
| - missing["position"] = position |
69 |
| - position += 1 |
70 |
| - name_matches.append(missing) |
| 54 | + creators = [ |
| 55 | + creator_map.get(committer, {"name": committer}) for committer in committers |
| 56 | + ] |
71 | 57 |
|
72 |
| - zenodo["creators"] = sorted(name_matches, key=lambda k: k["position"]) |
73 |
| - # Remove position |
74 |
| - for creator in zenodo["creators"]: |
75 |
| - del creator["position"] |
| 58 | + zenodo["creators"] = creators |
76 | 59 |
|
77 |
| - zenodo_file.write_text("%s\n" % json.dumps(zenodo, indent=2, sort_keys=True)) |
| 60 | + zenodo_file.write_text("%s\n" % json.dumps(zenodo, indent=2)) |
0 commit comments