On Wed, Apr 4, 2018 at 12:35 PM, Johannes Schindelin <Johannes.Schindelin@xxxxxx> wrote: > Hi team, > > I found myself in dear need to quickly look up mails in the public-inbox > mail archive corresponding to any given commit in git.git. Some time ago, > I wrote a shell script to help me with that, and I found myself using it a > couple of times, so I think it might be useful for others, too. > > This script (I call it lookup-commit.sh) needs to be dropped into a *bare* > clone of http://public-inbox.org/git, and called with its absolute or > relative path from a git.git worktree, e.g. > > ~/public-inbox-git.git/lookup-commit.sh \ > fea16b47b603e7e4fa7fca198bd49229c0e5da3d > > This will take a while initially, or when the `master` branch of the > public-inbox mirror was updated, as it will generate two files with > plain-text mappings. > > In its default mode, it will print the Message-ID of the mail (if found). > > With --open, it opens the mail in a browser (macOS support is missing, > mainly because I cannot test: just add an `open` alternative to > `xdg-open`). > > With --reply, it puts the mail into the `from-public-inbox` folder of a > maildir-formatted ~/Mail/, so it is pretty specific to my setup here. > > Note: the way mails are matched is by timestamp. In practice, this works > amazingly often (although not always, I reported findings short after > GitMerge 2017). My plan was to work on this when/as needed. > > Note also: the script is very much in a 'works-for-me' state, and I could > imagine that others might want to modify it to their needs. I would be > delighted if somebody would take custody of it (as in: start a repository > on GitHub, adding a README.md, adding a config setting to point to the > location of the public-inbox mirror without having to copy the script, > adding an option to install an alias to run the script, etc). > > And now, without further ado, here it is, the script, in its current glory: > > -- snipsnap -- > #!/bin/sh > > # This is a very simple helper to assist with finding the mail (if any) > # corresponding to a given commit in git.git. > > die () { > echo "$*" >&2 > exit 1 > } > > mode=print > while case "$1" in > --open) mode=open;; > --reply) mode=reply;; > -*) die "Unknown option: $1";; > *) break;; > esac; do shift; done > > test $# = 1 || > die "Usage: $0 ( [--open] | [--reply] ) <commit>" > > test reply != $mode || > test -d "$HOME/Mail" || > die "Need $HOME/Mail to reply" > > commit="$1" > tae="$(git show -s --format='%at %an <%ae>' "$1")" || > die "Could not get Timestamp/Author/Email triplet from $1" > > # We try to match the timestamp first; the author name and author email are > # not as reliable: they might have been overridden via a "From:" line in the > # mail's body > timestamp=${tae%% *} > > cd "$(dirname "$0")" || > die "Could not cd to the public-inbox directory" > > git rev-parse --quiet --verify \ > b60d038730d2c2bb8ab2b48c117db917ad529cf7 >/dev/null 2>&1 || > die "Not a public-inbox directory: $(pwd)" > > head="$(git rev-parse --verify master)" || > die "Could not determine tip of master" > > prevhead= > test ! -f map.latest-rev || > prevhead="$(cat map.latest-rev)" > > if test $head != "$prevhead" > then > range=${prevhead:+$prevhead..}$head > echo "Inserting records for $range" >&2 > git log --format="%at %h %an <%ae>" $range >map.txt.add || > die "Could not enumerate $range" > > cat map.txt map.txt.add 2>/dev/null | sort -n >map.txt.new && > mv -f map.txt.new map.txt || > die "Could not insert new records" > > echo $head >map.latest-rev > fi > > lines="$(grep "^$timestamp " <map.txt)" > if test 1 != $(echo "$lines" | wc -l) > then > test -n "$lines" || > die "No records found for timestamp $timestamp" > > echo "Multiple records found:" > > for h in $(echo "$lines" | cut -d ' ' -f 2) > do > git show -s --format="%nOn %ad, %an <%ae> sent" $h > git show $h | > sed -n -e 's/^+Message-Id: <\(.*\)>/\1/ip' \ > -e 's/^+Subject: //ip' > done > > exit 1 > fi > > # We found exactly one record: print the message ID > h=${lines#$timestamp } > h=${h%% *} > messageid="$(git show $h | sed -n 's/^+Message-Id: <\(.*\)>/\1/ip')" || > die "Could not determine Message-Id from $h" > > case $mode in > print) echo $messageid;; > open) > url=https://public-inbox.org/git/$messageid > case "$(uname -s)" in > Linux) xdg-open "$url";; > MINGW*|MSYS*) start "$url";; Darwin*) open "$url";; > *) die "Need to learn how to open URLs on $(uname -s)";; > esac > ;; > reply) > mkdir -p "$HOME/Mail/from-public-inbox/new" && > mkdir -p "$HOME/Mail/from-public-inbox/cur" && > mkdir -p "$HOME/Mail/from-public-inbox/tmp" || > die "Could not set up mail folder 'from-public-inbox'" > > path=$(git diff --name-only $h^!) && > mail="$(printf "%s_%09d.%s:2," $(date +%s.%N) $$ $(hostname -f))" > && > git show $h:$path >"$HOME/Mail/from-public-inbox/new/$mail" || > die "Could not write mail" > ;; > *) > die "Unhandled mode: $mode" > ;; > esac