Initial commit

This commit is contained in:
Dionysus 2023-06-15 19:50:38 -04:00
commit be306cd215
Signed by: acidvegas
GPG Key ID: EF4B922DB85DC9DE
17 changed files with 2231 additions and 0 deletions

110
Makefile Normal file
View File

@ -0,0 +1,110 @@
.POSIX:
NAME = stagit
VERSION = 1.2
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/man
DOCPREFIX = ${PREFIX}/share/doc/${NAME}
LIB_INC = -I/usr/local/include
LIB_LIB = -L/usr/local/lib -lgit2 -lmd4c-html
# use system flags.
STAGIT_CFLAGS = ${LIB_INC} ${CFLAGS}
STAGIT_LDFLAGS = ${LIB_LIB} ${LDFLAGS}
STAGIT_CPPFLAGS = -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE -D_BSD_SOURCE
# Uncomment to enable workaround for older libgit2 which don't support this
# option. This workaround will be removed in the future *pinky promise*.
#STAGIT_CFLAGS += -DGIT_OPT_SET_OWNER_VALIDATION=-1
SRC = \
stagit.c\
stagit-index.c
COMPATSRC = \
reallocarray.c\
strlcat.c\
strlcpy.c
BIN = \
stagit\
stagit-index
MAN1 = \
stagit.1\
stagit-index.1
DOC = \
LICENSE\
README.md
HDR = compat.h
COMPATOBJ = \
reallocarray.o\
strlcat.o\
strlcpy.o
OBJ = ${SRC:.c=.o} ${COMPATOBJ}
all: ${BIN}
.o:
${CC} -o $@ ${LDFLAGS}
.c.o:
${CC} -o $@ -c $< ${STAGIT_CFLAGS} ${STAGIT_CPPFLAGS}
dist:
rm -rf ${NAME}-${VERSION}
mkdir -p ${NAME}-${VERSION}
cp -f ${MAN1} ${HDR} ${SRC} ${COMPATSRC} ${DOC} \
Makefile assets/favicon.png assets/logo.png assets/style.css assets/helper ${NAME}-${VERSION}
# make tarball
tar -cf - ${NAME}-${VERSION} | \
gzip -c > ${NAME}-${VERSION}.tar.gz
rm -rf ${NAME}-${VERSION}
${OBJ}: ${HDR}
stagit: stagit.o ${COMPATOBJ}
${CC} -o $@ stagit.o ${COMPATOBJ} ${STAGIT_LDFLAGS}
stagit-index: stagit-index.o ${COMPATOBJ}
${CC} -o $@ stagit-index.o ${COMPATOBJ} ${STAGIT_LDFLAGS}
clean:
rm -f ${BIN} ${OBJ} ${NAME}-${VERSION}.tar.gz
install: all
# installing executable files.
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${BIN} ${DESTDIR}${PREFIX}/bin
for f in ${BIN}; do chmod 755 ${DESTDIR}${PREFIX}/bin/$$f; done
# installing example files.
mkdir -p ${DESTDIR}${DOCPREFIX}
cp -f assets/style.css\
assets/favicon.png\
assets/logo.png\
assets/helper\
README.md\
${DESTDIR}${DOCPREFIX}
# installing manual pages.
mkdir -p ${DESTDIR}${MANPREFIX}/man1
cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1
for m in ${MAN1}; do chmod 644 ${DESTDIR}${MANPREFIX}/man1/$$m; done
uninstall:
# removing executable files.
for f in ${BIN}; do rm -f ${DESTDIR}${PREFIX}/bin/$$f; done
# removing example files.
rm -f \
${DESTDIR}${DOCPREFIX}/style.css\
${DESTDIR}${DOCPREFIX}/favicon.png\
${DESTDIR}${DOCPREFIX}/logo.png\
${DESTDIR}${DOCPREFIX}/example_create.sh\
${DESTDIR}${DOCPREFIX}/example_post-receive.sh\
${DESTDIR}${DOCPREFIX}/README.md
-rmdir ${DESTDIR}${DOCPREFIX}
# removing manual pages.
for m in ${MAN1}; do rm -f ${DESTDIR}${MANPREFIX}/man1/$$m; done
.PHONY: all clean dist install uninstall

31
README.md Normal file
View File

@ -0,0 +1,31 @@
# stagit
> static git page generator
## Information
This is my personal fork of [stagit](https://codemadness.org/stagit.html) which is running [git.acid.vegas](https://git.acid.vegas/)
## Dependencies
- C compiler *(C99)*
- libc *(tested with OpenBSD, FreeBSD, NetBSD, Linux: glibc and musl)*
- [libgit2](https://github.com/libgit2/libgit2) *(v0.22+)*
- [md4c](https://github.com/mity/md4c) *(v0.4.4+)*
- POSIX make *(optional)*
## Setup
```shell
cd stagit
make
sudo make install
```
###### New Features
- Markdown rendering to HTML for README files
- Syntax hilighting
- Repository categories
- Direct download to repository tar.gz
- Style changes
###### Props
- Hiltjo Posthuma *(orignal author of [stagit](https://codemadness.org/git/stagit/))*
- Larry Burns *([stagit-md](https://github.com/lmburns/stagit-md))*
- Oscar Benedito *([md4c implementation](https://oscarbenedito.com/blog/2020/08/adding-about-pages-to-stagit/))*

BIN
assets/acidvegas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

62
assets/helper Executable file
View File

@ -0,0 +1,62 @@
#!/bin/sh
# stagit setup helper - developed by acidevegas (https://git.acid.vegas/stagit)
# sudo apt-get install libgit2-1.1 libmd4c*
URL="git.acid.vegas"
PROTO="https"
CLONE_URL="git://$URL"
COMMIT_LIMIT=100
HTML_DIR="$HOME/dev/git/acidvegas/git.acid.vegas"
REPOS_DIR="$HOME/dev/git"
REPO_EXCLUDE="git.acid.vegas"
REPOS="$(find $REPOS_DIR -type d -name mirror -prune -o -type d -name $REPO_EXCLUDE -prune -o -type d -name .git -printf "%h\\n " | sort | xargs echo)"
prepair() {
[ -d $HTML_DIR ] && rm -rf $HTML_DIR/*
mkdir -p $HTML_DIR/assets
cp acidvegas.png favicon.png logo.png mostdangerous.png style.css $HTML_DIR/assets
echo $URL > $HTML_DIR/CNAME
}
make_index() {
echo "[~] creating index..."
args=""
for dir in $(ls $REPOS_DIR | grep -v 'mirror'); do
echo "[~] indexing '$dir' repositories..."
DIR_REPOS="$(find $REPOS_DIR/$dir -type d -name mirror -prune -o -type d -name $REPO_EXCLUDE -prune -o -type d -name .git -printf "%h\\n " | sort | xargs echo)"
args="$args -c \"$dir\" $DIR_REPOS"
done
echo "$args" | xargs stagit-index > $HTML_DIR/index.html
echo "[+] finished"
}
make_repos() {
for dir in $(echo $REPOS); do
USER=$(basename $(dirname $dir))
REPO=$(basename $dir)
if [ -f $dir/.git/description ]; then
if [ "$(cat $dir/.git/description)" = "Unnamed repository; edit this file 'description' to name the repository." ]; then
read -p "description for '$USER/$REPO':" desc
echo "$desc" > $dir/.git/description
echo "[+] updated default 'description' file for '$REPO'"
fi
else
read -p "description for '$USER/$REPO':" desc
echo "$desc" > $dir/.git/description
echo "[+] added missing 'description' file for '$REPO'"
fi
if [ ! -f $dir/.git/url ]; then
echo "$CLONE_URL/$REPO.git" > $dir/.git/url
echo "[+] added missing 'url' file for '$REPO'"
fi
echo "[~] processing '$REPO' repository..."
mkdir -p $HTML_DIR/$REPO && cd $HTML_DIR/$REPO && stagit -l $COMMIT_LIMIT -u "$PROTO://$URL/$REPO" $dir
ln -sf log.html index.html
#git --git-dir $dir/.git archive --format=tar.gz -o "$HTML_DIR/$REPO/$REPO.tar.gz" --prefix="$REPO/" HEAD
done
}
# Main
prepair
make_repos
make_index

BIN
assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

BIN
assets/mostdangerous.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

40
assets/post-recieve Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
# stagit setup helper - developed by acidevegas (https://git.acid.vegas/stagit)
# sudo apt-get install libgit2-1.1 libmd4c*
BASE_URL="https://git.acid.vegas"
CLONE_URL="git://git.acid.vegas"
HTML_DIR="/home/acidvegas/dev/html/stagit/out"
REPOS="$(find $HOME/dev/git -type d -name mirror -prune -o -type d -name .git -print | sort | xargs echo)"
mkdir -p $HTML_DIR
cp favicon.png logo.png style.css $HTML_DIR
for dir in $(echo $REPOS); do
OWNER=$(basename $(dirname $(dirname $dir)))
REPO=$(basename $(dirname $dir))
if [ -f $dir/description ]; then
REPO_DESC=$(cat $dir/description)
if [ "$REPO_DESC" = "Unnamed repository; edit this file 'description' to name the repository." ]; then
nano $dir/description
echo "[+] updated default 'description' file for '$REPO'"
fi
else
nano $dir/description
echo "[+] added missing 'description' file for '$REPO'"
fi
if [ ! -f $dir/owner ]; then
echo $OWNER > $dir/owner
echo "[+] added missing 'owner' file for '$REPO'"
fi
if [ ! -f $dir/url ]; then
echo "$CLONE_URL/$REPO.git" > $dir/url
echo "[+] added missing 'url' file for '$REPO'"
fi
echo "[~] processing '$REPO' repository..."
mkdir -p $HTML_DIR/$REPO && cd $HTML_DIR/$REPO && stagit -c ".cache" -u "$BASE_URL/$REPO" $dir
ln -sf log.html index.html && ln -sf ../style.css style.css && ln -sf ../logo.png logo.png && ln -sf ../favicon.png favicon.png
git --git-dir $dir archive HEAD -o "$HTML_DIR/$REPO/$REPO.zip" # TODO: can we do this with libgit2?
done
echo "[~] creating index..."
stagit-index "$REPOS" > $HTML_DIR/index.html
echo "[+] finished"

42
assets/style.css Normal file
View File

@ -0,0 +1,42 @@
*{font-family:monospace}
a{color:#8dc;text-decoration:none}
a:hover{color:#8dc}
a:target {background-color:#222;}
body{background-color:#000;color:#bdbdbd;font-size:14px;}
h1{display:inline;}
table thead td{font-weight:bold;}
table td{padding:0 0.3em;}
table tr{margin:0px;}
img{max-width:800px}
.border-bottom{border-bottom:1px solid #222;}
.container{border:1px solid #222;border-radius:5px;padding-top:10px;padding-bottom:10px;overflow-x:auto;}
.desc{color:#aaa;}
td.num{text-align:right;}
#blob{text-align:left;}
#blob a{color:#555;}
#blob a:hover{color:#56c8ff;text-decoration:none;}
#blob a:target{color:#eee;}
#content table td{vertical-align:top;white-space:nowrap;}
#index .category td {font-style: italic;}
#index .item-repo td:first-child{padding-left:1.5em;}
#footer{font-size:smaller;padding-top:10px;}
#files tbody tr:hover td, #index .item-repo:hover td, #log tbody tr:hover td{background-color:#111}
#files tr td:nth-child(2), #index .item-repo td:nth-child(2), #log tr td:nth-child(2){white-space:normal;}
.container, #container, #content, #footer, #index, #log{width:100%;max-width:800px;}
a.d, a.h, a.i, a.line {text-decoration:none;}
h1, h2, h3, h4, h5, h6{font-size:1em;margin:0;}
img, h1, h2{vertical-align middle;}
#branches tr td:nth-child(3),
#branches tr:hover td, #tags tr:hover td{background-color:#111;}
#tags tr td:nth-child(3){white-space:normal;}
.A, span.i, pre a.i{color:#00cd00;}
.D, span.d, pre a.d {color:#cd0000;}
.md{text-align:left;}
.md h1{font-size:1.5em;}
.md h2{font-size:1.25em;}
.md table{border-collapse:collapse;margin:1em 1em;border:1px solid var(--border);}
.md table td, .md table th{padding:0.25em 1em;border:1px solid var(--border);}
pre a.h{color:#00cdcd;}
pre a.h:hover, pre a.i:hover, pre a.d:hover{text-decoration:none;}
pre:not(#readme){overflow-x:auto;border:1px solid var(--code-border);border-radius:4px;}

6
compat.h Normal file
View File

@ -0,0 +1,6 @@
#undef strlcat
size_t strlcat(char *, const char *, size_t);
#undef strlcpy
size_t strlcpy(char *, const char *, size_t);
#undef reallocarray
void *reallocarray(void *, size_t, size_t);

39
reallocarray.c Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "compat.h"
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}

47
stagit-index.1 Normal file
View File

@ -0,0 +1,47 @@
.Dd August 2, 2021
.Dt STAGIT-INDEX 1
.Os
.Sh NAME
.Nm stagit-index
.Nd static git index page generator
.Sh SYNOPSIS
.Nm
.Op Ar repodir...
.Sh DESCRIPTION
.Nm
will create an index HTML page for the repositories specified and writes
the HTML data to stdout.
The repos in the index are in the same order as the arguments
.Ar repodir
specified.
.Pp
The basename of the directory is used as the repository name.
The suffix ".git" is removed from the basename, this suffix is commonly used
for "bare" repos.
.Pp
The content of the follow files specifies the meta data for each repository:
.Bl -tag -width Ds
.It .git/description or description (bare repos).
description
.It .git/owner or owner (bare repo).
owner of repository
.El
.Pp
For changing the style of the page you can use the following files:
.Bl -tag -width Ds
.It favicon.png
favicon image.
.It logo.png
32x32 logo.
.It style.css
CSS stylesheet.
.El
.Sh EXAMPLES
.Bd -literal
cd htmlroot
stagit-index path/to/gitrepo1 path/to/gitrepo2 > index.html
.Ed
.Sh SEE ALSO
.Xr stagit 1
.Sh AUTHORS
.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org

216
stagit-index.c Normal file
View File

@ -0,0 +1,216 @@
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <git2.h>
static git_repository *repo;
static const char *relpath = "";
static char description[255] = "Acidvegas Repositories";
static char *name = "";
static char category[255];
/* Handle read or write errors for a FILE * stream */
void checkfileerror(FILE *fp, const char *name, int mode) {
if (mode == 'r' && ferror(fp))
errx(1, "read error: %s", name);
else if (mode == 'w' && (fflush(fp) || ferror(fp)))
errx(1, "write error: %s", name);
}
void joinpath(char *buf, size_t bufsiz, const char *path, const char *path2) {
int r;
r = snprintf(buf, bufsiz, "%s%s%s", path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
if (r < 0 || (size_t)r >= bufsiz)
errx(1, "path truncated: '%s%s%s'", path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
}
/* Percent-encode, see RFC3986 section 2.1. */
void percentencode(FILE *fp, const char *s, size_t len) {
static char tab[] = "0123456789ABCDEF";
unsigned char uc;
size_t i;
for (i = 0; *s && i < len; s++, i++) {
uc = *s;
/* NOTE: do not encode '/' for paths or ",-." */
if (uc < ',' || uc >= 127 || (uc >= ':' && uc <= '@') || uc == '[' || uc == ']') {
putc('%', fp);
putc(tab[(uc >> 4) & 0x0f], fp);
putc(tab[uc & 0x0f], fp);
} else {
putc(uc, fp);
}
}
}
/* Escape characters below as HTML 2.0 / XML 1.0. */
void xmlencode(FILE *fp, const char *s, size_t len) {
size_t i;
for (i = 0; *s && i < len; s++, i++) {
switch(*s) {
case '<': fputs("&lt;", fp); break;
case '>': fputs("&gt;", fp); break;
case '\'': fputs("&#39;" , fp); break;
case '&': fputs("&amp;", fp); break;
case '"': fputs("&quot;", fp); break;
default: putc(*s, fp);
}
}
}
void printtimeshort(FILE *fp, const git_time *intime) {
struct tm *intm;
time_t t;
char out[32];
t = (time_t)intime->time;
if (!(intm = gmtime(&t)))
return;
strftime(out, sizeof(out), "%Y-%m-%d", intm);
fputs(out, fp);
}
void writeheader(FILE *fp) {
fputs("<!DOCTYPE html>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>", fp);
xmlencode(fp, description, strlen(description));
fputs("</title>\n<meta name=\"description\" content=\"acidvegas repositories\">\n"
"<meta name=\"keywords\" content=\"git, repositories, supernets, irc, python, stagit\">\n"
"<meta name=\"author\" content=\"acidvegas\">\n", fp);
fputs("<link rel=\"icon\" type=\"image/png\" href=\"/assets/favicon.png\">\n"
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/style.css\">\n", fp);
fputs("<center>\n<img src=\"/assets/acidvegas.png\"><br>\n<img src=\"/assets/mostdangerous.png\"><br><br>\n"
"<div id=\"content\">\n\t<table id=\"index\">\n\t\t<thead>\n\t\t\t<tr><td>Name</td><td>Description</td><td>Last commit</td></tr>\n\t\t</thead>\n\t\t<tbody>", fp);
}
void writefooter(FILE *fp) {
fputs("\n\t\t</tbody>\n\t</table>\n</div>\n<div id=\"footer\">\n"
"\t&copy; 2023 acidvegas, inc &bull; generated with stagit\n"
"</div>\n</center>", fp);
}
int writelog(FILE *fp) {
git_commit *commit = NULL;
const git_signature *author;
git_revwalk *w = NULL;
git_oid id;
char *stripped_name = NULL, *p;
int ret = 0;
git_revwalk_new(&w, repo);
git_revwalk_push_head(w);
if (git_revwalk_next(&id, w) ||
git_commit_lookup(&commit, repo, &id)) {
ret = -1;
goto err;
}
author = git_commit_author(commit);
/* strip .git suffix */
if (!(stripped_name = strdup(name)))
err(1, "strdup");
if ((p = strrchr(stripped_name, '.')))
if (!strcmp(p, ".git"))
*p = '\0';
fputs("\n\t\t\t<tr class=\"item-repo\"><td><a href=\"", fp);
percentencode(fp, stripped_name, strlen(stripped_name));
fputs("/log.html\">", fp);
xmlencode(fp, stripped_name, strlen(stripped_name));
fputs("</a></td><td>", fp);
xmlencode(fp, description, strlen(description));
fputs("</td><td>", fp);
if (author)
printtimeshort(fp, &(author->when));
fputs("</td></tr>", fp);
git_commit_free(commit);
err:
git_revwalk_free(w);
free(stripped_name);
return ret;
}
int main(int argc, char *argv[]) {
FILE *fp;
char path[PATH_MAX], repodirabs[PATH_MAX + 1];
const char *repodir;
int i, ret = 0;
if (argc < 2) {
fprintf(stderr, "usage: %s [repodir...]\n", argv[0]);
return 1;
}
/* do not search outside the git repository:
GIT_CONFIG_LEVEL_APP is the highest level currently */
git_libgit2_init();
for (i = 1; i <= GIT_CONFIG_LEVEL_APP; i++)
git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, i, "");
/* do not require the git repository to be owned by the current user */
git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 0);
#ifdef __OpenBSD__
if (pledge("stdio rpath", NULL) == -1)
err(1, "pledge");
#endif
writeheader(stdout);
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-c")) {
i++;
if (i == argc)
err(1, "missing argument");
repodir = argv[i];
fputs("\n\t\t\t<tr class=\"category\"><td colspan=\"3\">", stdout);
xmlencode(stdout, repodir, strlen(repodir));
fputs("</td></tr>", stdout);
continue;
}
repodir = argv[i];
if (!realpath(repodir, repodirabs))
err(1, "realpath");
if (git_repository_open_ext(&repo, repodir, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL)) {
fprintf(stderr, "%s: cannot open repository\n", argv[0]);
ret = 1;
continue;
}
/* use directory name as name */
if ((name = strrchr(repodirabs, '/')))
name++;
else
name = "";
/* read description or .git/description */
joinpath(path, sizeof(path), repodir, "description");
if (!(fp = fopen(path, "r"))) {
joinpath(path, sizeof(path), repodir, ".git/description");
fp = fopen(path, "r");
}
description[0] = '\0';
if (fp) {
if (!fgets(description, sizeof(description), fp))
description[0] = '\0';
checkfileerror(fp, "description", 'r');
fclose(fp);
}
writelog(stdout);
}
writefooter(stdout);
/* cleanup */
git_repository_free(repo);
git_libgit2_shutdown();
checkfileerror(stdout, "<stdout>", 'w');
return ret;
}

125
stagit.1 Normal file
View File

@ -0,0 +1,125 @@
.Dd August 2, 2021
.Dt STAGIT 1
.Os
.Sh NAME
.Nm stagit
.Nd static git page generator
.Sh SYNOPSIS
.Nm
.Op Fl c Ar cachefile
.Op Fl l Ar commits
.Op Fl u Ar baseurl
.Ar repodir
.Sh DESCRIPTION
.Nm
writes HTML pages for the repository
.Ar repodir
to the current directory.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl c Ar cachefile
Cache the entries of the log page up to the point of
the last commit.
The
.Ar cachefile
will store the last commit id and the entries in the HTML table.
It is up to the user to make sure the state of the
.Ar cachefile
is in sync with the history of the repository.
.It Fl l Ar commits
Write a maximum number of
.Ar commits
to the log.html file only.
However the commit files are written as usual.
.It Fl u Ar baseurl
Base URL to make links in the Atom feeds absolute.
For example: "https://git.codemadness.org/stagit/".
.El
.Pp
The options
.Fl c
and
.Fl l
cannot be used at the same time.
.Pp
The following files will be written:
.Bl -tag -width Ds
.It atom.xml
Atom XML feed of the last 100 commits.
.It tags.xml
Atom XML feed of the tags.
.It files.html
List of files in the latest tree, linking to the file.
.It log.html
List of commits in reverse chronological applied commit order, each commit
links to a page with a diffstat and diff of the commit.
.It refs.html
Lists references of the repository such as branches and tags.
.El
.Pp
For each entry in HEAD a file will be written in the format:
file/filepath.html.
This file will contain the textual data of the file prefixed by line numbers.
The file will have the string "Binary file" if the data is considered to be
non-textual.
.Pp
For each commit a file will be written in the format:
commit/commitid.html.
This file will contain the diffstat and diff of the commit.
It will write the string "Binary files differ" if the data is considered to
be non-textual.
Too large diffs will be suppressed and a string
"Diff is too large, output suppressed" will be written.
.Pp
When a commit HTML file exists it won't be overwritten again, note that if
you've changed
.Nm
or changed one of the metadata files of the repository it is recommended to
recreate all the output files because it will contain old data.
To do this remove the output directory and
.Ar cachefile ,
then recreate the files.
.Pp
The basename of the directory is used as the repository name.
The suffix ".git" is removed from the basename, this suffix is commonly used
for "bare" repos.
.Pp
The content of the follow files specifies the metadata for each repository:
.Bl -tag -width Ds
.It .git/description or description (bare repo).
description
.It .git/owner or owner (bare repo).
owner of repository
.It .git/url or url (bare repo).
primary clone URL of the repository, for example:
git://git.codemadness.org/stagit
.El
.Pp
When a README or LICENSE file exists in HEAD or a .gitmodules submodules file
exists in HEAD a direct link in the menu is made.
.Pp
For changing the style of the page you can use the following files:
.Bl -tag -width Ds
.It favicon.png
favicon image.
.It logo.png
32x32 logo.
.It style.css
CSS stylesheet.
.El
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
.Bd -literal
mkdir -p htmlroot/htmlrepo1 && cd htmlroot/htmlrepo1
stagit path/to/gitrepo1
# repeat for other repositories.
.Ed
.Pp
To update the HTML files when the repository is changed a git post-receive hook
can be used, see the file example_post-receive.sh for an example.
.Sh SEE ALSO
.Xr stagit-index 1
.Sh AUTHORS
.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org

1404
stagit.c Normal file

File diff suppressed because it is too large Load Diff

57
strlcat.c Normal file
View File

@ -0,0 +1,57 @@
/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include "compat.h"
/*
* Appends src to string dst of size dsize (unlike strncat, dsize is the
* full size of dst, not space left). At most dsize-1 characters
* will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
* Returns strlen(src) + MIN(dsize, strlen(initial dst)).
* If retval >= dsize, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t dsize)
{
const char *odst = dst;
const char *osrc = src;
size_t n = dsize;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end. */
while (n-- != 0 && *dst != '\0')
dst++;
dlen = dst - odst;
n = dsize - dlen;
if (n-- == 0)
return(dlen + strlen(src));
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return(dlen + (src - osrc)); /* count does not include NUL */
}

52
strlcpy.c Normal file
View File

@ -0,0 +1,52 @@
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include "compat.h"
/*
* Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0).
* Returns strlen(src); if retval >= dsize, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t dsize)
{
const char *osrc = src;
size_t nleft = dsize;
/* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */
while (*src++)
;
}
return(src - osrc - 1); /* count does not include NUL */
}