Code

Teach rsync transport about alternates.
authorJunio C Hamano <junkio@cox.net>
Sat, 17 Sep 2005 18:56:41 +0000 (11:56 -0700)
committerJunio C Hamano <junkio@cox.net>
Sat, 17 Sep 2005 18:56:41 +0000 (11:56 -0700)
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>
git-clone.sh
git-fetch.sh
git-parse-remote.sh

index a21f13af2ab1ea54db3b8919a5fbb00c5bb59bf4..bfb8fd628536c5bbb08c9d07c7e93455cd253650 100755 (executable)
@@ -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"
index 22739440384648357896898f11001e2fa05f217e..72f17ab6c9fab567b236e5f2656515df40d98adc 100755 (executable)
@@ -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
        }
        ;;
index 3c5d94b344b31d69b42bcb75d718dd23d01be542..a9db0cd82558af9bebec083450b35348a1d0b29a 100755 (executable)
@@ -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
+}