From 7afce21a30355068a4bdd186b44d79dd37d94937 Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Fri, 14 Apr 2023 14:07:43 -0300 Subject: Cleanup repo, reinit in sh --- src/gistatic.in | 700 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 606 insertions(+), 94 deletions(-) (limited to 'src/gistatic.in') diff --git a/src/gistatic.in b/src/gistatic.in index 3f005ee..21980a5 100755 --- a/src/gistatic.in +++ b/src/gistatic.in @@ -1,25 +1,27 @@ #!/bin/sh # shellcheck disable=2034 disable=2059 +# FIXME: remove these ^^^ set -eu MSG_USAGE_EN='Usage: - @NAME@ -i -o DIRECTORY REPOSITORY... - @NAME@ -o DIRECTORY -u CLONE_URL REPOSITORY - @NAME@ [-hV] -' - -MSG_HELP_EN='Options: - -i build the index page of the repositories - -u CLONE_URL address to be shown alongside "git clone" - -o DIRECTORY output where to place the generated files - -h, --help show this help - -V, --version print the version information - -See "man @NAME@" for more information.' - -MSG_MISSING_CLIARG_EN='Missing %s\n' -MSG_INCOMPATIBLE_OPTIONS_EN='Incompatible options -u and -i' -MSG_MISSING_ARGS_EN='Missing [PATH | [PATHS]]' + gistatic -i -o DIRECTORY REPOSITORY... + gistatic -o DIRECTORY -u CLONE_URL [-b MAIN_BRANCH] REPOSITORY + gistatic [-hV]' + +MSG_HELP_EN=' +Options: + -i build the index page of the repositories + -u CLONE_URL address to be shown alongside "git clone" + -o DIRECTORY output where to place the generated files + -b MAIN_BRANCH the default branch of the repository (default: main) + -h, --help show this help + -V, --version print the version information + +See "man gistatic" for more information.' + +MSG_MISSING_CLIARG_EN='Missing %s' +MSG_INCOMPATIBLE_OPTIONS_EN='Incompatible options: ' +MSG_MISSING_ARGS_EN='[PATH | [PATHS]]' MSG_LANGNAME_EN='en' MSG_INDEX_DESCRIPTION_EN='Index of repositories' MSG_DEFAULT_TITLE_EN='Repositories' @@ -28,7 +30,6 @@ MSG_LOGO_ALT_REPOSITORY_EN='Logo image of the repository' MSG_NAME_EN='Name' MSG_DESCRIPTION_EN='Description' MSG_LAST_COMMIT_EN='Last commit' -MSG_FOOTER_TEMPLATE_EN='Generated with @NAME@.' MSG_COMMIT_FEED_EN='commit feed' MSG_TAGS_FEED_EN='tags feed' MSG_NAV_FILES_EN='files' @@ -40,6 +41,10 @@ MSG_THEAD_AUTHOR_EN='Author' MSG_THEAD_DATE_EN='Date' MSG_THEAD_TAG_EN='Tag' MSG_TITLE_REFS_EN='refs' +MSG_GENERATING_LOG_EN='Generating %s...' + +# HTML escaped messages +MSG_ESCAPED_FOOTER_TEMPLATE_EN='Generated with gistatic.' set_lang() { lang="$1" @@ -57,7 +62,6 @@ set_lang() { MSG_NAME=\$MSG_NAME_$lang MSG_DESCRIPTION=\$MSG_DESCRIPTION_$lang MSG_LAST_COMMIT=\$MSG_LAST_COMMIT_$lang - MSG_FOOTER_TEMPLATE=\$MSG_FOOTER_TEMPLATE_$lang MSG_COMMIT_FEED=\$MSG_COMMIT_FEED_$lang MSG_TAGS_FEED=\$MSG_TAGS_FEED_$lang MSG_NAV_FILES=\$MSG_NAV_FILES_$lang @@ -69,6 +73,9 @@ set_lang() { MSG_THEAD_DATE=\$MSG_THEAD_DATE_$lang MSG_THEAD_TAG=\$MSG_THEAD_TAG_$lang MSG_TITLE_REFS=\$MSG_TITLE_REFS_$lang + MSG_GENERATING_LOG=\$MSG_GENERATING_LOG_$lang + + MSG_ESCAPED_FOOTER_TEMPLATE=\$MSG_ESCAPED_FOOTER_TEMPLATE_$lang " } @@ -76,7 +83,7 @@ get_lang() { # LC_MESSAGES="ll_CC.CODESET@modifier" -> ll_CC, where quotes # are optional locale 2>/dev/null | - grep LC_MESSAGES | + grep ^LC_MESSAGES | cut -d. -f1 | cut -d\" -f2 | cut -d= -f2 @@ -93,6 +100,10 @@ esac # Utilities # +tac() { + sed '1!G;h;$!d' +} + escape() { echo "$1" | sed -e 's|&|\&|g;s|<|\<|g;s|>|\>|g;s|"|\"|g' \ @@ -119,7 +130,7 @@ help() { } version() { - printf '@NAME@-@VERSION@ @DATE@\n' + printf 'gistatic-0.1.0 1970-01-01\n' } @@ -199,16 +210,22 @@ print_style() { :root { --color: black; --background-color: white; + --background-contrast-color: hsl(0, 0%, 98%); --hover-color: hsl(0, 0%, 93%); --nav-color: hsl(0, 0%, 87%); + --selected-color: hsl(0, 0%, 80%); + --diff-added-color: hsl(120, 100%, 23%); + --diff-removed-color: hsl(0, 100%, 47%); } @media(prefers-color-scheme: dark) { :root { --color: white; --background-color: black; + --background-contrast-color: hsl(0, 0%, 2%); --hover-color: hsl(0, 0%, 7%); --nav-color: hsl(0, 0%, 13%); + --selected-color: hsl(0, 0%, 20%); } body { @@ -293,6 +310,69 @@ td { padding-right: 1em; } + +/* commit page */ + +.diff-added, .diff-removed { + text-decoration: none; +} + +.diff-added:target, .diff-removed:target { + background-color: var(--selected-color); +} + +.diff-added, .diff-added:visited { + color: var(--diff-added-color); +} + +.diff-removed, .diff-removed:visited { + color: var(--diff-removed-color); +} + + +/* log page */ + +.log-commit-box { + padding: 1em; + margin: 1em; + background-color: var(--background-contrast-color); +} + +.log-commit-tag { + padding: 2px; + border: 1px solid; + color: var(--color); +} + +.log-head-highlight { + background-color: #ff8888; /* FIXME: hsl + dark-mode */ +} + +.log-branch-highlight { + background-color: #88ff88; /* FIXME: hsl + dark-mode */ +} + +.log-tag-highlight { + background-color: #ffff88; /* FIXME: hsl + dark-mode */ +} + +.pre-wrapping { + overflow: auto; + margin: 1em; +} + +.log-notes { + /* FIXME: yellow box goes until the end of the screen */ + padding: 1em; + background-color: #ffd; /* FIXME: hsl + dark-mode */ +} + +.log-pagination { + text-align: center; + margin: 2em; +} + + footer { text-align: center; } @@ -369,7 +449,7 @@ print_index_footer() { @@ -389,6 +469,72 @@ index_write() { print_style > "$OUTDIR/style.css" } +genlog() { + if [ "$VERBOSE" = true ]; then + printf "$MSG_GENERATING_LOG\n" "$1" >&2 + fi +} + +parallel_n=0 +cached_run() { + TARGET_PATH="$1" + shift # drop $TARGET_PATH + shift # drop -- + + if [ -e "$OUTDIR/$TARGET_PATH" ]; then + return + fi + + if [ -e "$CACHE_DIR/$TARGET_PATH" ]; then + cp "$CACHE_DIR/$TARGET_PATH" "$OUTDIR/$TARGET_PATH" + else + { + genlog "$OUTDIR/$TARGET_PATH" + "$@" + cp "$CACHE_DIR/$TARGET_PATH" "$OUTDIR/$TARGET_PATH" + } & + parallel_n=$((parallel_n + 1)) + if [ "$parallel_n" = "$MAX_JOBS" ]; then + wait + parallel_n=0 + fi + fi +} + +repo_tarballs_write() { + repo="$1" + mkdir -p "$OUTDIR/tarballs" "$CACHE_DIR/tarballs" + local_parallel_n=0 + for branch in $(git branch --format '%(refname:lstrip=2)'); do + TARBALL_PATH="$OUTDIR/tarballs/$repo-$branch.tar.gz" + genlog "$TARBALL_PATH" + git archive --prefix "$repo-$branch/" "$branch" \ + -o "$TARBALL_PATH" & + local_parallel_n=$((local_parallel_n + 1)) + if [ "$local_parallel_n" = "$MAX_JOBS" ]; then + wait + local_parallel_n=0 + fi + done + wait + + for tag in $(git tag); do + TARBALL_PATH="tarballs/$repo-$tag.tar.gz" + cached_run "$TARBALL_PATH" -- \ + git archive --prefix "$repo-$tag/" "$tag" \ + -o "$CACHE_DIR/$TARBALL_PATH" + + SIGNATURE_PATH="tarballs/$repo-$tag.tar.gz.asc" + if git notes --ref=refs/notes/signatures/tar.gz show "$tag" \ + 1>/dev/null 2>&1; then + git notes --ref=refs/notes/signatures/tar.gz \ + show "$tag" > "$OUTDIR/$SIGNATURE_PATH" + fi + done + + wait +} + print_repo_refs() { repo="$1" description="$2" @@ -409,7 +555,7 @@ print_repo_refs() {
- +

@@ -428,12 +574,12 @@ print_repo_refs() {

-$(print_formatted_diff "$sha") +$(print_formatted_diff "$sha" "$previous_sha")
@@ -629,76 +839,352 @@ $(print_formatted_diff "$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" -cached_run() { - TARGET_PATH="$1" - shift # drop $TARGET_PATH - shift # drop -- + if [ -e "$OUTDIR/$COMMIT_PATH" ]; then + # Assume all previous history exists, too + break + fi - if [ -e "$OUTDIR/$TARGET_PATH" ]; then - echo "$OUTDIR/$TARGET_PATH" - return - fi - if [ ! -e "$CACHE_DIR/$TARGET_PATH" ]; then - "$@" - fi - cp "$CACHE_DIR/$TARGET_PATH" "$OUTDIR/$TARGET_PATH" + cached_run "$COMMIT_PATH" -- \ + eval "print_repo_commit_page '$repo' '$description' '$commit' \ + > '$CACHE_DIR/$COMMIT_PATH'" + done + done + + wait } -repo_tarballs_write() { +NEWLINE="$(printf '\n')" +print_repo_log_page() { repo="$1" - mkdir -p "$OUTDIR/tarballs" "$CACHE_DIR/tarballs" - for branch in $(git branch --format '%(refname:lstrip=2)'); do - git archive --prefix "$repo-$branch/" "$branch" \ - -o "$OUTDIR/tarballs/$repo-$branch.tar.xz" - done + 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 - for tag in $(git tag); do - TARBALL_PATH="tarballs/$repo-$tag.tar.gz" - cached_run "$TARBALL_PATH" -- \ - git archive --prefix "$repo-$tag/" "$tag" \ - -o "$CACHE_DIR/$TARBALL_PATH" + if [ -z "$older_page_name" ]; then + escaped_older_page_link='' + else + escaped_older_page_link=" older FIXME i18n"' +' + fi - SIGNATURE_PATH="tarballs/$repo-$tag.tar.gz.asc" - if git notes --ref=refs/notes/signatures/tar.gz show "$tag" \ - 1>/dev/null 2>&1; then - git notes --ref=refs/notes/signatures/tar.gz show "$tag" \ - > "$OUTDIR/$SIGNATURE_PATH" + if [ -n "$newer_page_name" ] || [ -n "$older_page_name" ]; then + escaped_pagination_open='
+' + escaped_pagination_close='
+' + 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") + + +
+
+ + + +
+

+ + $(escape "$repo") + +

+

+ $(escape "$description") +

+ + git clone $(escape "$CLONE_URL") + +
+
+ +
+
+
+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 < +
+
+

+ $MSG_ESCAPED_FOOTER_TEMPLATE +

+
+ + +EOF } -repo_commits_write() { - 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 +# 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 - if [ ! -e "CACHE_DIR/$COMMIT_PATH" ]; then - print_repo_commit_page "$repo" "$commit" \ - > "$CACHE_DIR/$COMMIT_PATH" + LAST="$commit" + PAGE_NAME="$FIRST..$LAST.html" + PAGE_SIZE=$((PAGE_SIZE + 1)) + + if [ "$PAGE_SIZE" != "$LOG_PAGE_MAX" ]; then + continue fi - cp "$CACHE_DIR/$COMMIT_PATH" "$OUTDIR/$COMMIT_PATH" - # FIXME: WIP - return + 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 + + +
+
+ + + +
+

+ + $(escape "$repo") + +

+

+ $(escape "$description") +

+ + git clone $(escape "$CLONE_URL") + +
+
+ +
+
+
+
+ Os arquivos vão aqui. +
+
+ O README vai aqui. +
+
+ + + +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" + 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" @@ -725,25 +1211,41 @@ for flag in "$@"; do esac done +VERBOSE=true INDEX=false TITLE="$MSG_DEFAULT_TITLE" OUTDIR= CLONE_URL= CACHE_DIR= -while getopts 'o:t:u:ihV' flag; do +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 - i) - INDEX=true - ;; - t) - TITLE="$OPTARG" + 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 @@ -763,7 +1265,8 @@ shift $((OPTIND - 1)) assert_arg() { if [ -z "$1" ]; then - printf "$MSG_MISSING_CLIARG" "$2" >&2 + printf "$MSG_MISSING_CLIARG\n\n" "$2" >&2 + usage >&2 exit 2 fi } @@ -772,16 +1275,25 @@ assert_arg "$OUTDIR" '-o DIRECTORY' if [ "$INDEX" = false ]; then assert_arg "$CLONE_URL" '-u CLONE_URL' -elif [ -n "$CLONE_URL" ]; then - printf '%s\n' "$MSG_INCOMPATIBLE_OPTIONS" >&2 - exit 2 -fi +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' -if [ -z "${1:-}" ]; then - printf '%s\n' "$MSG_MISSING_ARGS" >&2 + usage + } >&2 exit 2 fi +assert_arg "${1:-}" "$MSG_MISSING_ARGS" + mkdir -p "$OUTDIR" if [ "$INDEX" = true ]; then -- cgit v1.2.3