fast-import: Fix crash when referencing already existing objects
[gitweb.git] / git-fetch.sh
index b04bd553f86213478a36f8ec2f19476f02ccf09f..0e05cf1195737d2c7afc4b9447d7b4105908bf77 100755 (executable)
@@ -177,9 +177,34 @@ fetch_all_at_once () {
            git-bundle unbundle "$remote" $rref ||
            echo failed "$remote"
        else
-         git-fetch-pack --thin $exec $keep $shallow_depth \
-             $quiet $no_progress "$remote" $rref ||
-         echo failed "$remote"
+               if      test -d "$remote" &&
+
+                       # The remote might be our alternate.  With
+                       # this optimization we will bypass fetch-pack
+                       # altogether, which means we cannot be doing
+                       # the shallow stuff at all.
+                       test ! -f "$GIT_DIR/shallow" &&
+                       test -z "$shallow_depth" &&
+
+                       # See if all of what we are going to fetch are
+                       # connected to our repository's tips, in which
+                       # case we do not have to do any fetch.
+                       theirs=$(echo "$ls_remote_result" | \
+                               git-fetch--tool -s pick-rref "$rref" "-") &&
+
+                       # This will barf when $theirs reach an object that
+                       # we do not have in our repository.  Otherwise,
+                       # we already have everything the fetch would bring in.
+                       git-rev-list --objects $theirs --not --all \
+                               >/dev/null 2>/dev/null
+               then
+                       echo "$ls_remote_result" | \
+                               git-fetch--tool pick-rref "$rref" "-"
+               else
+                       git-fetch-pack --thin $exec $keep $shallow_depth \
+                               $quiet $no_progress "$remote" $rref ||
+                       echo failed "$remote"
+               fi
        fi
       ) |
       (
@@ -239,16 +264,8 @@ fetch_per_ref () {
          fi
 
          # Find $remote_name from ls-remote output.
-         head=$(
-               IFS='   '
-               echo "$ls_remote_result" |
-               while read sha1 name
-               do
-                       test "z$name" = "z$remote_name" || continue
-                       echo "$sha1"
-                       break
-               done
-         )
+         head=$(echo "$ls_remote_result" | \
+               git-fetch--tool -s pick-rref "$remote_name" "-")
          expr "z$head" : "z$_x40\$" >/dev/null ||
                die "No such ref $remote_name at $remote"
          echo >&2 "Fetching $remote_name from $remote using $proto"