mirror of https://github.com/deuill/grawkit.git
First version of Grawkit, with simple single-branch test
This version has support for adding commits on a single branch using `git commit`, and enough scaffolding for adding additional commands and accompanying tests easily.
This commit is contained in:
commit
0e5eee146f
|
@ -0,0 +1,14 @@
|
||||||
|
# Code styles for Fawkss.
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = tab
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2016 Alex Palaistras
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,98 @@
|
||||||
|
# --------------------
|
||||||
|
# Makefile for Grawkit
|
||||||
|
# --------------------
|
||||||
|
|
||||||
|
# Run `make help` for information on available actions.
|
||||||
|
|
||||||
|
# --------------------
|
||||||
|
# Variable definitions
|
||||||
|
# --------------------
|
||||||
|
|
||||||
|
# Default name for Grawkit executable.
|
||||||
|
CMD = $(CURDIR)/grawkit
|
||||||
|
|
||||||
|
# Default executables to use.
|
||||||
|
SHELL = /bin/bash
|
||||||
|
DIFF = $(shell which colordiff || which diff)
|
||||||
|
|
||||||
|
# Test files to execute.
|
||||||
|
TESTS ?= $(shell find tests/*/*)
|
||||||
|
|
||||||
|
# Color & style definitions.
|
||||||
|
BOLD = \033[1m
|
||||||
|
UNDERLINE = \033[4m
|
||||||
|
RED = \033[31m
|
||||||
|
GREEN = \033[32m
|
||||||
|
BLUE = \033[36m
|
||||||
|
RESET = \033[0m
|
||||||
|
|
||||||
|
# ----------------
|
||||||
|
# Other directives
|
||||||
|
# ----------------
|
||||||
|
|
||||||
|
# Make `help` be the default action when no arguments are passed to `make`.
|
||||||
|
.DEFAULT_GOAL = help
|
||||||
|
.PHONY: $(TESTS) test help
|
||||||
|
|
||||||
|
# Awk script for extracting Grawkit documentation as Markdown.
|
||||||
|
define EXTRACT_MARKDOWN
|
||||||
|
/^(#|# .*)$$/ {
|
||||||
|
if (f==1) {f=0; printf "```\n\n"}
|
||||||
|
print substr($$0, 3)
|
||||||
|
}
|
||||||
|
/^[^#]/ {
|
||||||
|
if (f==0) {f=1; printf "\n```awk\n"}
|
||||||
|
print
|
||||||
|
}
|
||||||
|
!NF {
|
||||||
|
print
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (f==1) {printf "```\n"}
|
||||||
|
}
|
||||||
|
endef
|
||||||
|
export EXTRACT_MARKDOWN
|
||||||
|
|
||||||
|
# ----------------
|
||||||
|
# Rule definitions
|
||||||
|
# ----------------
|
||||||
|
|
||||||
|
## Build documentation from source file in Markdown format.
|
||||||
|
doc:
|
||||||
|
@awk "$$EXTRACT_MARKDOWN" "$(CMD)"
|
||||||
|
|
||||||
|
## Execute test suite, accepts list of specific files to run.
|
||||||
|
test: test-before $(TESTS) test-after
|
||||||
|
|
||||||
|
test-before:
|
||||||
|
@printf ">> $(BOLD)Executing tests...$(RESET)\n"
|
||||||
|
|
||||||
|
test-after:
|
||||||
|
@printf ">> $(BOLD)Finished executing tests.$(RESET)\n"
|
||||||
|
|
||||||
|
$(TESTS):
|
||||||
|
$(eval TEST_$@ := awk '/<!--/ {f=1;next} /-->/ {exit} f' $@)
|
||||||
|
$(eval EXPECTED_$@ := awk '/-->/ {f=1;getline;next} f' $@)
|
||||||
|
$(eval ACTUAL_$@ := $(CMD) <($(TEST_$@)))
|
||||||
|
|
||||||
|
@printf ">> $(BOLD)Testing file '$@'...$(RESET) "
|
||||||
|
|
||||||
|
# Generate diff between expected and actual results and print back to user.
|
||||||
|
@result=$$($(DIFF) -ud <($(EXPECTED_$@)) <($(ACTUAL_$@)) | tail -n +3); \
|
||||||
|
if [ -z "$$result" ]; then \
|
||||||
|
printf "$(GREEN)OK$(RESET)\n"; \
|
||||||
|
else \
|
||||||
|
printf "$(RED)FAIL$(RESET)\n"; \
|
||||||
|
echo "$$result"; \
|
||||||
|
fi \
|
||||||
|
|
||||||
|
## Show usage information for this Makefile.
|
||||||
|
help:
|
||||||
|
@printf "$(BOLD)Grawkit — The Awksome Git Graph Generator.$(RESET)\n\n"
|
||||||
|
@printf "This Makefile contains tasks for processing auxiliary actions, such as\n"
|
||||||
|
@printf "generating documentation or running test cases against the test suite.\n\n"
|
||||||
|
@printf "$(UNDERLINE)Available Tasks$(RESET)\n\n"
|
||||||
|
@awk -F \
|
||||||
|
':|##' '/^##/ {c=$$2; getline; printf "$(BLUE)%6s$(RESET) %s\n", $$1, c}' \
|
||||||
|
$(MAKEFILE_LIST)
|
||||||
|
@printf "\n"
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Grawkit - The AWKsome Git Graph Toolkit
|
||||||
|
|
||||||
|
Grawkit is a tool that helps build SVG graphs from git command-line descriptions, and is built in Awk.
|
||||||
|
|
||||||
|
## Testing & Documentation
|
||||||
|
|
||||||
|
A `Makefile` is provided for running tests and producing documentation for Grawkit. Run `make help` in the project root for more information.
|
||||||
|
|
||||||
|
A full test-suite is provided (depending only on `make` and `awk`), which should serve as a good example of the existing feature-set.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
All code in this repository is covered by the terms of the MIT License, the full text of which can be found in the LICENSE file.
|
||||||
|
|
||||||
|
[license-url]: https://github.com/deuill/grawkit/blob/master/LICENSE
|
||||||
|
[license-svg]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
@ -0,0 +1,157 @@
|
||||||
|
#!/usr/bin/awk -f
|
||||||
|
#
|
||||||
|
# Grawkit — The Awksome Git Graph Generator.
|
||||||
|
# ==========================================
|
||||||
|
#
|
||||||
|
# Grawkit is a tool that helps build SVG graphs from Git command-line descriptions.
|
||||||
|
#
|
||||||
|
# This documentation is built using Markdown syntax, and can be parsed out by
|
||||||
|
# running `make doc` in the project root. Please check the project's README file
|
||||||
|
# for additional information.
|
||||||
|
#
|
||||||
|
# Built-in Functions
|
||||||
|
# ------------------
|
||||||
|
#
|
||||||
|
# This section contains global helper functions, used across different rules, as
|
||||||
|
# defined in the next section below.
|
||||||
|
#
|
||||||
|
# > Function `t` processes the string passed as a template. It's mainly used for
|
||||||
|
# > cleaning up strings with single quotes etc.
|
||||||
|
function t(str) {
|
||||||
|
# Replace single quotes with double quotes.
|
||||||
|
gsub("'", "\"", str)
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
# > Function `branch` renders pre-defined branch under a specific name to its
|
||||||
|
# > SVG representation.
|
||||||
|
function branch(name, _, buf, tmp, refs, i, bs, cs) {
|
||||||
|
# Find index of branch.
|
||||||
|
for (n in branches) {
|
||||||
|
if (n == name) break
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get commit refs.
|
||||||
|
split(branches[name], refs, ",")
|
||||||
|
bs = i * style["branch/spacing"]
|
||||||
|
|
||||||
|
# Add path for branch.
|
||||||
|
tmp = "M" refs[1] * style["commit/spacing"] "," bs
|
||||||
|
tmp = tmp " L" (length(refs) - 1) * style["commit/spacing"] "," bs
|
||||||
|
|
||||||
|
# Print path.
|
||||||
|
buf = sprintf(svg["g"], name)
|
||||||
|
buf = buf "\n" sprintf(svg["path"], tmp)
|
||||||
|
|
||||||
|
# Add commits on path.
|
||||||
|
for (c in refs) {
|
||||||
|
cs = refs[c] * style["commit/spacing"]
|
||||||
|
|
||||||
|
tmp = sprintf(svg["circle"], cs, bs, style["commit/radius"])
|
||||||
|
buf = buf "\n" tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = buf "\n" svg["/g"]
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
# Global Declarations
|
||||||
|
# -------------------
|
||||||
|
#
|
||||||
|
# This block contains logic for initializing global variables used across Grawkit.
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
# Rule matching.
|
||||||
|
rule["commit"] = "^git commit"
|
||||||
|
|
||||||
|
# Style definitions.
|
||||||
|
style["branch/spacing"] = "50"
|
||||||
|
style["branch/fill"] = "none"
|
||||||
|
style["branch/stroke"] = "#333"
|
||||||
|
style["branch/stroke-width"] = "10"
|
||||||
|
|
||||||
|
style["commit/spacing"] = "100"
|
||||||
|
style["commit/fill"] = "#fff"
|
||||||
|
style["commit/stroke"] = style["branch/stroke"]
|
||||||
|
style["commit/stroke-width"] = style["branch/stroke-width"] / 2
|
||||||
|
style["commit/radius"] = style["commit/stroke-width"] * 1.5
|
||||||
|
|
||||||
|
# Static SVG templates.
|
||||||
|
svg["svg"] = t("<svg xmlns='http://www.w3.org/2000/svg' viewBox='%d %d %d %d'>")
|
||||||
|
svg["/svg"] = "</svg>"
|
||||||
|
svg["g"] = t("<g id='%s'>")
|
||||||
|
svg["/g"] = "</g>"
|
||||||
|
svg["path"] = t("<path class='branch' d='%s' />")
|
||||||
|
svg["circle"] = t("<circle class='commit' cx='%d' cy='%d' r='%s' />")
|
||||||
|
|
||||||
|
# Branch definitions.
|
||||||
|
branches["master"] = "0"
|
||||||
|
len["branches"] = 1;
|
||||||
|
|
||||||
|
# Commit definitions.
|
||||||
|
commits[0] = "b:master"
|
||||||
|
len["commits"] = 1;
|
||||||
|
|
||||||
|
# Tracks the state across calls.
|
||||||
|
state["branch"] = "master"
|
||||||
|
state["HEAD"] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rule Definitions
|
||||||
|
# ----------------
|
||||||
|
#
|
||||||
|
# This block contains definitions for line manipulation rules used across Fawkss.
|
||||||
|
# Rules may or may not be exclusive, i.e. the effects of one rule may cascade to
|
||||||
|
# subsequent rules for the same line.
|
||||||
|
#
|
||||||
|
|
||||||
|
# > Match `git commit` declarations.
|
||||||
|
$0 ~ rule["commit"] {
|
||||||
|
# Add new commit with specific message.
|
||||||
|
commits[len["commits"]] = "b:" state["branch"]
|
||||||
|
|
||||||
|
# Update commit references.
|
||||||
|
branches[state["branch"]] = branches[state["branch"]] "," len["commits"]
|
||||||
|
state["HEAD"] = len["commits"]
|
||||||
|
|
||||||
|
len["commits"] += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# SVG Graph Generation
|
||||||
|
#
|
||||||
|
# This block contains logic for building the final SVG output from Grawkit's
|
||||||
|
# internal state, as defined in the command-line provided.
|
||||||
|
#
|
||||||
|
END {
|
||||||
|
xy = style["branch/stroke-width"] * -1
|
||||||
|
w = (style["commit/spacing"] * (len["commits"] - 1)) + (style["commit/stroke-width"] * 4)
|
||||||
|
h = (style["branch/spacing"] * (len["branches"] - 1)) + (style["branch/stroke-width"] * 2)
|
||||||
|
|
||||||
|
# Print SVG header.
|
||||||
|
printf svg["svg"], xy, xy, w, h
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
|
# Print inline style definitions.
|
||||||
|
print t("<style type='text/css'><![CDATA[")
|
||||||
|
print ".branch {"
|
||||||
|
print " fill: " style["branch/fill"] ";"
|
||||||
|
print " stroke: " style["branch/stroke"] ";"
|
||||||
|
print " stroke-width: " style["branch/stroke-width"] ";"
|
||||||
|
print "}"
|
||||||
|
print ".commit {"
|
||||||
|
print " fill: " style["commit/fill"] ";"
|
||||||
|
print " stroke: " style["commit/stroke"] ";"
|
||||||
|
print " stroke-width: " style["commit/stroke-width"] ";"
|
||||||
|
print "}"
|
||||||
|
print "]]></style>"
|
||||||
|
|
||||||
|
# Print each branch and corresponding commits in turn.
|
||||||
|
for (name in branches) {
|
||||||
|
print branch(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print SVG footer.
|
||||||
|
print svg["/svg"]
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!--
|
||||||
|
|
||||||
|
# Test a simple scenario of adding a few commits to `master`.
|
||||||
|
|
||||||
|
git commit -m "Adding a new commit"
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 20">
|
||||||
|
<style type="text/css"><![CDATA[
|
||||||
|
.branch {
|
||||||
|
fill: none;
|
||||||
|
stroke: #333;
|
||||||
|
stroke-width: 10;
|
||||||
|
}
|
||||||
|
.commit {
|
||||||
|
fill: #fff;
|
||||||
|
stroke: #333;
|
||||||
|
stroke-width: 5;
|
||||||
|
}
|
||||||
|
]]></style>
|
||||||
|
<g id="master">
|
||||||
|
<path class="branch" d="M0,0 L100,0" />
|
||||||
|
<circle class="commit" cx="0" cy="0" r="7.5" />
|
||||||
|
<circle class="commit" cx="100" cy="0" r="7.5" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 523 B |
Loading…
Reference in New Issue