[PATCH] First crude implementation of git-svn-externals

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

 



From: Eddy Petrisor <eddy@xxxxxxxxxxxxxxxx>

Current functionality:
 - fetches all the externals of an already svn-fetched repo
 - support for svn:externals refresh
 - if the location of the external has changed, the current working
   copy will be placed aside and a new directory will be created
   instead
 - if the remote URI is the same (maybe a verison bump, there will
   be a 'git svn rebase'
 - remove support (useful for testing purposes or clean restarts)
 - avoid zombie externals at all costs - in some repos empty
   svn:externals might exist; svn ignores such externals, so git should
   do the same

TODO:
 - take into account the revision of an external, if it exists
 - do not do deep svn cloning, to avoid legthy operations, just pull HEAD
 - add shallow copies to git svn repos (one revision should be enough
   for most externals)
 - use submodules for externals
---
 .gitignore           |    1 +
 Makefile             |    1 +
 git-svn-externals.sh |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100755 git-svn-externals.sh

diff --git a/.gitignore b/.gitignore
index bbaf9de..cd2c47d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -123,6 +123,7 @@ git-status
 git-stripspace
 git-submodule
 git-svn
+git-svn-externals
 git-symbolic-ref
 git-tag
 git-tar-tree
diff --git a/Makefile b/Makefile
index bf400e6..b130244 100644
--- a/Makefile
+++ b/Makefile
@@ -265,6 +265,7 @@ SCRIPT_SH += git-sh-setup.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
 SCRIPT_SH += git-web--browse.sh
+SCRIPT_SH += git-svn-externals.sh
 
 SCRIPT_PERL += git-add--interactive.perl
 SCRIPT_PERL += git-archimport.perl
diff --git a/git-svn-externals.sh b/git-svn-externals.sh
new file mode 100755
index 0000000..38b7af6
--- /dev/null
+++ b/git-svn-externals.sh
@@ -0,0 +1,158 @@
+#!/bin/sh
+
+set -e
+
+GIT_SVN_LAST_DIR="$(pwd)"
+trap "cd '$GIT_SVN_LAST_DIR'" INT EXIT KILL
+
+
+USAGE='[help|init|refresh|show]'
+
+LONG_USAGE='git svn externals help
+	print this long help message.
+git svn externals init [<pathspec>...]
+	pull all externals according to current repo state.
+git svn externals refresh [<pathspec>...]
+	removes current externals and repulls them.
+'
+
+
+SUBDIRECTORY_OK=Sometimes
+OPTIONS_SPEC=
+. git-sh-setup
+cd_to_toplevel
+# this should never fail
+require_work_tree
+
+
+GIT_SVN_TOP_DIR="$(pwd)"
+
+svn_revision_to_numrevision ()
+#$1 - repository URI
+#$2 - the revision to be transformed
+{
+	local REVSPEC
+	[ "$2" ] && REVSPEC="-r $2" || REVSPEC=''
+	[ "$1" ] || die "Internal error: no repository given in svn_revision_to_numrevision"
+	LANG=C svn info "$1" "$REVSPEC" | grep 'Revision' | cut -f 2 -d ':' | sed 's#^\ \ *##g'
+}
+
+prune_inital_slashes ()
+{
+	echo "$1" | sed 's#^//*##g'
+}
+
+git_svn_externals_remove ()
+{
+	local LASTDIR="$(pwd)"
+	cd_to_toplevel && TOPLEVELDIR="$(pwd)"
+	git svn show-externals | grep -vE '^(#.*|)$' | while read EXT_DIR REV EXT_SRC ; do
+		if [ -z "$REV" ] ; then
+			echo "Skipping illegal external '$EXT_DIR' which has no value" >&2
+			continue
+		fi
+		EXT_DIR="$(prune_inital_slashes "$EXT_DIR")"
+
+		if [ -z "$EXT_SRC" ] ; then
+			EXT_SRC="$REV"
+			REV="-rHEAD"
+		fi
+		REV=${REV#-r}
+
+		echo "Removing local copy for external '$EXT_DIR' ( $EXT_SRC@$REV )"
+		rm -fr "$EXT_DIR"
+	done
+
+	cd "$LASTDIR"
+}
+
+git_svn_init_dir_repo ()
+# assumes is ran from the parent dir of the repo
+# $1 EXT_DIR
+# $2 EXT_SRC
+# $3 REV
+{
+	local LASTDIR="$(pwd)"
+
+	mkdir -p "$1"
+	cd "$1"
+	git svn init "$2"
+	git svn fetch
+
+	cd "$LASTDIR"
+}
+
+git_svn_externals_refresh_external ()
+#$1 directory where the external is locally
+#$2 remote url
+#$3 revision at which the external is pinned at
+{
+	local LASTDIR="$GIT_SVN_TOP_DIR"
+
+	local EXT_SRC="$2"
+	local EXT_DIR="$1"
+
+	if cd "$EXT_DIR" 2>/dev/null; then
+		local OLDDIREXISTS=yes
+		local OLD_EXT_SRC=$(git config --get svn-remote.svn.url)
+		local OLD_EXT_REV=$(git config --get svn-remote.svn.revision || svn_revision_to_numrevision $OLD_EXT_SRC HEAD)
+		cd -
+	else
+		local OLDDIREXISTS=no
+		local OLD_EXT_SRC="${EXT_SRC}"
+		local OLD_EXT_REV=$(svn_revision_to_numrevision $EXT_SRC HEAD)
+	fi
+
+	if [ "$OLD_EXT_SRC" != "$EXT_SRC" ] ; then
+		echo "External URI definition changed. Moving away the old repo and pulling a new one."
+		cd "$LASTDIR"
+		local SUBDIR="$(basename "$EXT_DIR")"
+		local DIRNAME="$(dirname "$EXT_DIR")"
+		NEWDIR="$(mktemp -p "$DIRNAME" "$SUBDIR.obsolete.XXXXXX")" && rm -f "$NEWDIR"
+		mv "$EXT_DIR" "$NEWDIR"
+		echo "  Old copy moved to '$NEWDIR'."
+		git_svn_init_dir_repo "$EXT_DIR" "$EXT_SRC" "$REV"
+	elif [ "$OLDDIREXISTS" = "no" ] ; then
+		git_svn_init_dir_repo "$EXT_DIR" "$EXT_SRC" "$REV"
+	else
+		cd "$EXT_DIR"
+		git svn rebase
+	fi
+
+	cd "$LASTDIR"
+	return 0
+}
+
+git_svn_externals_refresh ()
+{
+	git svn show-externals | grep -vE '^(#.*|)$' | while read EXT_DIR REV EXT_SRC ; do
+		if [ -z "$REV" ] ; then
+			echo "Skipping illegal external '$EXT_DIR' which has no value" >&2
+			continue
+		fi
+		EXT_DIR="$(prune_inital_slashes "$EXT_DIR")"
+
+		if [ -z "$EXT_SRC" ] ; then
+			EXT_SRC="$REV"
+			REV="-rHEAD"
+		fi
+		REV=${REV#-r}
+
+		echo "Refreshing local copy for external '$EXT_DIR' ( $EXT_SRC@$REV )"
+		cd "$GIT_SVN_TOP_DIR"
+		git_svn_externals_refresh_external "$EXT_DIR" "$EXT_SRC" "$REV"
+	done
+
+	cd "$GIT_SVN_TOP_DIR"
+}
+
+
+case $1 in
+	--remove)
+		git_svn_externals_remove
+		;;
+	-r|--refresh|*)
+		git_svn_externals_refresh
+		;;
+esac
+
-- 
1.5.6.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]

  Powered by Linux