EOF
}
print_formatted_diff() {
sha="$1"
previous_sha="$2"
printf ''
# git show -p --stat "$sha"
escape "$(git show -p "$sha")" | awk \
-v SHA="$sha" -v PREVIOUS_SHA="$previous_sha" '
BEGIN {
diff_init = 0
diffl = 0
}
/^(diff|index) / {
diff_init = 1
print $0
next
}
diff_init == 1 && /^--- a\// {
fname = substr($0, 7)
printf "--- a/%s \n",
PREVIOUS_SHA, fname, fname
next
}
diff_init == 1 && /^\+\+\+ b\// {
fname = substr($0, 7)
printf "--- b/%s \n",
SHA, fname, fname
next
}
{ diff_init = 0 }
/^-/ {
diffl++
printf "%s \n",
diffl, diffl, $0
next
}
/^\+/ {
diffl++
printf "%s \n",
diffl, diffl, $0
next
}
{
print $0
}
'
printf ' \n'
}
print_repo_commit_page() {
repo="$1"
description="$2"
sha="$3"
previous_sha="$(git rev-parse "$sha^" 2>/dev/null ||:)"
summary="$(git log -1 --format=%B "$sha")"
cat <
$(escape "$repo")@$(escape "$sha") - $(escape "$summary")
$(print_formatted_diff "$sha" "$previous_sha")
EOF
}
repo_commits_write() {
repo="$1"
description="$2"
mkdir -p "$OUTDIR/commit" "$CACHE_DIR/commit"
for branch in $(git branch --format '%(refname:lstrip=2)'); do
for commit in $(git rev-list "$branch"); do
COMMIT_PATH="commit/$commit.html"
if [ -e "$OUTDIR/$COMMIT_PATH" ]; then
# Assume all previous history exists, too
break
fi
cached_run "$COMMIT_PATH" -- \
eval "print_repo_commit_page '$repo' '$description' '$commit' \
> '$CACHE_DIR/$COMMIT_PATH'"
done
done
wait
}
NEWLINE="$(printf '\n')"
print_repo_log_page() {
repo="$1"
description="$2"
newer_page_name="$3"
older_page_name="$4"
shift
shift
shift
shift
title='FIXME'
if [ -z "$newer_page_name" ]; then
escaped_newer_page_link=''
else
escaped_newer_page_link=" newer FIXME i18n "'
'
fi
if [ -z "$older_page_name" ]; then
escaped_older_page_link=''
else
escaped_older_page_link=" older FIXME i18n "'
'
fi
if [ -n "$newer_page_name" ] || [ -n "$older_page_name" ]; then
escaped_pagination_open='
'
else
escaped_pagination_open=''
escaped_pagination_close=''
fi
if [ -n "$newer_page_name" ] && [ -n "$older_page_name" ]; then
escaped_pagination_separator=' |
'
else
escaped_pagination_separator=''
fi
cat <
$(escape "$repo") - $(escape "$title")
EOF
for commit in "$@"; do
body_txt="$(git log -1 --format=%b "$commit")"
if [ "$body_txt" = "$NEWLINE" ]; then
body=''
else
body="
$body_txt"
fi
notes_txt="$(git log -1 --format=%N "$commit")"
if [ "$notes_txt" = "$NEWLINE" ]; then
escaped_notes=''
else
escaped_notes="
$(escape "$notes_txt") "
fi
# FIXME: show if commit is in branch, tag or HEAD
# HEAD
# main
# v0.2.1
cat <
$(escape "$commit")
|
$(escape "$(git log -1 --format=%an "$commit")")
$(escape "$(git log -1 --format=%s "$commit")") $(escape "$body") $escaped_notes
EOF
done
cat <
EOF
}
# FIXME: use log/main/1.html over diffs?
LOG_PAGE_MAX=50
repo_log_write() {
repo="$1"
description="$2"
mkdir -p "$OUTDIR/log" "$CACHE_DIR/log"
for ref in $(git branch --format '%(refname:lstrip=2)') $(git tag); do
# FIXME: add bail out of loop when the first page already
# exists, so nothing after that needs to be ran
mkdir -p "$CACHE_DIR/log_tmp/$ref"
PAGE_SIZE=0
PAGE_INDEX=0
for commit in $(git rev-list "$ref" | tac); do
if [ "$PAGE_SIZE" = 0 ]; then
FIRST="$commit"
fi
LAST="$commit"
PAGE_NAME="$FIRST..$LAST.html"
PAGE_SIZE=$((PAGE_SIZE + 1))
if [ "$PAGE_SIZE" != "$LOG_PAGE_MAX" ]; then
continue
fi
echo "$PAGE_NAME" > "$CACHE_DIR/log_tmp/$ref/$PAGE_INDEX"
PAGE_INDEX=$((PAGE_INDEX + 1))
PAGE_SIZE=0
done
if [ "$PAGE_SIZE" != 0 ]; then
echo "$PAGE_NAME" > "$CACHE_DIR/log_tmp/$ref/$PAGE_INDEX"
fi
PAGE_COMMITS=''
PAGE_SIZE=0
PAGE_INDEX=0
for commit in $(git rev-list "$ref" | tac); do
PAGE_COMMITS="$commit $PAGE_COMMITS"
PAGE_SIZE=$((PAGE_SIZE + 1))
if [ "$PAGE_SIZE" != "$LOG_PAGE_MAX" ]; then
continue
fi
# FIXME: 80 columns
NEWER_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX + 1))" 2>/dev/null ||:)"
CURRT_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX + 0))" 2>/dev/null ||:)"
OLDER_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX - 1))" 2>/dev/null ||:)"
PAGE_PATH="log/$CURRT_PAGE_NAME"
cached_run "$PAGE_PATH" -- eval "print_repo_log_page \
'$repo' '$description' \
'$NEWER_PAGE_NAME' '$OLDER_PAGE_NAME' \
$PAGE_COMMITS \
> '$CACHE_DIR/$PAGE_PATH'"
PAGE_COMMITS=''
PAGE_SIZE=0
PAGE_INDEX=$((PAGE_INDEX + 1))
done
if [ "$PAGE_SIZE" != 0 ]; then
# FIXME: 80 columns
NEWER_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX + 1))" 2>/dev/null ||:)"
CURRT_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX + 0))" 2>/dev/null ||:)"
OLDER_PAGE_NAME="$(cat "$CACHE_DIR/log_tmp/$ref/$((PAGE_INDEX - 1))" 2>/dev/null ||:)"
PAGE_PATH="log/$CURRT_PAGE_NAME"
cached_run "$PAGE_PATH" -- eval "print_repo_log_page \
'$repo' '$description' \
'$NEWER_PAGE_NAME' '$OLDER_PAGE_NAME' \
$PAGE_COMMITS \
> '$CACHE_DIR/$PAGE_PATH'"
fi
ln -fs "$CURRT_PAGE_NAME" "$OUTDIR/log/$ref.html"
done
rm -rf "$CACHE_DIR/log_tmp"
wait
}
print_repo_index_page() {
repo="$1"
description="$2"
cat <
$(escape "$repo") - FIXME
EOF
}
repo_trees_write() {
echo
}
repo_write() {
cd "$1"
# FIXME: use $REPO and $DESCRIPTION
repo="$(basename "$(realpath "${1%.git}")")"
description="$(cat "$1/description" 2>/dev/null ||:)"
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/gistatic/$repo"
repo_tarballs_write "$repo"
print_repo_refs "$repo" "$description" > "$OUTDIR/refs.html"
repo_commits_write "$repo" "$description"
repo_log_write "$repo" "$description"
print_repo_index_page "$repo" "$description" > "$OUTDIR/index.html"
repo_trees_write "$repo" "$description"
print_logo > "$OUTDIR/logo.svg"
print_style > "$OUTDIR/style.css"
cd - > /dev/null
}
for flag in "$@"; do
case "$flag" in
--)
break
;;
--help)
usage
help
exit
;;
--version)
version
exit
;;
*)
;;
esac
done
VERBOSE=true
INDEX=false
TITLE="$MSG_DEFAULT_TITLE"
OUTDIR=
CLONE_URL=
CACHE_DIR=
MAX_JOBS=1
MAIN_BRANCH='main'
MAIN_BRANCH_SET=false
REPO=
DESCRIPTION=
while getopts 'b:o:t:u:j:iqhV' flag; do
case "$flag" in
b)
MAIN_BRANCH="$OPTARG"
MAIN_BRANCH_SET=true
;;
o)
OUTDIR="$(realpath "$OPTARG")"
;;
t)
TITLE="$OPTARG"
;;
u)
CLONE_URL="$OPTARG"
;;
j)
MAX_JOBS="$OPTARG"
;;
i)
INDEX=true
;;
q)
VERBOSE=false
;;
h)
usage
help
exit
;;
V)
version
exit
;;
*)
usage >&2
exit 2
;;
esac
done
shift $((OPTIND - 1))
assert_arg() {
if [ -z "$1" ]; then
printf "$MSG_MISSING_CLIARG\n\n" "$2" >&2
usage >&2
exit 2
fi
}
assert_arg "$OUTDIR" '-o DIRECTORY'
if [ "$INDEX" = false ]; then
assert_arg "$CLONE_URL" '-u CLONE_URL'
elif [ -n "$CLONE_URL" ] || [ "$MAIN_BRANCH_SET" = true ]; then
{
printf '%s' "$MSG_INCOMPATIBLE_OPTIONS"
printf -- '-i'
if [ -n "$CLONE_URL" ]; then
printf -- ' -u'
fi
if [ "$MAIN_BRANCH_SET" = true ]; then
printf -- ' -b'
fi
printf '\n\n'
usage
} >&2
exit 2
fi
assert_arg "${1:-}" "$MSG_MISSING_ARGS"
mkdir -p "$OUTDIR"
if [ "$INDEX" = true ]; then
index_write "$@"
else
repo_write "$1"
fi