←︎ stagit :: eef4ee8


1
commit eef4ee86d0a16f028010b6ce0c54f2521d802cbb
2
Author: acidvegas <acid.vegas@acid.vegas>
3
Date:   Wed Apr 8 19:44:53 2020 -0400
4
5
    Initial commit
6
---
7
 LICENSE   |  15 +++++
8
 README.md |  43 ++++++++++++
9
 stagit    | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
 3 files changed, 279 insertions(+)
11
12
diff --git a/LICENSE b/LICENSE
13
new file mode 100644
14
index 0000000..0f72fc8
15
--- /dev/null
16
+++ b/LICENSE
17
@@ -0,0 +1,15 @@
18
+ISC License
19
+
20
+Copyright (c) 2020, acidvegas <acid.vegas@acid.vegas>
21
+
22
+Permission to use, copy, modify, and/or distribute this software for any
23
+purpose with or without fee is hereby granted, provided that the above
24
+copyright notice and this permission notice appear in all copies.
25
+
26
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33
diff --git a/README.md b/README.md
34
new file mode 100644
35
index 0000000..997263d
36
--- /dev/null
37
+++ b/README.md
38
@@ -0,0 +1,43 @@
39
+# stagit
40
+> static git page generator
41
+
42
+## Information
43
+This is basically a pure shell script clone of [stagit](https://git.2f30.org/stagit/).
44
+
45
+It is meant to be hosted on [Github](https://github.com) using [Github Pages](https://pages.github.com) with a [Custom domain](https://help.github.com/en/articles/using-a-custom-domain-with-github-pages).
46
+
47
+A live demo of this script can be seen [here](https://acid.vegas).
48
+
49
+## Settings
50
+| Setting          | Default        | Description                                                        |
51
+| ---------------- | -------------- | ------------------------------------------------------------------ |
52
+| CLONE_URL        | remote         | base url for cloning repositories *(remote = remote.origin.url)*   |
53
+| CNAME            | empty          | create a CNAME file with a custom domain *(empty = do not create)* |
54
+| MAX_COMMITS      | 100            | maximum number of commits to show (0 = all)                        |
55
+| MAX_COMMIT_MSG   | 100            | maximum characters in a commit message to display *(0 = all)*      |
56
+| MAX_COMMIT_LINES | 999            | maximum number of lines to show in a commit *(0 = all)*            |
57
+| REPO_DIR         | $HOME/git      | directory containing repositories                                  |
58
+| THEME            | light          | style used *(light or dark)*                                       |
59
+| TITLE            | "Repositories" | title used on homepage                                             |
60
+| WWW_DIR          | $HOME/www      | directory to output to                                             |
61
+
62
+If the `CLONE_URL` was set to `https://github.com/acidvegas/` for example, then it will display as `git clone https://github.com/acidvegas/REPO_NAME.git` on all repository indexes, otherwise if you leave it as `remote` it will just parse the remote url *(`git config --get remote.origin.url`)* for that repository. For those using the `remote` option, remote urls from Github/Gitlab that use SSH will be converted to an HTTPS url. This applies to Github/Gitlab remote urls only, so if you cloned your repositories with SSH, then people may not be able to clone your repositories!
63
+
64
+The `CNAME` option is optional if you are planning on using a custom domain with Github pages. See [here](https://help.github.com/en/articles/troubleshooting-custom-domains#github-repository-setup-errors) for more information.
65
+
66
+Lastly, stagit will ignore the `$REPO_DIR/mirrors` directory by default. To make stagit include this directory, remove `-path $REPO_DIR/mirrors -prune` from the `find` command in the source.
67
+
68
+## Todo
69
+- mailto links in commits and more
70
+- Create an index per-user to view specific users repos & key information.
71
+- Pagination support for repos exceeding `MAX_COMMITS`.
72
+- Add a footer to all pages with the last updated datetime and a link to this repository.
73
+- Hook git pushes to rebuild the repositories index.
74
+- Add support for displaying LICENSE/README files and convert markdown to HTML.
75
+- Add support to view file contents.
76
+- Fix all possible bashisms identified in source by checkbashisms.
77
+
78
+## Mirrors
79
+- [acid.vegas](https://acid.vegas/stagit) *(main)*
80
+- [GitHub](https://github.com/acidvegas/stagit)
81
+- [GitLab](https://gitlab.com/acidvegas/stagit)
82
diff --git a/stagit b/stagit
83
new file mode 100755
84
index 0000000..d4b94d7
85
--- /dev/null
86
+++ b/stagit
87
@@ -0,0 +1,221 @@
88
+#!/bin/sh
89
+# developed by acidvegas (https://acid.vegas/stagit)
90
+
91
+set -e
92
+
93
+##### settings ########################################################################
94
+CLONE_URL='remote'   # base url for cloning repositories ('remote' = remote.origin.url)
95
+CNAME=''             # create a CNAME file with a custom domain (empty = do not create)
96
+MAX_COMMITS=100      # maximum number of commits to show (0 = all)
97
+MAX_COMMIT_MSG=100   # maximum characters in a commit message to display (0 = all)
98
+MAX_COMMIT_LINES=999 # maximum number of lines to show in a commit (0 = all)
99
+REPO_DIR=$HOME/git   # directory containing repositories
100
+THEME='light'        # default style used ('light' or 'dark')
101
+TITLE='Repositories' # title used on homepage
102
+WWW_DIR=$HOME/www    # directory to output to
103
+#######################################################################################
104
+
105
+generate_404() {
106
+	{
107
+		echo "<!doctype html>"
108
+		echo "<title>Error</title>"
109
+		if [ $THEME = 'light' ]; then
110
+			echo "<style>body{background-color:#fff;color:#000;font-family:monospace}</style>"
111
+		else # We have to use internal CSS here because the style.css path will differ inside directories!
112
+			echo "<style>body{background-color:#111;color:#fff;font-family:monospace}</style>"
113
+		fi
114
+		echo "<br><br><br><enter><h1>404</h1></center>"
115
+	} > $WWW_DIR/404.html
116
+}
117
+
118
+generate_yml() {
119
+	{
120
+		echo "pages:"
121
+		echo "  stage: deploy"
122
+		echo "  script:"
123
+		echo "  - mkdir .public"
124
+		echo "  - cp -r * .public"
125
+		echo "  - mv .public public"
126
+		echo "  artifacts:"
127
+		echo "    paths:"
128
+		echo "    - public"
129
+		echo "  only:"
130
+		echo "  - master"
131
+	} > $WWW_DIR/.gitlab-ci.yml
132
+}
133
+
134
+generate_css() {
135
+	if [ $THEME = 'light' ]; then
136
+		{
137
+			echo "a{color:blue}"
138
+			echo "body{background-color:#fff;color:#000;font-family:monospace;margin-top:0px}"
139
+			echo "h1{margin:0px}"
140
+			echo "h1 a{color:#000;text-decoration:none}"
141
+			echo "h4{color:#777;margin:0px}"
142
+			echo "h5{margin:0px;font-style:italic;font-weight:normal}"
143
+			echo "hr{border:none;border-bottom:1px solid #777}"
144
+			echo "pre{margin:0px}"
145
+			echo ".bold{font-weight:bold}"
146
+			echo ".branch{color:green;font-weight:bold}"
147
+			echo ".commit{color:olive}"
148
+			echo ".deletion{color:red}"
149
+			echo ".hunk{color:teal}"
150
+			echo ".insertion{color:green}"
151
+			echo ".reference{color:teal;font-weight:bold}"
152
+			echo ".remote{color:red;font-weight:bold}"
153
+			echo ".item:hover{background-color:#eee}"
154
+			echo ".item td{white-space:nowrap}"
155
+			echo ".linenumber{text-align:right;-moz-user-select:-moz-none;-khtml-user-select: none;-webkit-user-select:none}"
156
+			echo ".linenumber a{text-decoration:none}"
157
+			echo "#main{border-collapse:collapse;table-layout:fixed}"
158
+			echo "#main td,th{padding-left:5px;padding-right:5px}"
159
+			echo "#navigation{color:#000;font-weight:900;text-align:left}"
160
+		} > $WWW_DIR/style.css
161
+	else
162
+		{
163
+			echo "a{color:#8dc}"
164
+			echo "a:hover{color:#8cd}"
165
+			echo "body{background-color:#111;color:#fff;font-family:monospace;margin-top:0px}"
166
+			echo "h1{margin:0px}"
167
+			echo "h1 a{color:#fff;text-decoration:none}"
168
+			echo "h4{color:#777;margin:0px}"
169
+			echo "h5{font-style:italic;font-weight:normal;margin:0px}"
170
+			echo "hr{border:none;border-bottom:1px dashed #fff}"
171
+			echo "pre{margin:0px}"
172
+			echo ".bold{font-weight:bold}"
173
+			echo ".branch{color:green;font-weight:bold}"
174
+			echo ".commit{color:olive}"
175
+			echo ".deletion{color:red}"
176
+			echo ".hunk{color:teal}"
177
+			echo ".insertion{color:green}"
178
+			echo ".reference{color:teal;font-weight:bold}"
179
+			echo ".remote{color:red;font-weight:bold}"
180
+			echo ".item:hover{background-color:#1a1a1a}"
181
+			echo ".item td{white-space:nowrap}"
182
+			echo ".linenumber{text-align:right;-moz-user-select:-moz-none;-khtml-user-select: none;-webkit-user-select:none}"
183
+			echo ".linenumber a{text-decoration:none}"
184
+			echo "#main{border-collapse:collapse;table-layout:fixed}"
185
+			echo "#main td,th{padding-left:5px;padding-right:5px}"
186
+			echo "#navigation{color:#fff;font-weight:900;text-align:left}"
187
+		} > $WWW_DIR/style.css
188
+	fi
189
+}
190
+
191
+generate_index() {
192
+	{
193
+		echo "<!doctype html>"
194
+		echo "<link rel=\"stylesheet\" href=\"style.css\">"
195
+		echo "<title>$TITLE</title>"
196
+		echo "<h1>&#8962;&#xFE0E; $TITLE</h1>"
197
+		echo "<hr>"
198
+		echo "<table id=\"main\" cellpadding=\"0\" cellspacing=\"0\">"
199
+		echo "<tr id=\"navigation\"><th>Name</th><th>Description</th><th>Owner</th><th>Last commit</th></tr>"
200
+	} > $WWW_DIR/index.html
201
+}
202
+
203
+generate_repository_index() {
204
+	local REPO_NAME=$1
205
+	local REPO_URL=$2
206
+	local REPO_DESC=${@:3} # todo: fix possible bashism
207
+	mkdir -p $WWW_DIR/$REPO_NAME/commit
208
+	{
209
+		echo "<!doctype html>"
210
+		echo "<link rel=\"stylesheet\" href=\"../style.css\">"
211
+		echo "<title>$REPO_NAME</title>"
212
+		echo "<h1><a href=\"../index.html\" title=\"Home\">&#8962;&#xFE0E;</a> $REPO_NAME</h1>"
213
+		echo "<div style=\"padding-left:30px\">"
214
+		echo "<h4>$REPO_DESC</h4>"
215
+		echo "<h5>git clone <a href=\"$REPO_URL\" title=\"$REPO_NAME clone URL\">$REPO_URL</a></h5>"
216
+		echo "</div>"
217
+		echo "<hr>"
218
+		echo "<table id=\"main\" cellpadding=\"0\" cellspacing=\"0\">"
219
+		echo "<tr id=\"navigation\"><th></th><th>Hash</th><th>Commit message</th><th>Author</th><th>Date</th><th align=\"right\">Files</th><th align=\"right\">+</th><th align=\"right\">-</th></tr>"
220
+	} > $WWW_DIR/$REPO_NAME/index.html
221
+}
222
+
223
+generate_commit_index() {
224
+	local REPO_NAME=$1
225
+	local COMMIT_HASH=$2
226
+	{
227
+		echo "<!doctype html>"
228
+		echo "<link rel=\"stylesheet\" href=\"../../style.css\">"
229
+		echo "<title>$REPO_NAME :: $COMMIT_HASH</title>"
230
+		echo "<h1><a href=\"../index.html\" title=\"Back to Repository\">&larr;&#xFE0E;</a> $REPO_NAME :: $COMMIT_HASH</h1>"
231
+		echo "<hr>"
232
+		echo "<table id=\"main\" cellpadding=\"0\" cellspacing=\"0\">"
233
+	} > $WWW_DIR/$REPO_NAME/commit/$COMMIT_HASH.html
234
+}
235
+
236
+[ ! -d $REPO_DIR ] && echo "'$REPO_DIR' directory does not exist" && exit 1
237
+REPOS=$(find $REPO_DIR -type d -name mirrors -prune -o -type d -name .git -print | sort  -t '/' -k 7)
238
+[ -z "$REPOS" ] && echo "'$REPO_DIR' contains no repositories" && exit 1
239
+mkdir -p $WWW_DIR && rm -rf $WWW_DIR/*
240
+[ ! -z $CNAME ] && echo $CNAME > $WWW_DIR/CNAME
241
+generate_yml && generate_404 && generate_css && generate_index
242
+for d in $REPOS; do
243
+	REPO_NAME=$(basename -s .git `git --git-dir $d config --get remote.origin.url`)
244
+	if [ -f $d/description ]; then
245
+		REPO_DESC=$(head -n 1 $d/description)
246
+		if [ "$REPO_DESC" = "Unnamed repository; edit this file 'description' to name the repository." ]; then
247
+			echo "edit description for $REPO_NAME ($d/description)"
248
+			REPO_DESC="no description available"
249
+		fi
250
+	else
251
+		echo "missing description file for $REPO_NAME ($d/description)"
252
+		REPO_DESC="no description available"
253
+	fi
254
+	REPO_OWNER=$(git --git-dir $d log --reverse --pretty=format:'%an' | head -n 1) # todo: find a better way to do this & handle organization name parsing
255
+	REPO_LAST_COMMIT=$(git --git-dir $d log -1 --pretty=format:'%cs')
256
+	echo "<tr class=\"item\"><td><a href=\"$REPO_NAME\" title=\"$REPO_NAME\">$REPO_NAME</a></td><td>$REPO_DESC</td><td>$REPO_OWNER</td><td>$REPO_LAST_COMMIT</td></tr>" >> $WWW_DIR/index.html
257
+	if [ $CLONE_URL = 'remote' ]; then
258
+		REPO_URL=$(git --git-dir $d config --get remote.origin.url)
259
+		REPO_URL=$(echo $REPO_URL | sed 's#git@github.com:#https://github.com/#' | sed 's#git@gitlab.com:#https://gitlab.com/#')
260
+	else
261
+		REPO_URL=$CLONE_URL/$REPO_NAME.git
262
+	fi
263
+	generate_repository_index $REPO_NAME $REPO_URL $REPO_DESC
264
+	if [ $MAX_COMMITS -eq 0 ]; then
265
+		REPO_COMMITS=$(git --git-dir $d log --all --date=format:"%Y-%m-%d %H:%M" --pretty=format:"%G?|%GS|%GK|%h|%s|%cn|%cd")
266
+	else
267
+		REPO_COMMITS=$(git --git-dir $d log --all --date=format:"%Y-%m-%d %H:%M" --pretty=format:"%G?|%GS|%GK|%h|%s|%cn|%cd" | head -n $MAX_COMMITS)
268
+	fi
269
+	echo "$REPO_COMMITS" | while IFS= read -r line; do
270
+		COMMIT_SIGNED=$(echo $line | cut -d'|' -f1)
271
+		COMMIT_KEY=$(echo $line | cut -d'|' -f2)
272
+		COMMIT_KEYID=$(echo $line | cut -d'|' -f3)
273
+		if [ $COMMIT_SIGNED = 'G' ]; then
274
+			COMMIT_SIGNED="<span style=\"color:green\" title=\"$COMMIT_KEY&#13;$COMMIT_KEYID\">&#128274;&#xFE0E;</span>"
275
+		elif [ $COMMIT_SIGNED = 'B' ] || [ $COMMIT_SIGNED = 'U' ]  || [ $COMMIT_SIGNED = 'X' ] || [ $COMMIT_SIGNED = 'Y' ] || [ $COMMIT_SIGNED = 'R' ]; then
276
+			COMMIT_SIGNED="<span style=\"color:red\" title=\"$COMMIT_KEY&#13;$COMMIT_KEYID&#13;key is bad, invalid, expired, or revoked\">&#128274;&#xFE0E;</span>"
277
+		else
278
+			COMMIT_SIGNED=""
279
+		fi
280
+		COMMIT_HASH=$(echo $line | cut -d'|' -f4)
281
+		COMMIT_MESSAGE=$(echo $line | cut -d'|' -f5 | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;s/"/\&quot;/g;')
282
+		if [ $MAX_COMMIT_MSG -ne 0 -a ${#COMMIT_MESSAGE} -gt $MAX_COMMIT_MSG ]; then
283
+			COMMIT_MESSAGE=${COMMIT_MESSAGE:0:$MAX_COMMIT_MSG}... # todo: fix possible bashism
284
+		fi
285
+		COMMIT_AUTHOR=$(echo $line | cut -d'|' -f6)
286
+		COMMIT_DATE=$(echo $line | cut -d'|' -f7)
287
+		COMMIT_SUMMARY=$(git --git-dir $d show $COMMIT_HASH --stat | grep -E "fil(e|es) changed" | awk '{files+=$1; inserted+=$4; deleted+=$6} END {printf "%s|+%s|-%s", files, inserted, deleted }')
288
+		COMMIT_FILES=$(echo $COMMIT_SUMMARY | cut -d'|' -f1)
289
+		COMMIT_INSERTIONS=$(echo $COMMIT_SUMMARY | cut -d'|' -f2)
290
+		COMMIT_DELETIONS=$(echo $COMMIT_SUMMARY | cut -d'|' -f3)
291
+		echo "<tr class=\"item\"><td>$COMMIT_SIGNED</td><td><a href=\"commit/$COMMIT_HASH.html\" title=\"View this commit\">$COMMIT_HASH</a></td><td>$COMMIT_MESSAGE</td><td>$COMMIT_AUTHOR</td><td>$COMMIT_DATE</td><td align=\"right\">$COMMIT_FILES</td><td align=\"right\">$COMMIT_INSERTIONS</td><td align=\"right\">$COMMIT_DELETIONS</td></tr>" >> $WWW_DIR/$REPO_NAME/index.html
292
+		generate_commit_index $REPO_NAME $COMMIT_HASH
293
+		if [ $MAX_COMMIT_LINES -ne 0 -a $(echo "$COMMIT_DIFF" | wc -l) -gt $MAX_COMMIT_LINES ]; then
294
+			COMMIT_DIFF=$(echo "$COMMIT_DIFF" | head -n $MAX_COMMIT_LINES)
295
+		fi
296
+		COMMIT_DIFF=$(echo "$COMMIT_DIFF" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;s/"/\&quot;/g;' | tr -d '\r')
297
+		COMMIT_DIFF=$(echo "$COMMIT_DIFF" | sed 's/\[31m/<span class="deletion">/g; s/\[1\;31m/<span class="remote">/g; s/\[32m/<span class="insertion">/g; s/\[1\;32m/<span class="branch">/g; s/\[33m/<span class="commit">/g; s/\[36m/<span class="hunk">/g; s/\[1\;36m/<span class="reference">/g; s/\[1m/<span class="bold">/g; s/\[m/<\/span>/g')
298
+		COUNT=1
299
+		echo "$COMMIT_DIFF" | while IFS= read -r line; do
300
+				echo "<tr class=\"item\"><td class=\"linenumber\"><a href=\"#l$COUNT\" name=\"l$COUNT\">$COUNT</a></td><td><pre>$line</pre></td></tr>" >> $WWW_DIR/$REPO_NAME/commit/$COMMIT_HASH.html
301
+				COUNT=`expr $COUNT + 1`
302
+			fi
303
+		done
304
+		echo "</table></pre>" >> $WWW_DIR/$REPO_NAME/commit/$COMMIT_HASH.html
305
+	done
306
+done