[PATCHv2 1/2] Add git alternate command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]