#!/bin/sh # shellcheck disable=2034 disable=2059 # FIXME: remove these ^^^ set -eu MSG_USAGE_EN='Usage: 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='REPOSITORY' MSG_LANGNAME_EN='en' MSG_INDEX_DESCRIPTION_EN='Index of repositories' MSG_DEFAULT_TITLE_EN='Repositories' MSG_LOGO_ALT_INDEX_EN='Logo image of the repository list' 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_COMMIT_FEED_EN='commit feed' MSG_TAGS_FEED_EN='tags feed' MSG_NAV_FILES_EN='files' MSG_NAV_LOG_EN='log' MSG_NAV_REFS_EN='refs' MSG_THEAD_BRANCH_EN='Branch' MSG_THEAD_COMMITMSG_EN='Commit message' 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" eval " MSG_USAGE=\$MSG_USAGE_$lang MSG_HELP=\$MSG_HELP_$lang MSG_MISSING_CLIARG=\$MSG_MISSING_CLIARG_$lang MSG_INCOMPATIBLE_OPTIONS=\$MSG_INCOMPATIBLE_OPTIONS_$lang MSG_MISSING_ARGS=\$MSG_MISSING_ARGS_$lang MSG_LANGNAME=\$MSG_LANGNAME_$lang MSG_INDEX_DESCRIPTION=\$MSG_INDEX_DESCRIPTION_$lang MSG_DEFAULT_TITLE=\$MSG_DEFAULT_TITLE_$lang MSG_LOGO_ALT_INDEX=\$MSG_LOGO_ALT_INDEX_$lang MSG_LOGO_ALT_REPOSITORY=\$MSG_LOGO_ALT_REPOSITORY_$lang MSG_NAME=\$MSG_NAME_$lang MSG_DESCRIPTION=\$MSG_DESCRIPTION_$lang MSG_LAST_COMMIT=\$MSG_LAST_COMMIT_$lang MSG_COMMIT_FEED=\$MSG_COMMIT_FEED_$lang MSG_TAGS_FEED=\$MSG_TAGS_FEED_$lang MSG_NAV_FILES=\$MSG_NAV_FILES_$lang MSG_NAV_LOG=\$MSG_NAV_LOG_$lang MSG_NAV_REFS=\$MSG_NAV_REFS_$lang MSG_THEAD_BRANCH=\$MSG_THEAD_BRANCH_$lang MSG_THEAD_COMMITMSG=\$MSG_THEAD_COMMITMSG_$lang MSG_THEAD_AUTHOR=\$MSG_THEAD_AUTHOR_$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 " } get_lang() { # LC_MESSAGES="ll_CC.CODESET@modifier" -> ll_CC, where quotes # are optional locale 2>/dev/null | grep ^LC_MESSAGES | cut -d. -f1 | cut -d\" -f2 | cut -d= -f2 } case "$(get_lang)" in *) set_lang EN ;; esac # # Utilities # tac() { sed '1!G;h;$!d' } escape() { printf '%s' "$1" | sed \ -e 's|&|\&|g' \ -e 's|<|\<|g' \ -e 's|>|\>|g' \ -e 's|"|\"|g' \ -e "s|'|\'|g" } realpath() { mkdir -p "$1" cd "$1" pwd } # # Documentation functions # usage() { printf '%s\n' "$MSG_USAGE" } help() { printf '%s\n' "$MSG_HELP" } version() { printf 'gistatic-0.1.0 1970-01-01\n' } # # Template strings # print_logo() { cat <<-'EOF' EOF } print_style() { cat <<-'EOF' :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 { color: var(--color); background-color: var(--background-color); } a { color: hsl(211, 100%, 60%); } a:visited { color: hsl(242, 100%, 80%); } } body { font-family: monospace; max-width: 1100px; margin: 0 auto 0 auto; } .logo { height: 6em; width: 6em; } .header-horizontal-grouping { display: flex; align-items: center; margin-top: 1em; margin-bottom: 1em; } .header-description { margin-left: 2em; } nav { margin-top: 2em; } nav ul { display: flex; list-style-type: none; margin-bottom: 0; } nav li { margin-left: 10px; } nav a, nav a:visited { padding: 2px 8px 0px 8px; color: var(--color); } .selected-nav-item { background-color: var(--nav-color); } hr { margin-top: 0; border: 0; border-top: 3px solid var(--nav-color); } table { margin: 2em auto; } th { padding-bottom: 1em; } tbody tr:hover { background-color: var(--hover-color); } td { padding-left: 1em; 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; } EOF } print_index_header() { cat <<-EOF $(escape "$TITLE")
$(escape

$(escape "$TITLE")


EOF } print_index_row() { repo="$(basename "$(realpath "${1%.git}")")" description="$(cat "$1/description" 2>/dev/null ||:)" last_commit_date="$(git -C "$1" log -1 --format=%cd --date='format:%Y-%m:%d %H:%M' 2>/dev/null ||:)" cat <<-EOF EOF } print_index_footer() { cat <<-EOF
$(escape "$MSG_NAME") $(escape "$MSG_DESCRIPTION") $(escape "$MSG_LAST_COMMIT")
$(escape "$repo") $(escape "$description") $(escape "$last_commit_date")
EOF } index_write() { { print_index_header for r in "$@"; do print_index_row "$r" done print_index_footer } > "$OUTDIR/index.html" print_logo > "$OUTDIR/logo.svg" 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 $CMD "$CACHE_DIR/$TARGET_PATH" "$OUTDIR/$TARGET_PATH" else { genlog "$OUTDIR/$TARGET_PATH" "$@" $CMD "$CACHE_DIR/$TARGET_PATH" "$OUTDIR/$TARGET_PATH" } & parallel_n=$((parallel_n + 1)) if [ "$parallel_n" = "$MAX_JOBS" ]; then wait parallel_n=0 fi fi } # FIXME: get from config? # exts() { } # FIXME: emit signatures code TAB="$(printf '\t')" repo_tarballs_write2() { git branch --format '%(refname:lstrip=2)' | while read -r branch; do cat <<-EOF all: $OUTDIR/tarballs/$NAME-$branch.$EXT $OUTDIR/tarballs/$NAME-$branch.$EXT: $CACHE_DIR/tarballs/$NAME-$branch.$EXT ${TAB}\$(LN) \$? \$@ $CACHE_DIR/tarballs/$NAME-$branch.$EXT: $CACHE_DIR/branch-revisions/$branch ${TAB}git -C "$REPO" archive --prefix $NAME-$branch/ -o \$@ $branch $CACHE_DIR/branch-revisions/$branch: ALWAYS ${TAB}@git -C "$REPO" rev-parse $branch | ifnew \$@ EOF done git tag | while read -r tag; do cat <<-EOF all: $OUTDIR/tarballs/$NAME-$tag.$EXT $OUTDIR/tarballs/$NAME-$tag.$EXT: $CACHE_DIR/tarballs/$NAME-$tag.$EXT ${TAB}\$(LN) \$? \$@ $CACHE_DIR/tarballs/$NAME-$tag.$EXT: ${TAB}git -C "$REPO" archive --prefix $NAME-$tag/ -o \$@ $tag EOF done } 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_refs2() { cat <<-EOF all: $OUTDIR/refs.html $OUTDIR/refs.html: ALWAYS ${TAB}$0 -x refs "$REPO" > \$@ EOF } exec_refs() { repo_vars "$1" cat <<-EOF $(escape "$NAME") - $(escape "$MSG_TITLE_REFS")

$(escape "$NAME")

$(escape "$DESCRIPTION")

git clone $(escape "$CLONE_URL")

EOF for branch in $(git branch --format '%(refname:lstrip=2)'); do sha="$(git rev-parse "$branch")" cat < EOF done cat <
$(escape "$MSG_THEAD_BRANCH") $(escape "$MSG_THEAD_COMMITMSG") $(escape "$MSG_THEAD_AUTHOR") $(escape "$MSG_THEAD_DATE")
$(escape "$branch") $(escape "$(git log -1 --format=%s "$sha")") $(escape "$(git log -1 --format=%an "$sha")") $(escape "$(git log -1 --format=%cd --date='format:%Y-%m:%d %H:%M' "$sha")")
EOF PRINTED_TABLE_OPEN=false for tag in $(git tag | tac); do if [ "$PRINTED_TABLE_OPEN" = false ]; then PRINTED_TABLE_OPEN=true cat < $(escape "$MSG_THEAD_TAG") $(escape "$MSG_THEAD_AUTHOR") $(escape "$MSG_THEAD_DATE") EOF fi if [ -e "$CACHE_DIR/tarballs/$repo-$tag.tar.gz.asc" ]; then tarball_link="(tarball, sig)" else tarball_link="(tarball)" fi cat < $(escape "$tag") $tarball_link $(escape "$(git log -1 --format=%an "$tag")") $(escape "$(git log -1 --format=%cd --date='format:%Y-%m:%d %H:%M' "$tag")") EOF done if [ "$PRINTED_TABLE_OPEN" = true ]; then cat < EOF fi cat <

$MSG_ESCAPED_FOOTER_TEMPLATE

EOF } print_repo_refs() { repo="$1" description="$2" cat < $(escape "$repo") - $(escape "$MSG_TITLE_REFS")

$(escape "$repo")

$(escape "$description")

git clone $(escape "$CLONE_URL")

EOF for branch in $(git branch --format '%(refname:lstrip=2)'); do sha="$(git rev-parse "$branch")" cat < EOF done cat <
$(escape "$MSG_THEAD_BRANCH") $(escape "$MSG_THEAD_COMMITMSG") $(escape "$MSG_THEAD_AUTHOR") $(escape "$MSG_THEAD_DATE")
$(escape "$branch") $(escape "$(git log -1 --format=%s "$sha")") $(escape "$(git log -1 --format=%an "$sha")") $(escape "$(git log -1 --format=%cd --date='format:%Y-%m:%d %H:%M' "$sha")")
EOF PRINTED_TABLE_OPEN=false for tag in $(git tag | tac); do if [ "$PRINTED_TABLE_OPEN" = false ]; then PRINTED_TABLE_OPEN=true cat < $(escape "$MSG_THEAD_TAG") $(escape "$MSG_THEAD_AUTHOR") $(escape "$MSG_THEAD_DATE") EOF fi if [ -e "$CACHE_DIR/tarballs/$repo-$tag.tar.gz.asc" ]; then tarball_link="(tarball, sig)" else tarball_link="(tarball)" fi cat < $(escape "$tag") $tarball_link $(escape "$(git log -1 --format=%an "$tag")") $(escape "$(git log -1 --format=%cd --date='format:%Y-%m:%d %H:%M' "$tag")") EOF done if [ "$PRINTED_TABLE_OPEN" = true ]; then cat < EOF fi cat <

$MSG_ESCAPED_FOOTER_TEMPLATE

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")

$(escape "$repo")

$(escape "$description")

git clone $(escape "$CLONE_URL")

$(print_formatted_diff "$sha" "$previous_sha")

$MSG_ESCAPED_FOOTER_TEMPLATE

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='
' 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 } # 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

$(escape "$repo")

$(escape "$description")

git clone $(escape "$CLONE_URL")

Os arquivos vão aqui.
O README vai aqui.
EOF } repo_trees_write() { echo } preamble() { cat <<-EOF .POSIX: LN = $CMD default: all ALWAYS: EOF } repo_vars() { EXT=tar.xz REPO_DIR="${1%/}" REPO="${1%/}" # FIXME: shesc NAME="$(basename "$REPO" .git)" CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/gistatic/$NAME" GIT_DIR="$REPO/$(git -C "$REPO" rev-parse --git-dir)" export GIT_DIR DESCRIPTION="$(cat "$GIT_DIR"/description 2>/dev/null ||:)" } repo_write2() { repo_vars "$1" mkdir -p \ "$OUTDIR"/tarballs \ "$CACHE_DIR"/tarballs \ "$CACHE_DIR"/branch-revisions { preamble repo_tarballs_write2 print_repo_refs2 } | tee f | make -f- } 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" 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= CMD='ln' EXEC= while getopts 'b:o:t:u:j:isqx:hV' 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 ;; s) CMD='ln -s' ;; x) EXEC="$OPTARG" ;; 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 } if [ -n "$EXEC" ]; then "exec_$EXEC" "$@" exit 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" repo_write2 "$1" fi