~kaction/forge-link

49694809e04f66c97e5631c77f6a52b142c4a269 — Dmitry Bogatov 3 years ago
Initial revision
1 files changed, 78 insertions(+), 0 deletions(-)

A forge-link
A  => forge-link +78 -0
@@ 1,78 @@
#!/bin/sh
set -eu

if [ $# != 1 ] && [ $# != 2 ]; then
	cat 2>&1 <<EOF
usage: forge-link FILE [LINE]

Analyze git repository, containing specified file and print link to that
file (optionally, with exact line) on web interface of one of known git
forges. Following forges are supported:

 * SourceHut
EOF
	exit 1
fi

readonly file=$1
readonly line=${2:-0}

if [ ! -e "${file}" ]; then
	echo "error: no such file: ${file}"
	exit 1
fi

cd "${file}/.."
gitroot=$(git rev-parse --show-toplevel)
abspath=$(realpath "${file}")
relpath=${abspath##${gitroot}}
sha1=$(git rev-parse HEAD)

# Remotes named "upstream" and "origin" are considered before others, in
# this order.
has_upstream_remote=no
has_origin_remote=no

remotes=$(git remote)
set --
for remote in $remotes; do # no quotes
	if [ "${remote}" = upstream ]; then
		has_upstream_remote=yes
		continue
	fi

	if [ "${remote}" = origin ]; then
		has_origin_remote=yes
		continue
	fi

	set -- "$@" "${remote}"
done

# Order matters, so if both "origin" and "upstream" remotes are present,
# "upstream" will be considered before "origin".
if [ "${has_origin_remote}" = yes ]; then
	set -- origin "$@"
fi

if [ "${has_upstream_remote}" = yes ]; then
	set -- upstream "$@"
fi

for remote; do
	base=$(git config "remote.${remote}.url")
	if [ "${base}" != "${base##https://git.sr.ht/}" ] ; then
		url="${base}/tree/${sha1}${relpath}"
		if [ "${line}" != 0 ] ; then
			url="${url}#L${line}"
		fi
	fi
	# Use HEAD method, don't waste our and forge's bandwidth.
	http_code=$(curl -I -s -o /dev/null "${url}" -w '%{http_code}')
	if [ "${http_code}" = 200 ] ; then
		echo "${url}"
		exit 0
	fi
done
echo >&2 "error: failed to construct link to forge"
exit 1