#!/usr/bin/env bash
# Desc: Grep search filenames of all git committed work trees
# Usage: git-bk-find-file [string regex]
# Example git-bk-find-file '*.txt'
# Ref/Attrib: albfan "How can I search Git branches for a file or directory?" https://stackoverflow.com/a/16868704/10850071
# Version: 0.0.1
# Depends: GNU bash v5.1.16, GNU parallel 20210822

yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
check_depends() {
    # Desc: Check dependencies
    # Usage: check_depends
    # Depends: GNU parallel 20210822
    if ! command -v parallel 1>/dev/random 2>&1; then die "FATAL:Missing:parallel"; fi;
    if ! command -v git 1>/dev/random 2>&1; then die "FATAL:Missing:git"; fi;
};
check_args() {
    if [[ $# -le 0 ]]; then die "FATAL:Incorrect number of args:$#"; fi;
}; # check arguments
display_commit() {
    # Show commit if filename in committed tree matches grep pattern
    # Input: arg1: commit id
    #        args2+: passed to grep
    # Output: stdout
    local commit results;
    
    commit="$1"; shift;

    # Decide if need to show commit at all
    if results="$(git ls-tree -r --name-only "$commit" | grep "$1")"; then
        commit="${commit:(-8)}"; # get last 8 chars
        # Prepend results with commit
        results="$( echo "$results" | sed "s/^/$commit: /" )";
        printf "%s\n" "$results";
    fi;
    
    return 0;
}; # display commit
main() {
    check_depends;
    check_args "$@";
    export -f yell die must display_commit;
    git rev-list --all | parallel --jobs=75% display_commit "{}" "$@";
};

main "$@";

# Author: Steven Baltakatei Sandoval
# License: GPLv3+