shithub: gitonline

ref: 93f12f1973aac3ff75f9c485105704c449e33fdb
dir: /gitonline.rc/

View raw version
#!/bin/rc

SITE_TITLE='Git repository browser (mirror of shithub.us)'

nl='
'

rfork ne
ramfs -m /tmp

cd $REPO_DIR

fn resolveref {
	if(~ $gitref HEAD)
		echo $gitref
	if not if(test -d /mnt/git/branch/$gitref/tree)
		echo branch/$gitref
	if not if(test -d /mnt/git/object/$gitref/tree)
		echo object/$gitref
	if not {
		status='bad ref'
	}
}

fn htcat {
	sed '
		s/&/\&/g;
		s/</\&lt;/g;
		s/>/\&gt;/g;
		s/"/\&quot;/g;
		s/''/\&#39;/g
	' $*
}

fn redirect {
	echo 'Status: 301 Moved Permanently'
	echo 'Location: '$1
}

fn html_emit_start {
	echo 'Content-type: text/html'
	echo

	echo '
	<!DOCTYPE html>
	<html>
	<head>
		<title>'$SITE_TITLE'</title>
		<meta charset="UTF-8">
		<style>
	body {
		background-color: #ffffea;
	}
	th {
		text-align: left;
	}
	code > pre.code {
		border: 1px solid black;
		background-color: #eaffff;
	}
		</style>
	</head>'
}

fn html_emit_end {
	echo '
	</body>
	</html>'
}

fn repo_index {
	html_emit_start 
	echo '<h1> '$SITE_TITLE' - index </h1>' 
	dirs=`{walk -d -n2,2}
	echo '
	<table style="width: 100%">
	<tr>
		<th>Name</th>
		<th>Description</th>
		<th>Last change</th>
	</tr>'
	for (d in $dirs) {
		cd $REPO_DIR
		if (test -d $d/.git) {
			cd $d
			git/fs
			echo '
	<tr>
		<td><a href="/'$d'">'$d'</a></td>
		<td>'
		htcat .git/description
		echo '
		</td>
		<td>'
		htcat /mnt/git/HEAD/msg | sed 1q
		echo '
		</td>
	</tr>'
		}
	}
	echo '</table>'
	html_emit_end
}

fn repo_view {
	html_emit_start
	reponame=$1
	echo '
	<h1>'$reponame'</h1>
	<a href="'$reponame'/shortlog">'Shortlog'</a>
	<a href="'$reponame'/browse">'browse'</a>'
	html_emit_end
}

fn repo_browse {
	html_emit_start
	cd $repo
	git/fs

	ref=`{resolveref $gitref}
	if (! ref=`{resolveref $gitref}) {
		`{resolveref $gitref}
		echo '<b>'$status'</b>'
		html_emit_end
		exit
	}

	echo '<h2> Browsing '$repo' at commit '$gitref': '$filepath'</h2>'
	gitpath=/mnt/git/$ref/tree$filepath
	if (test -d $gitpath) {
		cd $gitpath
		files=`$nl{ls -F | sed 's/\*//g'}
		echo '<pre>'
		for (f in $files) {
			echo '<a href="'$f'">'$f'</a>'
		}
		echo '</pre>'
	}
	if not if (test -f $gitpath) {
		echo '<code><pre class="code">'
		htcat $gitpath
		echo '</pre></code>'
	}
	if not {
		echo 'Sorry, could not find '$gitpath
	}
	html_emit_end
}

fn repo_shortlog {
	html_emit_start
	cd $repo
	git/fs
	if (! ref=`{resolveref $gitref}) {
		`{resolveref $gitref}
		echo '<b>'$status'</b>'
		html_emit_end
		exit
	}

	echo '
	<b>Showing the last 100 commits</b>
	<table>
		<tr>
			<th>Date</th>
			<th>Author</th>
			<th>Short message</th>
			<th>Commit hash</th>
		</tr>'
	commithash=`{cat /mnt/git/$ref/hash | sed 1q}
	count=()
	while (! ~ $#commithash 0 && ! ~ $#count 100) {
		count=($count 1)
		message=`{htcat /mnt/git/object/$commithash/msg | sed 1q}
		date=`{date -i `{mtime /mnt/git/object/$commithash/msg | awk '{print $1}'}}
		author=`"{htcat /mnt/git/object/$commithash/author | awk '{print $1}'}
		echo '
		<tr>
			<td>'$date'</td>
			<td>'$author'</td>
			<td>'$"message'</td>
			<td><a href="/'$repo'/showcommit/'$commithash'">'$commithash'</a></td>
		</tr>'
		commithash=`{cat /mnt/git/object/$commithash/parent | sed 1q}
	}
	echo '</table>'
	html_emit_end
}

fn show_commit {
	html_emit_start
	cd $repo
	git/fs
	gitref=$commithash
	if (! ref=`{resolveref $gitref}) {
		`{resolveref $gitref}
		echo '<b>'$status'</b>'
		html_emit_end
		exit
	}
	oldcommit=`{cat /mnt/git/$ref/parent}
	author=`''{htcat /mnt/git/$ref/author}
	date=`''{date `{mtime /mnt/git/$ref/msg | awk '{print $1}'}}
	msg=`''{htcat /mnt/git/$ref/msg}
	echo '
	<table>
	<tr><td><b>Commit:</b></td><td>'$commithash' (<a href="/'$repo'/browse/'$commithash'/">browse</a>)</td></tr>'
	if(~ $#oldcommit 0) {
		echo '<tr><td><b>Parent:</b></td><td>No parent</td></tr>'
	}
	if not {
		echo '<tr><td><b>Parent:</b></td><td><a href="/'$repo'/showcommit/'$oldcommit'">'$oldcommit'</a></td></tr>'
	}
	echo '<tr><td><b>Author:</b></td><td>'$author'</td></tr>
	<tr><td><b>Date:</b></td><td>'$date'</td></tr>
	<tr><td><b>Message:</b></td><td><pre>'$msg'</pre></td></tr>
	<tr><td></td></tr>
	</table>'
	diff=`''{git/export $commithash | 
		sed 's,^--- ([^	]*).*,--- \1,g' | 
		sed 's,^\+\+\+ ([^	]*).*,+++ \1,g' | 
		awk '
BEGIN {
	started=0
}
/^---/ {
	started = 1
}
/^+++/ {
	
}
{
	if (started) { 
		print $0
	}
}
' | htcat |
	sed -e 's,^--- a/(.*),</pre></code><br>\n--- <a href="/'$repo'/browse/'$oldcommit'/\1">\1</a>,g' \
	    -e 's,^\+\+\+ b/(.*),+++ <a href="/'$repo'/browse/'$commithash'/\1">\1</a><code><pre class="code">,g' \
	    -e 's,^--- (/dev/null),</pre></code><br>\n--- \1,g' \
	    -e 's,^\+\+\+ (/dev/null),+++ \1<code><pre class="code">,g' |
	ssam 's,^--- (.*)\n\+\+\+ (.*)$,\1 => \2,g'
}
	echo '<pre><code><pre>'$diff'</pre></code></pre>'
	html_emit_end
}

if (~ $location */browse) {
	redirect $location/HEAD/
}
if not if (~ $location */browse/) {
	redirect $locationHEAD
}
if not if (~ $location */shortlog) {
	redirect $location/HEAD/
}
if not if (~ $location */shortlog/) {
	redirect $locationHEAD
}

if (~ $location /) {
	repo_index
}
if not if (~ $location */showcommit/*) {
	parts=`{echo $location | sed 's,/(.*)/showcommit/([^/]*),\1 \2,'}
	repo=$parts(1)
	commithash=$parts(2)
	show_commit
}
if not if (~ $location */browse/*/* ) {
	parts=`{echo $location | sed 's,/(.*)/browse/([^/]*)(.*),\1 \2 \3,'}
	repo=$parts(1)
	gitref=$parts(2)
	filepath=$parts(3)
	repo_browse
}
if not if (~ $location */shortlog/*/* ) {
	parts=`{echo $location | sed 's,/(.*)/shortlog/([^/]*)(.*),\1 \2 \3,'}
	repo=$parts(1)
	gitref=$parts(2)
	filepath=$parts(3)
	repo_shortlog
}
if not if (test -d $REPO_DIR$location/.git) {
	repo_view $location
}
if not {
	echo no match
}