Add `git tag` support, labels on sidebar for tags and branch names

This commit is contained in:
Alex Palaistras 2016-12-28 21:13:49 +00:00
parent b1291b4adf
commit b956f428a6
6 changed files with 248 additions and 74 deletions

148
grawkit
View File

@ -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 xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%d %d %d %d\">"
svg["svg"] = "<svg xmlns=\"http://www.w3.org/2000/svg\" transform=\"translate(%d,%d)\">"
svg["/svg"] = "</svg>"
svg["g"] = "<g class=\"%s\">"
svg["gg"] = "<g class=\"%s\" transform=\"translate(%d,%d)\">"
svg["/g"] = "</g>"
svg["path"] = "<path class=\"branch\" d=\"%s\" />"
svg["circle"] = "<circle class=\"commit\" cx=\"%d\" cy=\"%d\" r=\"%s\" />"
svg["rect"] = "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%d\" class=\"label-rect\" />"
svg["text"] = "<text x=\"%d\" y=\"%d\" class=\"label-text\">%s</text>"
# 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 "<style type=\"text/css\"><![CDATA["
print ".branch {"
print " fill: " style["branch/fill"] ";"
print " stroke-width: " style["branch/stroke-width"] ";"
print "\tfill: " style["branch/fill"] ";"
print "\tstroke-width: " style["branch/stroke-width"] ";"
print "}"
print ".commit {"
print " fill: " style["commit/fill"] ";"
print " stroke-width: " style["commit/stroke-width"] ";"
print "\tfill: " style["commit/fill"] ";"
print "\tstroke-width: " style["commit/stroke-width"] ";"
print "}"
print ".label-tag {"
print "\tfill: " style["label/fill"] ";"
print "}"
print ".label-rect {"
print "\tstroke: none;"
print "}"
print ".label-text {"
print "\tfont-family: Inconsolata, Consolas, monospace;"
print "\tfont-size: 1.5em;"
print "\tfill: " style["label/text"] ";"
print "\tstroke: none;"
print "}"
# Print color scheme definitions for branches.
for (i = 0; i < len["branches"]; i++) {
print ".branch-" branches[i,"name"] " {stroke: " pallete[i + 1] "}"
print ".branch-" branches[i,"name"] " {stroke: " pallete[i + 1] "; fill: " pallete[i + 1] "}"
}
print "]]></style>"

View File

@ -4,20 +4,36 @@
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 20 20">
<svg xmlns="http://www.w3.org/2000/svg" transform="translate(10,10)">
<style type="text/css"><![CDATA[
.branch {
fill: none;
stroke-width: 10;
fill: none;
stroke-width: 10;
}
.commit {
fill: #fff;
stroke-width: 5;
fill: #fff;
stroke-width: 5;
}
.branch-master {stroke: #002b36}
.label-tag {
fill: #333;
}
.label-rect {
stroke: none;
}
.label-text {
font-family: Inconsolata, Consolas, monospace;
font-size: 1.5em;
fill: #fff;
stroke: none;
}
.branch-master {stroke: #002b36; fill: #002b36}
]]></style>
<g class="branch-master">
<path class="branch" d="M0,0 L0,0" />
<circle class="commit" cx="0" cy="0" r="7.5" />
<g class="label-branch" transform="translate(50,0)">
<rect x="0" y="-12" width="70" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">master</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 420 B

After

Width:  |  Height:  |  Size: 786 B

View File

@ -7,22 +7,38 @@ git commit
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 20 120">
<svg xmlns="http://www.w3.org/2000/svg" transform="translate(10,10)">
<style type="text/css"><![CDATA[
.branch {
fill: none;
stroke-width: 10;
fill: none;
stroke-width: 10;
}
.commit {
fill: #fff;
stroke-width: 5;
fill: #fff;
stroke-width: 5;
}
.branch-master {stroke: #002b36}
.label-tag {
fill: #333;
}
.label-rect {
stroke: none;
}
.label-text {
font-family: Inconsolata, Consolas, monospace;
font-size: 1.5em;
fill: #fff;
stroke: none;
}
.branch-master {stroke: #002b36; fill: #002b36}
]]></style>
<g class="branch-master">
<path class="branch" d="M0,0 L0,100" />
<circle class="commit" cx="0" cy="0" r="7.5" />
<circle class="commit" cx="0" cy="50" r="7.5" />
<circle class="commit" cx="0" cy="100" r="7.5" />
<g class="label-branch" transform="translate(50,100)">
<rect x="0" y="-12" width="70" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">master</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 594 B

After

Width:  |  Height:  |  Size: 961 B

View File

@ -18,18 +18,30 @@ git commit
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 70 270">
<svg xmlns="http://www.w3.org/2000/svg" transform="translate(10,10)">
<style type="text/css"><![CDATA[
.branch {
fill: none;
stroke-width: 10;
fill: none;
stroke-width: 10;
}
.commit {
fill: #fff;
stroke-width: 5;
fill: #fff;
stroke-width: 5;
}
.branch-master {stroke: #002b36}
.branch-test-stuff {stroke: #268bd2}
.label-tag {
fill: #333;
}
.label-rect {
stroke: none;
}
.label-text {
font-family: Inconsolata, Consolas, monospace;
font-size: 1.5em;
fill: #fff;
stroke: none;
}
.branch-master {stroke: #002b36; fill: #002b36}
.branch-test-stuff {stroke: #268bd2; fill: #268bd2}
]]></style>
<g class="merge">
<g class="branch-test-stuff">
@ -40,6 +52,10 @@ git commit
<path class="branch" d="M50,150 L50,200" />
<circle class="commit" cx="50" cy="150" r="7.5" />
<circle class="commit" cx="50" cy="200" r="7.5" />
<g class="label-branch" transform="translate(100,200)">
<rect x="0" y="-12" width="110" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">test-stuff</text>
</g>
</g>
<g class="branch-master">
<path class="branch" d="M0,0 L0,250" />
@ -47,5 +63,9 @@ git commit
<circle class="commit" cx="0" cy="50" r="7.5" />
<circle class="commit" cx="0" cy="100" r="7.5" />
<circle class="commit" cx="0" cy="250" r="7.5" />
<g class="label-branch" transform="translate(100,250)">
<rect x="0" y="-12" width="70" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">master</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -18,18 +18,30 @@ git merge test-merging
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 70 270">
<svg xmlns="http://www.w3.org/2000/svg" transform="translate(10,10)">
<style type="text/css"><![CDATA[
.branch {
fill: none;
stroke-width: 10;
fill: none;
stroke-width: 10;
}
.commit {
fill: #fff;
stroke-width: 5;
fill: #fff;
stroke-width: 5;
}
.branch-master {stroke: #002b36}
.branch-test-merging {stroke: #268bd2}
.label-tag {
fill: #333;
}
.label-rect {
stroke: none;
}
.label-text {
font-family: Inconsolata, Consolas, monospace;
font-size: 1.5em;
fill: #fff;
stroke: none;
}
.branch-master {stroke: #002b36; fill: #002b36}
.branch-test-merging {stroke: #268bd2; fill: #268bd2}
]]></style>
<g class="merge">
<g class="branch-test-merging">
@ -40,6 +52,10 @@ git merge test-merging
<g class="branch-test-merging">
<path class="branch" d="M50,150 L50,150" />
<circle class="commit" cx="50" cy="150" r="7.5" />
<g class="label-branch" transform="translate(100,150)">
<rect x="0" y="-12" width="130" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">test-merging</text>
</g>
</g>
<g class="branch-master">
<path class="branch" d="M0,0 L0,250" />
@ -48,5 +64,9 @@ git merge test-merging
<circle class="commit" cx="0" cy="100" r="7.5" />
<circle class="commit" cx="0" cy="200" r="7.5" />
<circle class="commit" cx="0" cy="250" r="7.5" />
<g class="label-branch" transform="translate(100,250)">
<rect x="0" y="-12" width="70" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">master</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 320">
<svg xmlns="http://www.w3.org/2000/svg" transform="translate(10,10)">
<style type="text/css"><![CDATA[
.branch {
fill: none;
stroke-width: 10;
fill: none;
stroke-width: 10;
}
.commit {
fill: #fff;
stroke-width: 5;
fill: #fff;
stroke-width: 5;
}
.branch-master {stroke: #002b36}
.branch-test-first {stroke: #268bd2}
.branch-test-second {stroke: #859900}
.label-tag {
fill: #333;
}
.label-rect {
stroke: none;
}
.label-text {
font-family: Inconsolata, Consolas, monospace;
font-size: 1.5em;
fill: #fff;
stroke: none;
}
.branch-master {stroke: #002b36; fill: #002b36}
.branch-test-first {stroke: #268bd2; fill: #268bd2}
.branch-test-second {stroke: #859900; fill: #859900}
]]></style>
<g class="merge">
<g class="branch-test-second">
@ -49,10 +63,22 @@ git merge test-second
<path class="branch" d="M100,200 L100,250" />
<circle class="commit" cx="100" cy="200" r="7.5" />
<circle class="commit" cx="100" cy="250" r="7.5" />
<g class="label-tag" transform="translate(150,250)">
<rect x="0" y="-12" width="120" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">v.2.0.0-rc1</text>
</g>
<g class="label-branch" transform="translate(280,250)">
<rect x="0" y="-12" width="120" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">test-second</text>
</g>
</g>
<g class="branch-test-first">
<path class="branch" d="M50,150 L50,150" />
<circle class="commit" cx="50" cy="150" r="7.5" />
<g class="label-branch" transform="translate(150,150)">
<rect x="0" y="-12" width="110" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">test-first</text>
</g>
</g>
<g class="branch-master">
<path class="branch" d="M0,0 L0,300" />
@ -60,5 +86,13 @@ git merge test-second
<circle class="commit" cx="0" cy="50" r="7.5" />
<circle class="commit" cx="0" cy="100" r="7.5" />
<circle class="commit" cx="0" cy="300" r="7.5" />
<g class="label-tag" transform="translate(150,100)">
<rect x="0" y="-12" width="80" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">v.1.0.0</text>
</g>
<g class="label-branch" transform="translate(150,300)">
<rect x="0" y="-12" width="70" height="25" rx="3" class="label-rect" />
<text x="10" y="5" class="label-text">master</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB