stagit

Updated README and changed it to markdown

Arjun Choudhary contact@arjunchoudhary.com

commit: 862c56d parent: 4c0ee0b
1 files changed, 274 insertions(+), 0 deletions(-)
AREADME.md+274-0
A · README.md +274, -0
  1@@ -0,0 +1,274 @@
  2+# stagit
  3+
  4+static git page generator.
  5+
  6+It generates static HTML pages for a git repository.
  7+
  8+## Changes
  9+This is my personal fork of stagit.    
 10+It has been modified to fit my needs and some refs points
 11+to cli apps on my web-server.
 12+
 13+* Title of files while viewing is now a link to download the file
 14+* The index page now links to the repository directory
 15+* md4c has been added to parse markdown files
 16+* Added classes and ids to some html tags to easier style them
 17+* Changed style.css to a modern looking nord theme as well as markdown styling
 18+
 19+The link to download the file points to `/raw/?repository=&file=` 
 20+where file is the full path to the file relative to the repository. 
 21+It is also possible to specify which branch to fetch the file from.
 22+
 23+Make necessary changes to the web-server to serve the file    
 24+
 25+To view a file in a bare repository:
 26+
 27+    $cd path/to/repo
 28+    $git show HEAD:path/to/file
 29+
 30+Simple python cgi to serve the file:
 31+
 32+```
 33+#!/bin/python3
 34+
 35+import cgi
 36+import subprocess
 37+import mimetypes
 38+import sys
 39+
 40+def getFile(repo, filepath, branch):
 41+    gitcmd = subprocess.run(['git', 'show', f'{branch}:{filepath}'],
 42+            cwd=f'/home/pi/repositories/{repo}',
 43+            capture_output=True)
 44+    return gitcmd.stdout
 45+
 46+
 47+def guessType(filepath, extensions_map):
 48+    ext = '.' + filepath.split('.')[-1]
 49+    if ext in extensions_map:
 50+        return extensions_map[ext]
 51+    ext = ext.lower()
 52+    if ext in extensions_map:
 53+        return extensions_map[ext]
 54+    return extensions_map['']
 55+
 56+
 57+if not mimetypes.inited:
 58+    mimetypes.init()
 59+extensions_map = mimetypes.types_map.copy()
 60+extensions_map[''] = 'application/octet-stream'
 61+
 62+form = cgi.FieldStorage()
 63+repo = form.getvalue('repository')
 64+filepath = form.getvalue('file')
 65+if (form.getvalue('branch')):
 66+    branch = form.getvalue('branch')
 67+else:
 68+    branch = 'HEAD'
 69+
 70+ctype = guessType(filepath, extensions_map)
 71+response = getFile(repo, filepath, branch)
 72+
 73+if response:
 74+    print(f"Content-Type: {ctype}")
 75+    print(f"Conent-Length: {str(len(response))}")
 76+    print()
 77+    sys.stdout.flush()
 78+    sys.stdout.buffer.write(response)
 79+else:
 80+    print("Content-Type: text/plain")
 81+    print()
 82+    print("404: File not found")
 83+
 84+``` 
 85+
 86+The index page linking to the directory will not change the default 
 87+behavior of stagit if the html files have been created with the [provided 
 88+shell script](example_create.sh.html), since log.html is symlinked
 89+to index.html.    
 90+
 91+This change was made so that the web-server could check if the
 92+request is for a directory. If it is check if there is a file called 
 93+README.md.html in the sub-directory file, if it exists serve that 
 94+file instead of log.html.
 95+
 96+Lighttpd conf to implement this:
 97+
 98+    url.redirect = ( "^\/stagit\/([a-zA-Z0-9-_.,]\/$" => "/stagit/$1/file/README.md" )
 99+    url.rewrite-if-not-file = ( "^\/stagit/([a-zA-Z0-9-_,.]*)\/file\/README.md.html$" => /redirect/$1" )
100+    url.redirect += ( "^\/redirect/\([a-zA-Z0-9-_,.]*)" => "/stagit/$1/log.html" )
101+
102+### md4c
103+md4c is used to parse and convert markdown documents into html. If a file 
104+ends with `.md` it will be parsed by md4c rather than the regular way 
105+stagit parses plain text files.
106+
107+https://github.com/mity/md4c
108+
109+## Usage
110+
111+Make files per repository:
112+
113+    $ mkdir -p htmldir && cd htmldir
114+    $ stagit path-to-repo
115+
116+Make index file for repositories:
117+
118+    $ stagit-index repodir1 repodir2 repodir3 > index.html
119+
120+
121+## Build and install
122+
123+    $ make
124+    # make install
125+
126+
127+## Dependencies
128+
129+- C compiler (C99).
130+- libc (tested with OpenBSD, FreeBSD, NetBSD, Linux: glibc and musl).
131+- libgit2 (v0.22+).
132+- POSIX make (optional).
133+- md4c (markdown parsing to html)
134+
135+## Documentation
136+
137+See man pages: stagit(1) and stagit-index(1).
138+
139+
140+### Building a static binary
141+
142+It may be useful to build static binaries, for example to run in a chroot.
143+
144+It can be done like this at the time of writing (v0.24):
145+
146+    cd libgit2-src
147+
148+    # change the options in the CMake file: CMakeLists.txt
149+    BUILD_SHARED_LIBS to OFF (static)
150+    CURL to OFF              (not needed)
151+    USE_SSH OFF              (not needed)
152+    THREADSAFE OFF           (not needed)
153+    USE_OPENSSL OFF          (not needed, use builtin)
154+    
155+    mkdir -p build && cd build
156+    cmake ../
157+    make
158+    make install
159+
160+
161+### Extract owner field from git config
162+
163+A way to extract the gitweb owner for example in the format:
164+
165+	[gitweb]
166+		owner = Name here
167+
168+Script:
169+
170+    #!/bin/sh
171+    awk '/^[ 	]*owner[ 	]=/ {
172+        sub(/^[^=]*=[ 	]*/, "");
173+        print $0;
174+    }'
175+
176+
177+### Set clone url for a directory of repos
178+
179+    #!/bin/sh
180+    cd "$dir"
181+    for i in *; do
182+        test -d "$i" && echo "git://git.codemadness.org/$i" > "$i/url"
183+    done
184+
185+
186+### Update files on git push
187+
188+Using a post-receive hook the static files can be automatically updated.
189+Keep in mind git push -f can change the history and the commits may need
190+to be recreated. This is because stagit checks if a commit file already
191+exists. It also has a cache (-c) option which can conflict with the new
192+history. See stagit(1).
193+
194+git post-receive hook (repo/.git/hooks/post-receive):
195+
196+    #!/bin/sh
197+    # detect git push -f
198+    force=0
199+    while read -r old new ref; do
200+        hasrevs=$(git rev-list "$old" "^$new" | sed 1q)
201+        if test -n "$hasrevs"; then
202+	        force=1
203+            break
204+        fi
205+    done
206+
207+    # remove commits and .cache on git push -f
208+    #if test "$force" = "1"; then
209+    # ...
210+    #fi
211+
212+    # see example_create.sh for normal creation of the files.
213+
214+
215+### Create .tar.gz archives by tag
216+
217+    #!/bin/sh
218+    name="stagit"
219+    mkdir -p archives
220+    git tag -l | while read -r t; do
221+    	f="archives/${name}-$(echo "${t}" | tr '/' '_').tar.gz"
222+    	test -f "${f}" && continue
223+    	git archive \
224+    		--format tar.gz \
225+    		--prefix "${t}/" \
226+    		-o "${f}" \
227+    		-- \
228+    		"${t}"
229+    done
230+
231+
232+## Features
233+
234+- Log of all commits from HEAD.
235+- Log and diffstat per commit.
236+- Show file tree with linkable line numbers.
237+- Show references: local branches and tags.
238+- Detect README and LICENSE file from HEAD and link it as a webpage.
239+- Detect submodules (.gitmodules file) from HEAD and link it as a webpage.
240+- Atom feed log (atom.xml).
241+- Make index page for multiple repositories with stagit-index.
242+- After generating the pages (relatively slow) serving the files is very fast,
243+  simple and requires little resources (because the content is static), only
244+  a HTTP file server is required.
245+- Usable with text-browsers such as dillo, links, lynx and w3m.
246+
247+
248+## Cons
249+
250+- Not suitable for large repositories (2000+ commits), because diffstats are
251+an expensive operation, the cache (-c flag) is a workaround for this in 
252+some cases.
253+- Not suitable for large repositories with many files, because all files 
254+are written for each execution of stagit. This is because stagit shows the 
255+lines of textfiles and there is no "cache" for file metadata 
256+(this would add more complexity to the code).
257+- Not suitable for repositories with many branches, a quite linear 
258+history is assumed (from HEAD).
259+
260+  In these cases it is better to just use cgit or possibly change stagit to
261+  run as a CGI program.
262+
263+- Relatively slow to run the first time (about 3 seconds for sbase, 
264+1500+ commits), incremental updates are faster.
265+- Does not support some of the dynamic features cgit has, like:
266+  - Snapshot tarballs per commit.
267+  - File tree per commit.
268+  - History log of branches diverged from HEAD.
269+  - Stats (git shortlog -s).
270+
271+  This is by design, just use git locally.
272+- After adding md4c for markdown rendering the stagit-index links are pointed
273+  to /file/README.md.html instead of log.html this in turn requires every repo
274+  to contain a README file in md. (Not really an issue for my personal use case).
275+