From b956f428a6e07e76061f3b40c5f35fb2a9807185 Mon Sep 17 00:00:00 2001 From: Alex Palaistras Date: Wed, 28 Dec 2016 21:13:49 +0000 Subject: [PATCH] Add `git tag` support, labels on sidebar for tags and branch names --- grawkit | 148 +++++++++++++++++++++++++++----------- tests/01-initial.svg | 28 ++++++-- tests/02-master.svg | 28 ++++++-- tests/03-branch.svg | 34 +++++++-- tests/04-merge.svg | 34 +++++++-- tests/05-multi-branch.svg | 50 ++++++++++--- 6 files changed, 248 insertions(+), 74 deletions(-) diff --git a/grawkit b/grawkit index 499e7bc..ee84deb 100755 --- a/grawkit +++ b/grawkit @@ -21,16 +21,15 @@ function addbranch(name) { branches[len["branches"],"name"] = name branches[len["branches"],"refs"] = "" branches[len["branches"],"merges"] = state["branch"] "|" state["HEAD"] + branches[len["branches"],"tags"] = "" len["branches"] += 1 } -# > Function `addcommit` adds a new commit, with a specific type and message, to -# > the internal list of commits to render. -function addcommit(type, message) { +# > Function `addcommit` adds a new commit, with a specific message, to the +# > internal list of commits to render. +function addcommit(message) { # Add commit information. - commits[len["commits"],"branch"] = state["branch"] - commits[len["commits"],"type"] = type commits[len["commits"],"message"] = msg # Update commit references. @@ -46,7 +45,7 @@ function addcommit(type, message) { # > Function `branch` renders pre-defined branch under a specific name to its # > SVG representation. -function branch(idx, _, buf, tmp, refs, i, bspc, cspc) { +function branch(idx, _, buf, tmp, refs, tags, t, i, hspc, vspc) { # Do not render branch with no commits. if (branches[idx,"refs"] == "") { return @@ -54,32 +53,64 @@ function branch(idx, _, buf, tmp, refs, i, bspc, cspc) { # Get commit refs. split(branches[idx,"refs"], refs, ",") - bspc = idx * style["branch/spacing"] + hspc = idx * style["branch/spacing"] # Print branch root element. buf = sprintf(svg["g"], "branch-" branches[idx,"name"]) # Add path for branch. - tmp = "M" bspc "," refs[1] * style["commit/spacing"] - tmp = tmp " L" bspc "," refs[length(refs)] * style["commit/spacing"] + tmp = "M" hspc "," refs[1] * style["commit/spacing"] + tmp = tmp " L" hspc "," refs[length(refs)] * style["commit/spacing"] # Print path. buf = buf "\n\t" sprintf(svg["path"], tmp) # Add commits on path. for (i in refs) { - cspc = refs[i] * style["commit/spacing"] + vspc = refs[i] * style["commit/spacing"] - tmp = sprintf(svg["circle"], bspc, cspc, style["commit/radius"]) + tmp = sprintf(svg["circle"], hspc, vspc, style["commit/radius"]) buf = buf "\n\t" tmp } - buf = buf "\n" svg["/g"] + # Add branch tags as labels. + split(branches[idx,"tags"], tags, ",") + for (i in tags) { + split(tags[i], t, "|") + buf = buf label(t[1], t[2], t[3]) + } + + # Add branch name as label on last commit. + buf = buf label(refs[length(refs)], "branch", branches[idx,"name"]) + + return buf "\n" svg["/g"] +} + +# > Function `label` adds a sidebar label at commit index, with a specific class +# > and label name. Multiple labels for the same index will be placed side-by-side. +function label(idx, class, name, _, buf, w, h, hspc, vspc) { + # Calculate width and height for label rectangle. + w = (style["label/spacing"] * length(name)) + style["label/spacing"] + h = style["label/spacing"] * 2.5 + + # Calculate label offsets. + hspc = (len["branches"] * style["branch/spacing"]) + __label_offset[idx] + vspc = idx * style["commit/spacing"] + + # Store width of labels in relation to their commit index. + __label_offset[idx] = w + style["label/spacing"] + + # Draw label elements. + buf = buf "\n\t" sprintf(svg["gg"], "label-" class, hspc, vspc) + buf = buf "\n\t\t" sprintf(svg["rect"], 0, (h / 2) * -1, w, h, style["label/round"]) + buf = buf "\n\t\t" sprintf(svg["text"], style["label/spacing"], style["label/spacing"] / 2, name) + buf = buf "\n\t" svg["/g"] + return buf } # > Function `merge` renders merge paths for a branch pointed to by `idx`. -function merge(idx, _, buf, tmp, refs, fields, m, i, bspc) { +function merge(idx, _, buf, tmp, refs, fields, m, i, hspc) { # Do not render merge paths for branch with no commits. if (branches[idx,"merges"] == "") { return @@ -87,7 +118,7 @@ function merge(idx, _, buf, tmp, refs, fields, m, i, bspc) { # Get commit refs. split(branches[idx,"refs"], refs, ",") - bspc = idx * style["branch/spacing"] + hspc = idx * style["branch/spacing"] # Print branch root element. buf = "\n\t" sprintf(svg["g"], "branch-" branches[idx,"name"]) @@ -101,16 +132,15 @@ function merge(idx, _, buf, tmp, refs, fields, m, i, bspc) { tmp = "M" m[1] * style["branch/spacing"] "," m[2] * style["commit/spacing"] # Add Bezier curve leading to current branch starting point. - tmp = tmp " C" bspc "," m[2] * style["commit/spacing"] - tmp = tmp " " bspc "," m[2] * style["commit/spacing"] - tmp = tmp " " bspc "," refs[1] * style["commit/spacing"] + tmp = tmp " C" hspc "," m[2] * style["commit/spacing"] + tmp = tmp " " hspc "," m[2] * style["commit/spacing"] + tmp = tmp " " hspc "," refs[1] * style["commit/spacing"] # Draw the path. buf = buf "\n\t\t" sprintf(svg["path"], tmp) } - buf = buf "\n\t" svg["/g"] - return buf + return buf "\n\t" svg["/g"] } # Global Declarations @@ -120,14 +150,15 @@ function merge(idx, _, buf, tmp, refs, fields, m, i, bspc) { BEGIN { # Errors. - error["branch/no-name"] = "Empty name for `git branch`, line %d\n" - error["branch/duplicate"] = "Unable to create duplicate branch '%s', line %d\n" + error["branch/no-name"] = "Empty name for `git branch`, line %d\n" + error["branch/duplicate"] = "Unable to create duplicate branch '%s', line %d\n" error["checkout/no-branch"] = "No branch with name '%s', line %d\n" - error["checkout/no-name"] = "Empty name for `git checkout`, line %d\n" - error["merge/no-name"] = "Empty name for `git merge`, line %d\n" + error["checkout/no-name"] = "Empty name for `git checkout`, line %d\n" + error["merge/no-name"] = "Empty name for `git merge`, line %d\n" + error["label/no-name"] = "Empty name for `git tag`, line %d\n" - # Rule matching. + # rule matching. rule["commit"] = "^git commit" rule["commit/message"] = "(--message|-m)[ ]+['|\"]([^'\"]+)['|\"]" @@ -140,6 +171,9 @@ BEGIN { rule["merge"] = "^git merge" rule["merge/name"] = rule["merge"] "[ ]*([^ ]+)" + rule["tag"] = "^git tag" + rule["label/name"] = rule["tag"] "[ ]*([^ ]+)" + # Style definitions. style["branch/spacing"] = "50" style["branch/fill"] = "none" @@ -150,27 +184,34 @@ BEGIN { style["commit/stroke-width"] = style["branch/stroke-width"] / 2 style["commit/radius"] = style["commit/stroke-width"] * 1.5 + style["label/spacing"] = "10" + style["label/round"] = "3" + style["label/fill"] = "#333" + style["label/text"] = "#fff" + # Color scheme, based on `base16-solarized-dark` style["pallete"] = "#002b36,#268bd2,#859900,#cb4b16,#2aa198,#dc322f,#d33682,#6c71c4,#b58900" # Static SVG templates. - svg["svg"] = "" + svg["svg"] = "" svg["/svg"] = "" svg["g"] = "" + svg["gg"] = "" svg["/g"] = "" svg["path"] = "" svg["circle"] = "" + svg["rect"] = "" + svg["text"] = "%s" # Branch definitions. branches[0,"name"] = "master" branches[0,"refs"] = 0 branches[0,"merges"] = "" + branches[0,"tags"] = "" len["branches"] = 1 # Commit definitions. - commits[0,"branch"] = "master" commits[0,"message"] = "Initial commit" - commits[0,"type"] = "commit" len["commits"] = 1 # Tracks the state across calls. @@ -191,7 +232,7 @@ $0 ~ rule["commit"] { match($0, rule["commit/message"], m) # Add new commit. - addcommit("commit", (2 in m) ? m[2] : "Empty message") + addcommit((2 in m) ? m[2] : "Empty message") next } @@ -269,13 +310,32 @@ $0 ~ rule["merge"] { } # Add a merge commit to current branch. - addcommit("merge", "Merge commit") + addcommit("Merge commit") # Add merge reference to target branch. if (branches[i,"merges"] == "") { branches[i,"merges"] = state["branch"] "|" state["HEAD"] } else { - branches[i,"merges"] = branches[i,"merges"] "," state["branch"] "|" state["HEAD"] + branches[i,"merges"] = branches[i,"merges"] "," state["branch"] "|" state["HEAD"] + } + + next +} + +# > Match `git tag` declarations. +$0 ~ rule["tag"] { + # Get tag name and throw error if one is not set. + match($0, rule["label/name"], n) + if (n[1] == "") { + printf error["label/no-name"], FNR | "cat >&2" + exit 1 + } + + # Add tag reference to target branch. + if (branches[state["branch"],"tags"] == "") { + branches[state["branch"],"tags"] = state["HEAD"] "|tag|" n[1] + } else { + branches[state["branch"],"tags"] = branches[state["branch"],"tags"] "," state["HEAD"] "|tag|" n[1] } next @@ -291,28 +351,36 @@ END { buf = "" split(style["pallete"], pallete, ",") - xy = style["branch/stroke-width"] * -1 - w = (style["branch/spacing"] * (len["branches"] - 1)) + (style["branch/stroke-width"] * 2) - h = (style["commit/spacing"] * (len["commits"] - 1)) + (style["commit/stroke-width"] * 4) - # Print SVG header. - printf svg["svg"], xy, xy, w, h + printf svg["svg"], style["branch/stroke-width"], style["branch/stroke-width"] printf "\n" # Print inline style definitions. print "" diff --git a/tests/01-initial.svg b/tests/01-initial.svg index a979664..bfb3d01 100644 --- a/tests/01-initial.svg +++ b/tests/01-initial.svg @@ -4,20 +4,36 @@ --> - + + + + master + diff --git a/tests/02-master.svg b/tests/02-master.svg index 88e9241..1def913 100644 --- a/tests/02-master.svg +++ b/tests/02-master.svg @@ -7,22 +7,38 @@ git commit --> - + + + + master + diff --git a/tests/03-branch.svg b/tests/03-branch.svg index b853090..b8c4eb2 100644 --- a/tests/03-branch.svg +++ b/tests/03-branch.svg @@ -18,18 +18,30 @@ git commit --> - + @@ -40,6 +52,10 @@ git commit + + + test-stuff + @@ -47,5 +63,9 @@ git commit + + + master + diff --git a/tests/04-merge.svg b/tests/04-merge.svg index 9043499..a53f113 100644 --- a/tests/04-merge.svg +++ b/tests/04-merge.svg @@ -18,18 +18,30 @@ git merge test-merging --> - + @@ -40,6 +52,10 @@ git merge test-merging + + + test-merging + @@ -48,5 +64,9 @@ git merge test-merging + + + master + diff --git a/tests/05-multi-branch.svg b/tests/05-multi-branch.svg index b59c281..400a961 100644 --- a/tests/05-multi-branch.svg +++ b/tests/05-multi-branch.svg @@ -8,6 +8,7 @@ git branch test-first git branch test-second git commit -m "Still on master" +git tag v.1.0.0 git checkout test-first git commit @@ -15,25 +16,38 @@ git commit git checkout test-second git commit git merge test-first +git tag v.2.0.0-rc1 git checkout master git merge test-second --> - + @@ -49,10 +63,22 @@ git merge test-second + + + v.2.0.0-rc1 + + + + test-second + + + + test-first + @@ -60,5 +86,13 @@ git merge test-second + + + v.1.0.0 + + + + master +