apply: allow-binary-replacement.
[gitweb.git] / git-clone.sh
index a21f13af2ab1ea54db3b8919a5fbb00c5bb59bf4..c09979a7a49e36b35e333b902cb0e0d689b693f4 100755 (executable)
@@ -9,7 +9,7 @@
 unset CDPATH
 
 usage() {
-       echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] <repo> <dir>"
+       echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> [<dir>]"
        exit 1
 }
 
@@ -23,7 +23,7 @@ fi
 
 http_fetch () {
        # $1 = Remote, $2 = Local
-       curl -nsf $curl_extra_args "$1" >"$2"
+       curl -nsfL $curl_extra_args "$1" >"$2"
 }
 
 clone_dumb_http () {
@@ -53,7 +53,11 @@ Perhaps git-update-server-info needs to be run there?"
        while read sha1 refname
        do
                name=`expr "$refname" : 'refs/\(.*\)'` &&
-               git-http-fetch -v -a -w "$name" "$name" "$1/" || exit 1
+               case "$name" in
+               *^*)    ;;
+               *)
+                       git-http-fetch -v -a -w "$name" "$name" "$1/" || exit 1
+               esac
        done <"$clone_tmp/refs"
        rm -fr "$clone_tmp"
 }
@@ -61,10 +65,12 @@ Perhaps git-update-server-info needs to be run there?"
 quiet=
 use_local=no
 local_shared=no
+no_checkout=
 upload_pack=
 while
        case "$#,$1" in
        0,*) break ;;
+       *,-n) no_checkout=yes ;;
        *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
         *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) 
           local_shared=yes ;;
@@ -90,7 +96,10 @@ if base=$(get_repo_base "$repo"); then
 fi
 
 dir="$2"
-mkdir "$dir" &&
+# Try using "humanish" part of source repo if user didn't specify one
+[ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*/||g')
+[ -e "$dir" ] && echo "$dir already exists." && usage
+mkdir -p "$dir" &&
 D=$(
        (cd "$dir" && git-init-db && pwd)
 ) &&
@@ -120,8 +129,7 @@ yes,yes)
            fi &&
            rm -f "$D/.git/objects/sample" &&
            cd "$repo" &&
-           find objects -type f -print |
-           cpio -puamd$l "$D/.git/" || exit 1
+           find objects -depth -print | cpio -puamd$l "$D/.git/" || exit 1
            ;;
        yes)
            mkdir -p "$D/.git/objects/info"
@@ -139,13 +147,39 @@ yes,yes)
        then
                HEAD=HEAD
        fi
-       tar Ccf "$repo" - refs $HEAD | tar Cxf "$D/.git" - || exit 1
+       (cd "$repo" && tar cf - refs $HEAD) |
+       (cd "$D/.git" && tar xf -) || exit 1
        ;;
 *)
        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" 2>/dev/null ||
+                       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"
@@ -160,9 +194,31 @@ yes,yes)
        ;;
 esac
 
-# Update origin.
-mkdir -p "$D/.git/remotes/" &&
-rm -f "$D/.git/remotes/origin" &&
-echo >"$D/.git/remotes/origin" \
-"URL: $repo
-Pull: master:origin"
+cd "$D" || exit
+
+if test -f ".git/HEAD"
+then
+       head_points_at=`git-symbolic-ref HEAD`
+       case "$head_points_at" in
+       refs/heads/*)
+               head_points_at=`expr "$head_points_at" : 'refs/heads/\(.*\)'`
+               mkdir -p .git/remotes &&
+               echo >.git/remotes/origin \
+               "URL: $repo
+Pull: $head_points_at:origin" &&
+               cp ".git/refs/heads/$head_points_at" .git/refs/heads/origin &&
+               find .git/refs/heads -type f -print |
+               while read ref
+               do
+                       head=`expr "$ref" : '.git/refs/heads/\(.*\)'` &&
+                       test "$head_points_at" = "$head" ||
+                       test "origin" = "$head" ||
+                       echo "Pull: ${head}:${head}"
+               done >>.git/remotes/origin
+       esac
+
+       case "$no_checkout" in
+       '')
+               git checkout
+       esac
+fi