summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2005-09-17 18:56:41 (GMT)
committerJunio C Hamano <junkio@cox.net>2005-09-17 18:56:41 (GMT)
commit4447badcd22a889d656192803eff1003602839c5 (patch)
tree6194c273a13907fea9bb5df76e681bec1c9df462
parent8805ccac40348094d26b3b892c6ca3d08dc12ae0 (diff)
downloadgit-4447badcd22a889d656192803eff1003602839c5.zip
git-4447badcd22a889d656192803eff1003602839c5.tar.gz
git-4447badcd22a889d656192803eff1003602839c5.tar.bz2
Teach rsync transport about alternates.
For local operations and downloading and uploading via git aware protocols, use of $GIT_OBJECT_DIRECTORY/info/alternates is recommended on the server side for big projects that are derived from another one (like Linux kernel). However, dumb protocols and rsync transport needs to resolve this on the client end, which we did not bother doing until this week. I noticed we use "rsync -z" but most of our payload is already compressed, which was not quite right. This commit also fixes it. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rwxr-xr-xgit-clone.sh28
-rwxr-xr-xgit-fetch.sh24
-rwxr-xr-xgit-parse-remote.sh21
3 files changed, 68 insertions, 5 deletions
diff --git a/git-clone.sh b/git-clone.sh
index a21f13a..bfb8fd6 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -144,8 +144,32 @@ yes,yes)
*)
case "$repo" in
rsync://*)
- rsync $quiet -avz --ignore-existing "$repo/objects/" "$D/.git/objects/" &&
- rsync $quiet -avz --ignore-existing "$repo/refs/" "$D/.git/refs/"
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$repo/objects/" "$D/.git/objects/" &&
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$repo/refs/" "$D/.git/refs/" || exit
+
+ # Look at objects/info/alternates for rsync -- http will
+ # support it natively and git native ones will do it on the
+ # remote end. Not having that file is not a crime.
+ rsync -q "$repo/objects/info/alternates" "$D/.git/TMP_ALT" ||
+ rm -f "$D/.git/TMP_ALT"
+ if test -f "$D/.git/TMP_ALT"
+ then
+ ( cd $D &&
+ . git-parse-remote &&
+ resolve_alternates "$repo" <"./.git/TMP_ALT" ) |
+ while read alt
+ do
+ case "$alt" in 'bad alternate: '*) die "$alt";; esac
+ case "$quiet" in
+ '') echo >&2 "Getting alternate: $alt" ;;
+ esac
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$alt" "$D/.git/objects" || exit
+ done
+ rm -f "$D/.git/TMP_ALT"
+ fi
;;
http://*)
clone_dumb_http "$repo" "$D"
diff --git a/git-fetch.sh b/git-fetch.sh
index 2273944..72f17ab 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -183,12 +183,30 @@ do
;;
rsync://*)
TMP_HEAD="$GIT_DIR/TMP_HEAD"
- rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
+ rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
head=$(git-rev-parse TMP_HEAD)
rm -f "$TMP_HEAD"
test "$rsync_slurped_objects" || {
- rsync -avz --ignore-existing "$remote/objects/" \
- "$GIT_OBJECT_DIRECTORY/" || exit
+ rsync -av --ignore-existing --exclude info \
+ "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
+
+ # Look at objects/info/alternates for rsync -- http will
+ # support it natively and git native ones will do it on the remote
+ # end. Not having that file is not a crime.
+ rsync -q "$remote/objects/info/alternates" "$GIT_DIR/TMP_ALT" ||
+ rm -f "$GIT_DIR/TMP_ALT"
+ if test -f "$GIT_DIR/TMP_ALT"
+ then
+ resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
+ while read alt
+ do
+ case "$alt" in 'bad alternate: '*) die "$alt";; esac
+ echo >&2 "Getting alternate: $alt"
+ rsync -av --ignore-existing --exclude info \
+ "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
+ done
+ rm -f "$GIT_DIR/TMP_ALT"
+ fi
rsync_slurped_objects=t
}
;;
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 3c5d94b..a9db0cd 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -153,3 +153,24 @@ get_remote_refs_for_fetch () {
;;
esac
}
+
+resolve_alternates () {
+ # original URL (xxx.git)
+ top_=`expr "$1" : '\([^:]*:/*[^/]*\)/'`
+ while read path
+ do
+ case "$path" in
+ \#* | '')
+ continue ;;
+ /*)
+ echo "$top_$path/" ;;
+ ../*)
+ # relative -- ugly but seems to work.
+ echo "$1/objects/$path/" ;;
+ *)
+ # exit code may not be caught by the reader.
+ echo "bad alternate: $path"
+ exit 1 ;;
+ esac
+ done
+}