aboutsummaryrefslogblamecommitdiff
path: root/watch-git-tags.sh
blob: f8d42658e547a50381c7d9a62b0acbc2e863d40f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11


                                           

                                                                   

                      



                             














                                                                              


                        

                                                     
             

                                                                       



                                                             





                                          

                                             

                            
                                                              
 

                                                                              
                           
                                       
 

        
                                 



                                        
                        

                                                          
                           

                                        



                              

        



                                                                               
# Function to retrieve and filter tag names
tags() {
    case $1 in
        local) git -C "${2:-.}" show-ref --tags ;;
        remote) git -C "${2:-.}" ls-remote --quiet --refs --tags ;;
        *) return 2 ;;
    esac |
    while read -r _ tag ; do
        tag=${tag#refs/tags/}
        printf '%s\n' "$tag"
    done
}

# Create a temporary directory with name in $td, and handle POSIX-ish traps to
# remove it when the script exits; requires mktemp(1) (not POSIX)
td=$(mktemp -d) || exit
cleanup() {
    [ -n "$td" ] || return
    rm -fr -- "$td"
}
for sig in EXIT HUP INT TERM ; do
    # shellcheck disable=SC2064
    trap "cleanup $sig" "$sig"
done

# Use current directory if no other arguments
if [ "$#" -eq 0 ] ; then
    set -- "$PWD"
fi

# Iterate through each repo in a subshell in parallel
for repo do (

    # Make a temporary directory with a hash in its name for uniqueness
    name=$(printf '%s' "$repo" | sed 's:/:_:g')
    cksum=$(printf '%s' "$repo" | cksum | sed 's:[^0-9].*::')
    sd=$td/$name.$cksum
    mkdir -- "$sd" "$sd"/tags || exit

    # Step in and write repo path to file
    cd -- "$sd" || exit
    printf '%s\n' "$repo" > path || exit

    # Write local and remote tags to files
    tags local "$repo" > tags/local || exit
    tags remote "$repo" > tags/remote || exit

    # Write new tags to file
    LC_COLLATE=C comm -13 -- tags/local tags/remote > tags/new

    # Attempt to quietly fetch new tags so that we don't notify about the same
    # ones next time
    [ -s tags/new ] || exit
    git -C "$repo" fetch --quiet --tags

) & done

# Wait for all of those to finish
wait

# Iterate through the temp dirs in order
for dir in "$td"/* ; do (
    cd -- "$dir" || exit

    # Look for non-zero "new" files (at least one new tag)
    [ -s tags/new ] || exit

    # Print repository path and new tags
    cat path
    while read -r tag ; do
        printf '* %s\n' "$tag"
    done < tags/new

) ; done

# Haven't yet decided on exit value semantics; for the moment, if it completes,
# exit success
exit 0