The current UI around alternates is lacking. There are commands to add an alternate at the time of a clone (e.g. 'git clone --reference') but no commands to see what alternates have been configured or to add an alternate after a repository has been cloned. This patch adds a friendlier UI for displaying and configuring alternates. Signed-off-by: Chris Packham <judge.packham@xxxxxxxxx> --- Hopefully I've addressed the comments from Junio and Jonathan. I haven't tried to re-work the commands into show|add|delete as per Stephens suggestion. I have subtly changed from 'alternates' to 'alternate' i.e. ditched the plural in line with commands like 'git remote' Makefile | 1 + git-alternate.sh | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 0 deletions(-) create mode 100755 git-alternate.sh diff --git a/Makefile b/Makefile index 3a6c6ea..0dc5e42 100644 --- a/Makefile +++ b/Makefile @@ -334,6 +334,7 @@ TEST_PROGRAMS_NEED_X = unexport CDPATH SCRIPT_SH += git-am.sh +SCRIPT_SH += git-alternate.sh SCRIPT_SH += git-bisect.sh SCRIPT_SH += git-difftool--helper.sh SCRIPT_SH += git-filter-branch.sh diff --git a/git-alternate.sh b/git-alternate.sh new file mode 100755 index 0000000..827baf5 --- /dev/null +++ b/git-alternate.sh @@ -0,0 +1,155 @@ +#!/bin/sh +# +# This file is licensed under the GPL v2 +# + +OPTIONS_KEEPDASHDASH= +OPTIONS_SPEC="\ +git alternate [-r|--recursive] +git alternate [-a|--add dir] +git alternate [-f|--force] [-d|delete dir] +-- +r,recursive recursively follow alternates +a,add= add dir as an alternate +d,del= delete dir as an alternate +f,force force a delete operation +" +. git-sh-setup + +# +# Given the path in $1, which may or may not be a relative path, +# convert it to an absolute path +# +abspath() +{ + cd "$1" + pwd + cd - > /dev/null +} + +# +# Runs through the alternates file calling the callback function $1 +# with the name of the alternate as the first argument to the callback +# any additional arguments are passed to the callback function. +# +walk_alternates() +{ + alternates=$GIT_DIR/objects/info/alternates + callback=$1 + shift + + if test -f "$alternates" + then + while read line + do + $callback "$line" "$@" + done< "$alternates" + fi +} + +# +# Walk function to display one alternate object store and, if the user +# has specified -r, recursively call show_alternates on the git +# repository that the object store belongs to. +# +show_alternates_walk() +{ + say "Object store $1" + say " referenced via $GIT_DIR" + + new_git_dir=${line%%/objects} + if test "$recursive" = "true" && test "$GIT_DIR" != "$new_git_dir" + then + ( + export GIT_DIR=$new_git_dir + show_alternates + ) + fi +} + +# Display alternates currently configured +show_alternates() +{ + walk_alternates show_alternates_walk +} + +# +# Walk function to check that the specified alternate does not +# already exist. +# +check_current_alternate_walk() +{ + if test "$1" = "$2"; then + die "fatal: Object store $2 is already used by $GIT_DIR" + fi +} + +# Add a new alternate +add_alternate() +{ + if test ! -d "$dir"; then + die "fatal: $dir is not a directory" + fi + + abs_dir=$(abspath "$dir") + walk_alternates check_current_alternate_walk "$abs_dir" + + # At this point we know that $dir is a directory that exists + # and that its not already being used as an alternate. We could + # go further and verify that $dir has valid objects. + + # if we're still going we can safely add the alternate + echo "$abs_dir" >> $GIT_DIR/objects/info/alternates + say "$abs_dir added as an alternate" + say " use 'git repack -adl' to remove duplicate objects" +} + +# Deletes the name alternate from the alternates file. +# If there are no more alternates the alternates file will be removed +del_alternate() +{ + if test ! $force = "true"; then + say "Not forced, use" + say " 'git repack -a' to fetch missing objects, then " + say " '$dashless -f -d $dir' to remove the alternate" + die + fi + + alternates=$GIT_DIR/objects/info/alternates + new_alternates=$alternates.tmp + + grep -v -F "$dir" <"$alternates" >"$new_alternates" + if test -s "$new_alternates" + then + mv "$new_alternates" "$alternates" + else + # save the git from repeatedly reading a 0 length file + rm -f "$alternates" + fi +} + +dir="" +oper="" +force="false" + +# Option parsing +while test $# != 0 +do + case "$1" in + -r|--recursive) recursive="true" ;; + -a|--add) oper="add"; dir="$2"; shift ;; + -d|--delete) oper="del"; dir="$2"; shift ;; + -f|--force) force="true" ;; + --) shift; break ;; + *) usage ;; + esac + shift +done + +# Now go and do it +case "$oper" in + add) add_alternate ;; + del) del_alternate ;; + *) show_alternates ;; +esac + -- 1.7.0.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html