File size: 3,890 Bytes
a8e4869
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""The command: run git log here, grade it, print the files most likely overwritten. Nothing leaves this machine."""
import argparse
import json
import subprocess
import sys
from datetime import datetime

from . import __version__
from .grade import grade, score_line

PREORDER = "https://overflow.games/memento/?ref=claudeplugin"
FIX = ("memento Team gives each file one owner at a time across machines: "
       "a session claims a path before it edits, and the next one waits.")


def git_log(repo, since):
    cmd = ["git", "-C", repo, "log", "--all", "--source", "--name-only",
           "--since=" + since, "--format=%H|%an|%aI|%S"]
    try:
        r = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except OSError as e:
        raise SystemExit("agent-overwrite-grader: git is not on the PATH (%s)" % e)
    if r.returncode:
        raise SystemExit("agent-overwrite-grader: git log failed in %s: %s"
                         % (repo, r.stderr.decode("utf-8", "replace").strip()))
    return r.stdout.decode("utf-8", "replace")


def when(ms):
    t = datetime.fromtimestamp(ms / 1000)
    return "%s %d %s" % (t.strftime("%b"), t.day, t.strftime("%H:%M"))


def who(c):
    return c["hash"][:7] + " " + c["author"] + (" on " + c["ref"] if c["ref"] else "")


def text(report, top):
    out = [score_line(report), "%d commits by %d sessions read, on this machine only." % (report["commits"], report["sessions"]), ""]
    for f in report["files"][:top]:
        p = f["pairs"][0]
        line = "  %d  %s" % (f["count"], f["file"])
        pair = "     %s, %s, then %d min later %s" % (who(p["a"]), when(p["a"]["when"]), p["minutes"], who(p["b"]))
        if f["count"] > 1:
            pair += " (%d such pairs)" % f["count"]
        out += [line, pair]
    n = len(report["files"])
    if n > top:
        out.append("And %d more %s." % (n - top, "file" if n - top == 1 else "files"))
    elif n == 0:
        out.append("Nothing collided in this history. The more agents run at once, the sooner it does.")
    out += ["", FIX, "Pre-order memento Team, 10 USD per agent a month: " + PREORDER]
    return "\n".join(out)


def main(argv=None):
    ap = argparse.ArgumentParser(
        prog="agent-overwrite-grader",
        description="List every file two sessions (two authors, or two branches) changed less than an hour apart: "
                    "the edits most likely to overwrite each other. It reads the local git log; nothing is sent anywhere.")
    ap.add_argument("repo", nargs="?", default=".", help="the repository to read (default: here)")
    ap.add_argument("--since", default="1 month ago", help="how far back to read (default: 1 month ago)")
    ap.add_argument("--log", metavar="FILE", help="grade a saved log instead ('-' for stdin), in the format of: "
                    "git log --all --source --name-only --format='%%H|%%an|%%aI|%%S'")
    ap.add_argument("--top", type=int, default=12, help="files to show (default: 12)")
    ap.add_argument("--json", action="store_true", help="print the report as JSON")
    ap.add_argument("--version", action="version", version="%(prog)s " + __version__)
    a = ap.parse_args(argv)
    try:
        if a.log == "-":
            log = sys.stdin.read()
        elif a.log:
            with open(a.log, encoding="utf-8", errors="replace") as f:
                log = f.read()
        else:
            log = git_log(a.repo, a.since)
    except SystemExit as e:
        print(e, file=sys.stderr)
        return 2
    report = grade(log)
    if not report["commits"] and a.log:
        print("agent-overwrite-grader: no commit in that text; save the output of the git log command in --help.",
              file=sys.stderr)
        return 1
    if a.json:
        report["preorder"] = PREORDER
        print(json.dumps(report, indent=2))
    else:
        print(text(report, a.top))
    return 0