Added chroma syntax highlighting
5 files changed, 59 insertions(+), 195 deletions(-) | |||
---|---|---|---|
M | Makefile | +8 | -1 |
D | README | +0 | -186 |
M | stagit | +0 | -0 |
M | stagit.c | +51 | -8 |
D | stagit.o | +0 | -0 |
1@@ -8,9 +8,15 @@ PREFIX = /usr/local
2 MANPREFIX = ${PREFIX}/man
3 DOCPREFIX = ${PREFIX}/share/doc/${NAME}
4
5+CHROMA = $(shell which chroma > /dev/null; echo $$?)
6 LIBGIT_INC = -I/usr/local/include
7 LIBGIT_LIB = -L/usr/local/lib -lgit2
8
9+ifeq (${CHROMA}, 0)
10+ STAGIT_CPPFLAGS := ${STAGIT_CPPFLAGS} -DHAS_CHROMA
11+endif
12+
13+
14 # use system flags.
15 STAGIT_CFLAGS = ${LIBGIT_INC} ${CFLAGS}
16 STAGIT_LDFLAGS = ${LIBGIT_LIB} ${LDFLAGS}
17@@ -26,6 +32,7 @@ COMPATSRC = \
18 entity.c\
19 md4c.c\
20 md4c-html.c
21+
22 BIN = \
23 stagit\
24 stagit-index
25@@ -90,7 +97,7 @@ install: all
26 logo.png\
27 example_create.sh\
28 example_post-receive.sh\
29- README\
30+ README.md\
31 ${DESTDIR}${DOCPREFIX}
32 # installing manual pages.
33 mkdir -p ${DESTDIR}${MANPREFIX}/man1
D · README
+0, -186 1@@ -1,186 +0,0 @@
2-stagit
3-------
4-
5-static git page generator.
6-
7-It generates static HTML pages for a git repository.
8-
9-
10-Usage
11------
12-
13-Make files per repository:
14-
15- $ mkdir -p htmlroot/htmlrepo1 && cd htmlroot/htmlrepo1
16- $ stagit path/to/gitrepo1
17- repeat for other repositories
18- $ ...
19-
20-Make index file for repositories:
21-
22- $ cd htmlroot
23- $ stagit-index path/to/gitrepo1 \
24- path/to/gitrepo2 \
25- path/to/gitrepo3 > index.html
26-
27-
28-Build and install
29------------------
30-
31-$ make
32-# make install
33-
34-
35-Dependencies
36-------------
37-
38-- C compiler (C99).
39-- libc (tested with OpenBSD, FreeBSD, NetBSD, Linux: glibc and musl).
40-- libgit2 (v0.22+).
41-- POSIX make (optional).
42-
43-
44-Documentation
45--------------
46-
47-See man pages: stagit(1) and stagit-index(1).
48-
49-
50-Building a static binary
51-------------------------
52-
53-It may be useful to build static binaries, for example to run in a chroot.
54-
55-It can be done like this at the time of writing (v0.24):
56-
57-cd libgit2-src
58-
59-# change the options in the CMake file: CMakeLists.txt
60-BUILD_SHARED_LIBS to OFF (static)
61-CURL to OFF (not needed)
62-USE_SSH OFF (not needed)
63-THREADSAFE OFF (not needed)
64-USE_OPENSSL OFF (not needed, use builtin)
65-
66-mkdir -p build && cd build
67-cmake ../
68-make
69-make install
70-
71-
72-Extract owner field from git config
73------------------------------------
74-
75-A way to extract the gitweb owner for example in the format:
76-
77- [gitweb]
78- owner = Name here
79-
80-Script:
81-
82- #!/bin/sh
83- awk '/^[ ]*owner[ ]=/ {
84- sub(/^[^=]*=[ ]*/, "");
85- print $0;
86- }'
87-
88-
89-Set clone URL for a directory of repos
90---------------------------------------
91- #!/bin/sh
92- cd "$dir"
93- for i in *; do
94- test -d "$i" && echo "git://git.codemadness.org/$i" > "$i/url"
95- done
96-
97-
98-Update files on git push
99-------------------------
100-
101-Using a post-receive hook the static files can be automatically updated.
102-Keep in mind git push -f can change the history and the commits may need
103-to be recreated. This is because stagit checks if a commit file already
104-exists. It also has a cache (-c) option which can conflict with the new
105-history. See stagit(1).
106-
107-git post-receive hook (repo/.git/hooks/post-receive):
108-
109- #!/bin/sh
110- # detect git push -f
111- force=0
112- while read -r old new ref; do
113- hasrevs=$(git rev-list "$old" "^$new" | sed 1q)
114- if test -n "$hasrevs"; then
115- force=1
116- break
117- fi
118- done
119-
120- # remove commits and .cache on git push -f
121- #if test "$force" = "1"; then
122- # ...
123- #fi
124-
125- # see example_create.sh for normal creation of the files.
126-
127-
128-Create .tar.gz archives by tag
129-------------------------------
130- #!/bin/sh
131- name="stagit"
132- mkdir -p archives
133- git tag -l | while read -r t; do
134- f="archives/${name}-$(echo "${t}" | tr '/' '_').tar.gz"
135- test -f "${f}" && continue
136- git archive \
137- --format tar.gz \
138- --prefix "${t}/" \
139- -o "${f}" \
140- -- \
141- "${t}"
142- done
143-
144-
145-Features
146---------
147-
148-- Log of all commits from HEAD.
149-- Log and diffstat per commit.
150-- Show file tree with linkable line numbers.
151-- Show references: local branches and tags.
152-- Detect README and LICENSE file from HEAD and link it as a webpage.
153-- Detect submodules (.gitmodules file) from HEAD and link it as a webpage.
154-- Atom feed of the commit log (atom.xml).
155-- Atom feed of the tags/refs (tags.xml).
156-- Make index page for multiple repositories with stagit-index.
157-- After generating the pages (relatively slow) serving the files is very fast,
158- simple and requires little resources (because the content is static), only
159- a HTTP file server is required.
160-- Usable with text-browsers such as dillo, links, lynx and w3m.
161-
162-
163-Cons
164-----
165-
166-- Not suitable for large repositories (2000+ commits), because diffstats are
167- an expensive operation, the cache (-c flag) is a workaround for this in
168- some cases.
169-- Not suitable for large repositories with many files, because all files are
170- written for each execution of stagit. This is because stagit shows the lines
171- of textfiles and there is no "cache" for file metadata (this would add more
172- complexity to the code).
173-- Not suitable for repositories with many branches, a quite linear history is
174- assumed (from HEAD).
175-
176- In these cases it is better to just use cgit or possibly change stagit to
177- run as a CGI program.
178-
179-- Relatively slow to run the first time (about 3 seconds for sbase,
180- 1500+ commits), incremental updates are faster.
181-- Does not support some of the dynamic features cgit has, like:
182- - Snapshot tarballs per commit.
183- - File tree per commit.
184- - History log of branches diverged from HEAD.
185- - Stats (git shortlog -s).
186-
187- This is by design, just use git locally.
M · stagit
+0, -0
M · stagit.c
+51, -8 1@@ -6,6 +6,7 @@
2 #include <libgen.h>
3 #include <limits.h>
4 #include <stdint.h>
5+#include <stdbool.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9@@ -75,6 +76,9 @@ static char *readmefiles[] = { "HEAD:README", "HEAD:README.md" };
10 static char *readme;
11 static long long nlogcommits = -1; /* -1 indicates not used */
12
13+bool htmlized; /* true if markdoown converted to HTML */
14+
15+
16 /* cache */
17 static git_oid lastoid;
18 static char lastoidstr[GIT_OID_HEXSZ + 2]; /* id + newline + NUL byte */
19@@ -592,9 +596,47 @@ writeblobmd(FILE *fp, const git_blob *blob)
20 return n;
21 }
22
23-size_t
24-writeblobhtml(FILE *fp, const git_blob *blob)
25+int
26+syntax_highlight(const char *filename, FILE *fp, const char *s, size_t len)
27 {
28+ // Flush HTML-file
29+ fflush(fp);
30+ // Copy STDOUT
31+ int stdout_copy = dup(1);
32+ // Redirect STDOUT
33+ dup2(fileno(fp), 1);
34+
35+ char cmd[255] = "chroma --html --html-only --html-lines --html-lines-table --filename ";
36+
37+ strncat(cmd, filename, strlen(filename) + 1);
38+ FILE *child = popen(cmd, "w");
39+ if (child == NULL) {
40+ printf("child is null: %s", strerror(errno));
41+ exit(1);
42+ }
43+
44+ // Give filename through STDIN:
45+ // fprintf(child, "%s\n", filename);
46+
47+ // Give code to highlight through STDIN:
48+ int lc;
49+ size_t i;
50+ for (i = 0; *s && i < len; s++, i++) {
51+ if (*s == '\n') lc++;
52+ fprintf(child, "%c", *s);
53+ }
54+
55+ pclose(child);
56+ fflush(stdout);
57+ // Give back STDOUT.
58+ dup2(stdout_copy, 1);
59+ return lc;
60+}
61+
62+size_t
63+writeblobhtml(const char *filename, FILE *fp, const git_blob *blob)
64+{
65+ int lc = 0;
66 size_t n = 0, i, len, prev;
67 const char *nfmt = "<a href=\"#l%zu\" class=\"line\" id=\"l%zu\">%zu</a>";
68 const char *s = git_blob_rawcontent(blob);
69@@ -603,7 +645,9 @@ writeblobhtml(FILE *fp, const git_blob *blob)
70 fputs("<pre id=\"blob\">\n", fp);
71
72 if (len > 0) {
73- for (i = 0, prev = 0; i < len; i++) {
74+ syntax_highlight(filename, fp, s, len);
75+ /* Uncomment to render the original file (no syntax highlight) */
76+/* for (i = 0, prev = 0; i < len; i++) {
77 if (s[i] != '\n')
78 continue;
79 n++;
80@@ -611,15 +655,14 @@ writeblobhtml(FILE *fp, const git_blob *blob)
81 xmlencodeline(fp, &s[prev], i - prev + 1);
82 putc('\n', fp);
83 prev = i + 1;
84- }
85+ } */
86 /* trailing data */
87- if ((len - prev) > 0) {
88+/* if ((len - prev) > 0) {
89 n++;
90 fprintf(fp, nfmt, n, n, n);
91 xmlencodeline(fp, &s[prev], len - prev);
92- }
93+ } */
94 }
95-
96 fputs("</pre>\n", fp);
97
98 return n;
99@@ -1029,7 +1072,7 @@ writeblob(git_object *obj, const char *fpath, const char *filename, size_t files
100 if (ferror(fp))
101 err(1, "md parse fail");
102 } else {
103- lc = writeblobhtml(fp, (git_blob *)obj);
104+ lc = writeblobhtml(filename, fp, (git_blob *)obj);
105 if (ferror(fp))
106 err(1, "fwrite");
107 }
D · stagit.o
+0, -0