X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=topgit.git;a=blobdiff_plain;f=tg.sh;h=5bb2d0cd123f09b1b038b04ed3b9a17bc4495a5d;hp=7005f98c882bde7c97094862aeb88b07b28de390;hb=1930aaddd2164df67e68f0b75f38e20db44d242d;hpb=28212dd015e70eae4b2b08e5f1cb93bca2d63781 diff --git a/tg.sh b/tg.sh index 7005f98..5bb2d0c 100644 --- a/tg.sh +++ b/tg.sh @@ -63,8 +63,8 @@ measure_branch() _bname="$1"; _base="$2" [ -n "$_base" ] || _base="refs/top-bases/$_bname" # The caller should've verified $name is valid - _commits="$(git rev-list "$_bname" ^"$_base" | wc -l)" - _nmcommits="$(git rev-list --no-merges "$_bname" ^"$_base" | wc -l)" + _commits="$(git rev-list "$_bname" ^"$_base" -- | wc -l)" + _nmcommits="$(git rev-list --no-merges "$_bname" ^"$_base" -- | wc -l)" if [ $_commits -gt 1 ]; then _suffix="commits" else @@ -77,7 +77,7 @@ measure_branch() # Whether B1 is a superset of B2. branch_contains() { - [ -z "$(git rev-list ^"$1" "$2" --)" ] + [ -z "$(git rev-list --max-count=1 ^"$1" "$2" --)" ] } # ref_exists REF @@ -94,6 +94,16 @@ has_remote() [ -n "$base_remote" ] && ref_exists "remotes/$base_remote/$1" } +branch_annihilated() +{ + _name="$1"; + + # use the merge base in case the base is ahead. + mb="$(git merge-base "refs/top-bases/$_name" "$_name")"; + + test "$(git rev-parse "$mb^{tree}")" = "$(git rev-parse "$_name^{tree}")"; +} + # recurse_deps CMD NAME [BRANCHPATH...] # Recursively eval CMD on all dependencies of NAME. # CMD can refer to $_name for queried branch name, @@ -116,7 +126,12 @@ recurse_deps() if has_remote "top-bases/$_name"; then echo "refs/remotes/$base_remote/top-bases/$_name" >>"$_depsfile" fi - git cat-file blob "$_name:.topdeps" >>"$_depsfile" + + # if the branch was annihilated, there exists no .topdeps file + if ! branch_annihilated "$_name"; then + #TODO: handle nonexisting .topdeps? + git cat-file blob "$_name:.topdeps" >>"$_depsfile"; + fi; _ret=0 while read _dep; do @@ -209,6 +224,12 @@ switch_to_base() do_help() { if [ -z "$1" ] ; then + # This is currently invoked in all kinds of circumstances, + # including when the user made a usage error. Should we end up + # providing more than a short help message, then we should + # differentiate. + # Petr's comment: http://marc.info/?l=git&m=122718711327376&w=2 + ## Build available commands list for help output cmds= @@ -222,7 +243,7 @@ do_help() sep="|" done - echo "TopGit v0.4 - A different patch queue manager" + echo "TopGit v0.5 - A different patch queue manager" echo "Usage: tg [-r REMOTE] ($cmds|help) ..." elif [ -r "@cmddir@"/tg-$1 ] ; then @cmddir@/tg-$1 -h || : @@ -232,24 +253,30 @@ do_help() fi else echo "`basename $0`: no help for $1" 1>&2 + do_help + exit 1 fi } +## Startup + +[ -d "@cmddir@" ] || + die "No command directory: '@cmddir@'" + ## Initial setup set -e git_dir="$(git rev-parse --git-dir)" root_dir="$(git rev-parse --show-cdup)"; root_dir="${root_dir:-.}" +# Make sure root_dir doesn't end with a trailing slash. +root_dir="${root_dir%/}" base_remote="$(git config topgit.remote 2>/dev/null)" || : tg="tg" # make sure merging the .top* files will always behave sanely setup_ours setup_hook "pre-commit" -[ -d "@cmddir@" ] || - die "No command directory: '@cmddir@'" - ## Dispatch # We were sourced from another script for our utility functions; @@ -257,25 +284,34 @@ setup_hook "pre-commit" [ -z "$tg__include" ] || return 0 if [ "$1" = "-r" ]; then - shift; base_remote="$1"; shift + shift + if [ -z "$1" ]; then + echo "Option -r requires an argument." >&2 + do_help + exit 1 + fi + base_remote="$1"; shift tg="$tg -r $base_remote" fi cmd="$1" -[ -n "$cmd" ] || die "He took a duck in the face at two hundred and fifty knots" +[ -n "$cmd" ] || { do_help; exit 1; } shift case "$cmd" in help|--help|-h) do_help "$1" - exit 1;; + exit 0;; --hooks-path) # Internal command echo "@hooksdir@";; *) [ -r "@cmddir@"/tg-$cmd ] || { echo "Unknown subcommand: $cmd" >&2 + do_help exit 1 } . "@cmddir@"/tg-$cmd;; esac + +# vim:noet