From 0c8b79bd53e1ff75c5a96a6dc018adb9da6e380b Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 30 Nov 2018 17:04:02 +1300 Subject: Refactor script some more --- watch-git-tags | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/watch-git-tags b/watch-git-tags index e7d2c59..b2b1fa8 100755 --- a/watch-git-tags +++ b/watch-git-tags @@ -2,14 +2,14 @@ self=watch-git-tags # List sorted local tags -local_tags() { +tags_local() { for repo ; do git -C "$repo" tag --list | LC_COLLATE=C sort done } # List sorted remote tags -remote_tags() { +tags_remote() { for repo ; do git -C "$repo" ls-remote --quiet --refs --tags || printf >&2 'Failed to retrieve tags for repository %s\n' "$PWD" @@ -39,25 +39,25 @@ done for repo ; do ( # Make a temporary directory with a hash in its name for uniqueness - df=$(printf %s "$repo" | sed s:/:_:g) - cs=$(printf %s "$repo" | cksum) - sd=$td/$df.${cs%% *} - mkdir -- "$sd" || exit + 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 - local_tags "$repo" > "$sd"/a || exit - remote_tags "$repo" > "$sd"/b || exit + tags_local "$repo" > tags/local || exit + tags_remote "$repo" > tags/remote || exit # Write new tags to file - LC_COLLATE=C comm -13 -- [ab] > new + 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 new ] || continue + [ -s tags/new ] || continue git -C "$repo" fetch --quiet --tags ) & done @@ -67,13 +67,19 @@ wait # Iterate through the temp dirs in order for dir in "$td"/* ; do ( - cd -- "$dir" || exit 0 + cd -- "$dir" || exit # Look for non-zero "new" files (at least one new tag) - [ -s new ] || exit 0 + [ -s tags/new ] || exit # Print repository path and new tags - sed '1!s/^/\t/' -- path new - exit 1 + 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 -- cgit v1.2.3 From d4819eab1eb9429f2f5033f840db98f152c29736 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 30 Nov 2018 17:04:47 +1300 Subject: Remove unused $self variable --- watch-git-tags | 1 - 1 file changed, 1 deletion(-) diff --git a/watch-git-tags b/watch-git-tags index b2b1fa8..890fa9e 100755 --- a/watch-git-tags +++ b/watch-git-tags @@ -1,5 +1,4 @@ #!/bin/sh -self=watch-git-tags # List sorted local tags tags_local() { -- cgit v1.2.3 From 3c92ae0d570556eceae352faca5469d00989db7c Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 30 Nov 2018 17:04:56 +1300 Subject: Use correct control structure for loop body exit --- watch-git-tags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-git-tags b/watch-git-tags index 890fa9e..b9fdce8 100755 --- a/watch-git-tags +++ b/watch-git-tags @@ -56,7 +56,7 @@ for repo ; do ( # Attempt to quietly fetch new tags so that we don't notify about the same # ones next time - [ -s tags/new ] || continue + [ -s tags/new ] || exit git -C "$repo" fetch --quiet --tags ) & done -- cgit v1.2.3 From 7fb468b76d0a503897f492a98e9b9f7f238c6a50 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 30 Nov 2018 17:10:20 +1300 Subject: Add Makefile and manual page --- .gitignore | 1 + Makefile | 14 ++++++++-- watch-git-tags | 84 ------------------------------------------------------- watch-git-tags.1 | 13 +++++++++ watch-git-tags.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 86 deletions(-) create mode 100644 .gitignore delete mode 100755 watch-git-tags create mode 100644 watch-git-tags.1 create mode 100644 watch-git-tags.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02a5345 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +watch-git-tags diff --git a/Makefile b/Makefile index 90bfa3b..acf1ab8 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,18 @@ .SUFFIXES: .PHONY: all install clean PREFIX = /usr/local -all: -install: +ALL = watch-git-tags +all: $(ALL) +watch-git-tags: watch-git-tags.sh + command -pv sh | sed 's_^_#!_' > $@ + cat watch-git-tags.sh >> $@ + chmod +x ./$@ +install: install-bin install-man +install-bin: mkdir -p -- $(PREFIX)/bin cp -- watch-git-tags $(PREFIX)/bin +install-man: + mkdir -p -- $(PREFIX)/share/man/man1 + cp -- watch-git-tags.1 $(PREFIX)/share/man/man1 clean: + rm -f -- $(ALL) diff --git a/watch-git-tags b/watch-git-tags deleted file mode 100755 index b9fdce8..0000000 --- a/watch-git-tags +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh - -# List sorted local tags -tags_local() { - for repo ; do - git -C "$repo" tag --list | LC_COLLATE=C sort - done -} - -# List sorted remote tags -tags_remote() { - for repo ; do - git -C "$repo" ls-remote --quiet --refs --tags || - printf >&2 'Failed to retrieve tags for repository %s\n' "$PWD" - done | - 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 -[ "$#" -gt 0 ] || set -- . - -# 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 diff --git a/watch-git-tags.1 b/watch-git-tags.1 new file mode 100644 index 0000000..70c9dc4 --- /dev/null +++ b/watch-git-tags.1 @@ -0,0 +1,13 @@ +.TH WATCH-GIT-TAGS 1 "November 2018" "Manual page for watch-git-tags" +.SH NAME +.B watch-git-tags +\- list and fetch new remote tags +.SH SYNOPSIS +.B watch-git-tags +[REPO...] +.SH DESCRIPTION +List new remote tags for each of the named Git repositories, defaulting to the +current directory, and then fetch them. Fetches in parallel over the repository +list. +.SH AUTHOR +Tom Ryder diff --git a/watch-git-tags.sh b/watch-git-tags.sh new file mode 100644 index 0000000..b9fdce8 --- /dev/null +++ b/watch-git-tags.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# List sorted local tags +tags_local() { + for repo ; do + git -C "$repo" tag --list | LC_COLLATE=C sort + done +} + +# List sorted remote tags +tags_remote() { + for repo ; do + git -C "$repo" ls-remote --quiet --refs --tags || + printf >&2 'Failed to retrieve tags for repository %s\n' "$PWD" + done | + 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 +[ "$#" -gt 0 ] || set -- . + +# 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 -- cgit v1.2.3 From 85dc6dd47f279aafd69b93aec91cf209c42e7aa7 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:40:13 +1300 Subject: Refactor Makefile for more generality --- Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index acf1ab8..8801108 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ .POSIX: .SUFFIXES: -.PHONY: all install clean +.SUFFIXES: .sh +.PHONY: all install install-bin install-man clean PREFIX = /usr/local ALL = watch-git-tags -all: $(ALL) -watch-git-tags: watch-git-tags.sh - command -pv sh | sed 's_^_#!_' > $@ - cat watch-git-tags.sh >> $@ +SH = /bin/sh +.sh: + { printf '#!%s\n\n' $(SH) ; cat $< ; } > $@ chmod +x ./$@ +all: $(ALL) install: install-bin install-man install-bin: mkdir -p -- $(PREFIX)/bin -- cgit v1.2.3 From 786702e3f1fc9aee755b539cfa633fdc061866bf Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:40:33 +1300 Subject: Refactor tag generation functions --- watch-git-tags.sh | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/watch-git-tags.sh b/watch-git-tags.sh index b9fdce8..857fbd0 100644 --- a/watch-git-tags.sh +++ b/watch-git-tags.sh @@ -1,18 +1,10 @@ -#!/bin/sh - -# List sorted local tags -tags_local() { - for repo ; do - git -C "$repo" tag --list | LC_COLLATE=C sort - done -} - -# List sorted remote tags -tags_remote() { - for repo ; do - git -C "$repo" ls-remote --quiet --refs --tags || - printf >&2 'Failed to retrieve tags for repository %s\n' "$PWD" - done | +# Function to retrieve and filter tag names +tags() { + case $1 in + remote) git -C "$repo" show-ref --tags ;; + local) git -C "$repo" ls-remote --quiet --refs --tags ;; + *) return 2 ;; + esac | while read -r _ tag ; do tag=${tag#refs/tags/} printf '%s\n' "$tag" @@ -48,8 +40,8 @@ for repo ; do ( 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 + 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 -- cgit v1.2.3 From ae895daf7ec5240300bd87a7157419ce586d9a72 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:52:19 +1300 Subject: Correct/adjust default behaviour with no args --- watch-git-tags.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/watch-git-tags.sh b/watch-git-tags.sh index 857fbd0..ba63f1c 100644 --- a/watch-git-tags.sh +++ b/watch-git-tags.sh @@ -24,7 +24,9 @@ for sig in EXIT HUP INT TERM ; do done # Use current directory if no other arguments -[ "$#" -gt 0 ] || set -- . +if [ "$#" -eq 0 ] ; then + set -- "$PWD" +fi # Iterate through each repo in a subshell in parallel for repo ; do ( -- cgit v1.2.3 From 51fe73814a5aa27cbeac1df6f5a7f0db493d0e88 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:53:43 +1300 Subject: Remove unneeded semicolon --- watch-git-tags.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch-git-tags.sh b/watch-git-tags.sh index ba63f1c..7dabb71 100644 --- a/watch-git-tags.sh +++ b/watch-git-tags.sh @@ -29,7 +29,7 @@ if [ "$#" -eq 0 ] ; then fi # Iterate through each repo in a subshell in parallel -for repo ; do ( +for repo do ( # Make a temporary directory with a hash in its name for uniqueness name=$(printf '%s' "$repo" | sed 's:/:_:g') -- cgit v1.2.3 From b4c295ebb2ea54c4187795c7a9987e2b31b33bb9 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:58:18 +1300 Subject: Correct subcommands for tags generation function I got them around the wrong way... --- watch-git-tags.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/watch-git-tags.sh b/watch-git-tags.sh index 7dabb71..f8d4265 100644 --- a/watch-git-tags.sh +++ b/watch-git-tags.sh @@ -1,8 +1,8 @@ # Function to retrieve and filter tag names tags() { case $1 in - remote) git -C "$repo" show-ref --tags ;; - local) git -C "$repo" ls-remote --quiet --refs --tags ;; + local) git -C "${2:-.}" show-ref --tags ;; + remote) git -C "${2:-.}" ls-remote --quiet --refs --tags ;; *) return 2 ;; esac | while read -r _ tag ; do -- cgit v1.2.3 From 81aead42acb04033ab793d5b4277d97db84199db Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 6 Dec 2018 14:59:32 +1300 Subject: Bump VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fd2a018..fcdb2e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0 +4.0.0 -- cgit v1.2.3