commit 5f5ecc9d74a6e0d66eca6f9850d3d55206729b78
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 17 Nov 2022 18:52:27 -0800
initial commit
Diffstat:
6 files changed, 276 insertions(+), 0 deletions(-)
diff --git a/.envrc b/.envrc
@@ -0,0 +1,6 @@
+
+source .privenv || :
+
+export PATH=$PATH:.
+
+
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,4 @@
+
+*.json
+.privenv
+.direnv
diff --git a/Makefile b/Makefile
@@ -0,0 +1,6 @@
+
+PREFIX ?= /usr/local
+
+install:
+	install -Dm755 git-send-nostr $(PREFIX)/bin/git-send-nostr
+	install -Dm755 git-show-nostr $(PREFIX)/bin/git-show-nostr
diff --git a/README.txt b/README.txt
@@ -0,0 +1,28 @@
+
+git-nostr-tools
+===============
+
+Send and receive patches over nostr
+
+Install
+-------
+
+sudo make install
+
+
+Dependencies
+------------
+
+jq, fzf, nostril, nostcat
+
+nostril: https://cdn.jb55.com/tarballs/nostril/
+nostcat: https://github.com/blakejakopovic/nostcat
+
+
+Tools
+-----
+
+git-show-nostr: list patches and show patches
+git-send-nostr: send patches to nostr
+
+
diff --git a/git-send-nostr b/git-send-nostr
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+
+NOSTR_RELAYER=${NOSTR_RELAYER:-nostcat}
+
+if ! command -v $NOSTR_RELAYER >&2 >/dev/null; then
+	printf "error: nostr relayer '%s' not found, set \$NOSTR_RELAYER or install '%s'\n" $NOSTR_RELAYER $NOSTR_RELAYER
+	exit 1
+fi
+
+check_cmd "nostril"
+
+check_cmd() {
+	if ! command -v $1 >&2 >/dev/null; then
+		printf "error: $1 is required. please install. \n"
+		exit 0
+	fi
+}
+
+usage() {
+	printf "usage: git-send-nostr [OPTIONS...] <commit> [NOSTRIL OPTIONS...]\n\n"
+
+	printf "OPTIONS\n\n"
+	printf "     -r            Relay to broadcast to. Will use 'git config nostr.relays' by default\n"
+	printf "     -d            Dry run. Just print event to stdout instead of relaying.\n"
+	printf "\n"
+	printf "     any other nostril option is supported here:\n\n"
+	printf "NOSTRIL OPTIONS\n"
+	nostril | sed '1,/OPTIONS/d'
+	printf "\nEXAMPLES\n\n"
+	printf "git send-nostr -d HEAD^- -t nostril -t nostrildev --pow 15\n\n"
+	exit 0
+}
+
+while getopts "dr:t:" o; do
+    case "${o}" in
+        r)
+            relay=${OPTARG}
+            ;;
+        t)
+            tag=${OPTARG}
+            ;;
+        d)
+            dryrun=1
+            ;;
+        *)
+            usage
+            ;;
+    esac
+done
+shift $((OPTIND-1))
+
+
+if [ -z $relay ]; then
+	relay=$(git config nostr.relays)
+	if [[ $relay == "" ]]; then
+		unset relay
+	fi
+fi
+
+if [ -z $1 ]; then
+	usage
+	exit 0
+fi
+
+commit=$1
+shift
+
+# this can be overridden
+sec="$(git config nostr.secretkey)"
+if [[ $sec != "" ]]; then
+	sec="--sec $sec"
+fi
+
+patch="$(git format-patch --stdout $commit)"
+subject=$(<<<"$patch" grep "^Subject:"| head -n1 | sed 's,^Subject: ,,')
+author=$(<<<"$patch" grep "^From:"| head -n1 | sed 's,^From: ,,')
+json=$(nostril --envelope $sec --kind 19691228 --tag author "$author" --tag subject "$subject" --content "$patch" "$@")
+
+id=$(jq -r '.[1].id' <<<"$json")
+
+if [ -n "$dryrun" ]; then
+	echo "$json"
+	printf "\nDRY RUN. printing event data\n" >&2
+elif [ -z "$relay" ]; then
+	echo "$json"
+	printf "\nRELAY NOT SET, not relaying. Use -r wss://relay.damus.io or 'git config --global nostr.relays wss://relay.damus.io'\n" >&2
+else
+	echo "$id"
+	printf "relaying to $relay using $NOSTR_RELAYER...\n" >&2
+	<<<$json $NOSTR_RELAYER "$relay"
+fi
+
+if [[ $sec == "" ]]; then
+	printf "NOSTR SECRET KEY NOT SET, using random key. Use --sec <key> or 'git config --global nostr.secretkey <hexkey>'\n" >&2
+fi
diff --git a/git-show-nostr b/git-show-nostr
@@ -0,0 +1,137 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+NOSTR_RELAYER=${NOSTR_RELAYER:-nostcat}
+FUZZER=${FUZZER:-fzf}
+
+check_cmd() {
+	if ! command -v $1 >&2 >/dev/null; then
+		printf "error: $1 is required. please install. \n"
+		exit 0
+	fi
+}
+
+if ! command -v $NOSTR_RELAYER >&2 >/dev/null; then
+	printf "error: nostr relayer '%s' not found, set \$NOSTR_RELAYER or install '%s'\n" $NOSTR_RELAYER $NOSTR_RELAYER
+	exit 1
+fi
+
+if ! command -v $FUZZER >&2 >/dev/null; then
+	printf "error: fuzzer '%s' not found, set \$FUZZER or install '%s'\n" $FUZZER $FUZZER
+	exit 1
+fi
+
+check_cmd "nostril"
+check_cmd "jq"
+
+usage() {
+	printf "usage: git-show-nostr [OPTIONS...]\n"
+	printf "\n"
+	printf "OPTIONS\n\n"
+	printf "     -O         output patches to a local file.\n"
+	printf "     -o name    output patches to a local file with a specific filename.\n"
+	printf "     -r relay   nostr relay to query. Uses 'git config nostr.relays' option by default\n"
+	printf "\n"
+	printf "Including query OPTIONS from nostril-query:\n\n"
+	nostril query -h | grep -A100 ^options:
+	exit 0
+}
+
+if [ "$1" == "--help" ]; then
+	usage
+	exit 1
+fi
+
+limit=20
+
+while true; do
+if [ -z $1 ]; then
+	break
+fi
+case "$1" in
+	-O)
+		writeout=1
+		shift
+		;;
+	-o)
+		writeout=1
+		fname=$OPTARG
+		shift
+		;;
+	-r)
+		relay=$2
+		shift
+		shift
+		;;
+	*)
+		break
+		;;
+esac
+done
+
+if [ -z $relay ]; then
+	relay="$(git config nostr.relays)"
+fi
+
+if [ -z $relay ]; then
+	usage
+	exit 0
+fi
+
+target=$tag
+
+fullquery=$(nostril query --kinds 19691228 --limit $limit "$@")
+
+if [ -z $fname ]; then
+	target=${target:-all}
+	outname="nostr-patches-$target.json"
+else
+	outname=$fname
+fi
+
+if [ -z $writeout ]; then
+	outname=$(mktemp)
+fi
+
+echo "$fullquery" | $NOSTR_RELAYER $relay | jq -c '.[2]' > "$outname"
+
+if [ ! -z $writeout ]; then
+	printf "saved results to %s\n" "$outname" >&2
+fi
+
+pager="$(git config core.pager)"
+if [ ! -t 1 ]; then
+	pager=cat
+fi
+
+ev_count=$(wc -l < "$outname")
+if [ $ev_count = 1 ]; then
+	jq -r .content "$outname" | $pager
+	exit 1
+fi
+
+dateformatter=""
+if ! command -v datefmt >&2 >/dev/null; then
+	printf "install https://jb55.com/datefmt if you want nice relative timestamp formatting\n" >&2
+	dateformatter=cat
+else
+	dateformatter="datefmt --relative"
+fi
+
+evid=$(jq -r '
+def tag(name): .tags[] | select(.[0] == name) | .[1];
+
+. | [(.created_at | tostring), (.|tag("t")), (.|tag("author")), (.|tag("subject")), .pubkey[0:20], "id:\(.id)"] | @tsv' "$outname" |
+sort -rn |
+$dateformatter |
+column -t -s $'\t' |
+$FUZZER |
+sed -E -n 's,.*id:(.*)$,\1,p'
+)
+
+jq -r 'select(.id == "'$evid'") | .content' "$outname" | $pager
+
+if [ -z $writeout ]; then
+	rm -f "$outname"
+fi