librsvg oxidation chart
| import json | |
| import os | |
| import re | |
| import pandas | |
| import matplotlib.pyplot as plt | |
| import dateutil | |
| from subprocess import run, PIPE | |
| repo = "/home/jess/repo/librsvg" | |
| tmp_csv = "/tmp/burndown.csv" | |
| rx1 = re.compile("(\d+) insertions") | |
| rx2 = re.compile("(\d+) deletions") | |
| def inspect(info): | |
| proc = run(["git", "show", "-s", "--format=%ci", "HEAD"], stdout=PIPE) | |
| date = dateutil.parser.parse(proc.stdout) | |
| date = date.replace(tzinfo=None) | |
| proc = run(["git", "diff", "HEAD^", "HEAD", "--shortstat"], stdout=PIPE) | |
| m1 = rx1.search(proc.stdout.decode("utf8")) | |
| if m1: | |
| addd = int(m1.groups(1)[0]) | |
| else: | |
| addd = 0 | |
| m2 = rx2.search(proc.stdout.decode("utf8")) | |
| if m2: | |
| deld = int(m2.groups(1)[0]) | |
| else: | |
| deld = 0 | |
| proc = run(["tokei", "-o", "json", "-t", "Rust,C,C Header"], stdout=PIPE) | |
| out = json.loads(proc.stdout) | |
| del out["C"]["stats"] | |
| del out["CHeader"]["stats"] | |
| try: | |
| del out["Rust"]["stats"] | |
| except KeyError: | |
| # add the first non-rusty stats then reraise to catch in parent | |
| info.append((date, out["C"]["lines"], 0, out["CHeader"]["lines"], addd, deld)) | |
| raise | |
| info.append( | |
| ( | |
| date, | |
| out["C"]["lines"], | |
| out["Rust"]["lines"], | |
| out["CHeader"]["lines"], | |
| addd, | |
| deld, | |
| ) | |
| ) | |
| def postprocess(df): | |
| df.sort_index(inplace=True) | |
| df.to_csv(tmp_csv) | |
| ax = df[["C", "Rust", "CHeader"]].plot(title="librsvg burndown", drawstyle="steps") | |
| ax.set_ylabel("LOC") | |
| # df["Commit"] = 1 | |
| # df2 = df[["Added", "Deleted", "Commit"]].resample("D").sum().rolling("7D").mean() | |
| # df2.plot(ax=ax, ) | |
| plt.show() | |
| def new_run(): | |
| info = [] | |
| ct = 0 | |
| os.chdir(repo) | |
| proc = run(["git", "checkout", "master"]) | |
| while True: | |
| try: | |
| inspect(info) | |
| except KeyError: | |
| break | |
| ct += 1 | |
| print(ct) | |
| _proc = run(["git", "checkout", "HEAD^"], stderr=PIPE) | |
| assert _proc.returncode == 0 | |
| df = pandas.DataFrame.from_records( | |
| info, "Date", columns=["Date", "C", "Rust", "CHeader", "Added", "Deleted"] | |
| ) | |
| proc = run(["git", "checkout", "master"]) | |
| return df | |
| if __name__ == "__main__": | |
| try: | |
| # delete tmp_csv file to re-run everything | |
| df = pandas.read_csv(tmp_csv, index_col="Date", parse_dates=["Date"]) | |
| except: | |
| df = new_run() | |
| postprocess(df) |
This comment has been minimized.
This comment has been minimized.
|
Hi there - yes of course, it's all your hard work, do whatever you like with it. I feel a little bit like I've stolen some unearned credit! |
This comment has been minimized.
This comment has been minimized.
|
In theory, to run the script, all you need to do is |
This comment has been minimized.
This comment has been minimized.
federicomenaquintero
commented
Jan 11, 2019
|
Thanks! I'll try to get my env set up for running it in the future. |
This comment has been minimized.
This comment has been minimized.
jaccarmac
commented
Feb 2, 2019
|
May I cannibalize the code to generate a similar chart for Remacs? We like the chart over there and are working on tracking something similar for that project. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
federicomenaquintero commentedJan 10, 2019
Hi! I saw your /r/rust post with the oxidation chart. Thanks for putting it together; it is very nice! Would you let me paste that image in my blog? I'll try to set up my environment to be able to run your script in the future :)