#!/bin/sh set -eu MSGS='' add_msg() { MSGS="$MSGS $1" } MSG_USAGE="$(cat <<-'EOF' Usage: git permalink [-phV] FILE [LINENO] EOF )" add_msg USAGE MSG_HELP="$(cat <<-'EOF' Options: -p only print the link, don't try to open it -h, --help show this help message -V, --version print the version number See "man git-permalink" for more information. EOF )" add_msg HELP MSG_MISSING_FILE="$(cat <<-'EOF' Missing FILE argument. EOF )" add_msg MISSING_FILE MSG_UNSUPPORTED_ORIGIN="$(cat <<-'EOF' Unsupported origin: %s. Add a template override to use git-permalink (see "man git-permalink" for instructions). EOF )" add_msg UNSUPPORTED_ORIGIN MSG_OPEN="$(cat <<-'EOF' Opening %s EOF )" add_msg OPEN # # End translatable strings # dump_translatable_strings() { for msg in $MSGS; do eval "echo \"\$MSG_$msg\"" > src/locale/"$msg".en.txt done cat <<-'EOF' #!/bin/sh # shellcheck disable=2034 set -eu EOF for msg in $MSGS; do printf 'MSG_%s="$(cat @LOCALEDIR@/@LANG@/LC_MESSAGES/@NAME@/%s.@LANG@.txt)"\n' \ "$msg" "$msg" done } if [ -n "${GIT_PERMALINK_DUMP_TRANSLATABLE_STRINGS:-}" ]; then dump_translatable_strings exit fi if [ -r '@LIBEXECDIR@/@NAME@/load-messages.sh' ]; then . '@LIBEXECDIR@/@NAME@/load-messages.sh' fi # # Documentation functions # usage() { printf '%s\n' "$MSG_USAGE" } help() { printf '\n%s\n' "$MSG_HELP" } version() { printf 'git-permalink-@VERSION@ @DATE@\n' } # # Core functions # normalize_origin() { if echo "$ORIGIN" | grep -q '^git@'; then NAME="$(echo "$ORIGIN" | cut -d: -f2 | cut -d/ -f1)" URL="$(echo "$ORIGIN" | cut -d@ -f2 | cut -d: -f1)" ORIGIN="https://$URL/$NAME/$REPOSITORY" fi } lineno_with_l() { if echo "$MYLINENO" | grep -q -- -; then P1="$(echo "$MYLINENO" | cut -d- -f1)" P2="$(echo "$MYLINENO" | cut -d- -f2)" printf '#L%s-L%s' "$P1" "$P2" elif [ -n "$MYLINENO" ]; then printf '#L%s' "${MYLINENO}" else printf '' fi } euandreh() { printf 'https://euandreh.xyz/%s.git/tree/%s?id=%s%s\n' \ "$REPOSITORY" "$FILE" "$COMMIT" "${MYLINENO:+#n$MYLINENO}" } sourcehut() { printf '%s/tree/%s/item/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "${MYLINENO:+#L$MYLINENO}" } kernel() { printf '%s/tree/%s?id=%s%s\n' \ "$ORIGIN" "$FILE" "$COMMIT" "${MYLINENO:+#n$MYLINENO}" } savannah() { ORIGIN="$(echo "$ORIGIN" | sed 's|gnu.org/git|gnu.org/cgit|')" printf '%s/tree/%s?id=%s%s\n' \ "$ORIGIN" "$FILE" "$COMMIT" "${MYLINENO:+#n$MYLINENO}" } notabug() { normalize_origin printf '%s/src/%s/%s%s\n' "$ORIGIN" "$COMMIT" "$FILE" "$(lineno_with_l)" } codeberg() { normalize_origin printf '%s/src/commit/%s/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "$(lineno_with_l)" } bitbucket() { normalize_origin MYLINENO="${MYLINENO:+#lines-$(echo "$MYLINENO" | tr '-' ':')}" printf '%s/src/%s/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "$MYLINENO" } pagure() { printf '%s/blob/%s/f/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "${MYLINENO:+#_$MYLINENO}" } gitlab() { normalize_origin printf '%s/-/blob/%s/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "${MYLINENO:+#L$MYLINENO}" } github() { normalize_origin printf '%s/blob/%s/%s%s\n' \ "$ORIGIN" "$COMMIT" "$FILE" "$(lineno_with_l)" } guess_permalink() { if [ -n "$OVERRIDE_CF" ]; then # shellcheck disable=2059 printf "$OVERRIDE_CF\n" "$COMMIT" "$FILE" elif [ -n "$OVERRIDE_FC" ]; then # shellcheck disable=2059 printf "$OVERRIDE_FC\n" "$FILE" "$COMMIT" else case "$ORIGIN" in *euandreh.xyz*) euandreh ;; *git.sr.ht*) sourcehut ;; *git.kernel.org*) kernel ;; *git.savannah.gnu.org*) savannah ;; *notabug.org*) notabug ;; *codeberg.org*) codeberg ;; *bitbucket.org*) bitbucket ;; *pagure.io*) pagure ;; *gitlab.com*) gitlab ;; *github.com*) github ;; *) # shellcheck disable=2059 printf "$MSG_UNSUPPORTED_ORIGIN\n" "$ORIGIN" >&2 exit 1 ;; esac fi } # # Main # for flag in "$@"; do case "$flag" in --) break ;; --help) usage help exit ;; --version) version exit ;; *) ;; esac done PRINTONLY=false while getopts 'phV' flag; do case "$flag" in p) PRINTONLY=true ;; h) usage help exit ;; V) version exit ;; *) usage >&2 exit 2 ;; esac done shift $((OPTIND - 1)) if [ -z "${1:-}" ]; then printf '%s\n\n' "$MSG_MISSING_FILE" >&2 usage >&2 exit 2 fi FILE="$1" MYLINENO="${2:-}" COMMIT="$(git rev-parse HEAD)" ORIGIN="$(git config remote.origin.url)" OVERRIDE_CF="$(git config git-permalink.template-commit-file ||:)" OVERRIDE_FC="$(git config git-permalink.template-file-commit ||:)" REPOSITORY="$(basename "$PWD")" LINK="$(guess_permalink)" if [ "$PRINTONLY" = true ]; then echo "$LINK" else # shellcheck disable=2059 printf "$MSG_OPEN\n" "$LINK" >&2 xdg-open "$LINK" fi