git-fetch.shon commit Merge branch 'ap/branch' (9b2c681)
   1#!/bin/sh
   2#
   3
   4USAGE='<fetch-options> <repository> <refspec>...'
   5. git-sh-setup
   6. git-parse-remote
   7_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
   8_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
   9
  10LF='
  11'
  12IFS="$LF"
  13
  14rloga=fetch
  15no_tags=
  16tags=
  17append=
  18force=
  19verbose=
  20update_head_ok=
  21exec=
  22upload_pack=
  23keep=
  24while case "$#" in 0) break ;; esac
  25do
  26        case "$1" in
  27        -a|--a|--ap|--app|--appe|--appen|--append)
  28                append=t
  29                ;;
  30        --upl|--uplo|--uploa|--upload|--upload-|--upload-p|\
  31        --upload-pa|--upload-pac|--upload-pack)
  32                shift
  33                exec="--exec=$1" 
  34                upload_pack="-u $1"
  35                ;;
  36        -f|--f|--fo|--for|--forc|--force)
  37                force=t
  38                ;;
  39        -t|--t|--ta|--tag|--tags)
  40                tags=t
  41                ;;
  42        -n|--n|--no|--no-|--no-t|--no-ta|--no-tag|--no-tags)
  43                no_tags=t
  44                ;;
  45        -u|--u|--up|--upd|--upda|--updat|--update|--update-|--update-h|\
  46        --update-he|--update-hea|--update-head|--update-head-|\
  47        --update-head-o|--update-head-ok)
  48                update_head_ok=t
  49                ;;
  50        -v|--verbose)
  51                verbose=Yes
  52                ;;
  53        -k|--k|--ke|--kee|--keep)
  54                keep='-k -k'
  55                ;;
  56        --reflog-action=*)
  57                rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
  58                ;;
  59        -*)
  60                usage
  61                ;;
  62        *)
  63                break
  64                ;;
  65        esac
  66        shift
  67done
  68
  69case "$#" in
  700)
  71        origin=$(get_default_remote)
  72        test -n "$(get_remote_url ${origin})" ||
  73                die "Where do you want to fetch from today?"
  74        set x $origin ; shift ;;
  75esac
  76
  77remote_nick="$1"
  78remote=$(get_remote_url "$@")
  79refs=
  80rref=
  81rsync_slurped_objects=
  82
  83rloga="$rloga $remote_nick"
  84test "$remote_nick" = "$remote" || rloga="$rloga $remote"
  85
  86if test "" = "$append"
  87then
  88        : >"$GIT_DIR/FETCH_HEAD"
  89fi
  90
  91# Global that is reused later
  92ls_remote_result=$(git ls-remote $upload_pack "$remote") ||
  93        die "Cannot find the reflist at $remote"
  94
  95append_fetch_head () {
  96    head_="$1"
  97    remote_="$2"
  98    remote_name_="$3"
  99    remote_nick_="$4"
 100    local_name_="$5"
 101    case "$6" in
 102    t) not_for_merge_='not-for-merge' ;;
 103    '') not_for_merge_= ;;
 104    esac
 105
 106    # remote-nick is the URL given on the command line (or a shorthand)
 107    # remote-name is the $GIT_DIR relative refs/ path we computed
 108    # for this refspec.
 109
 110    # the $note_ variable will be fed to git-fmt-merge-msg for further
 111    # processing.
 112    case "$remote_name_" in
 113    HEAD)
 114        note_= ;;
 115    refs/heads/*)
 116        note_="$(expr "$remote_name_" : 'refs/heads/\(.*\)')"
 117        note_="branch '$note_' of " ;;
 118    refs/tags/*)
 119        note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
 120        note_="tag '$note_' of " ;;
 121    refs/remotes/*)
 122        note_="$(expr "$remote_name_" : 'refs/remotes/\(.*\)')"
 123        note_="remote branch '$note_' of " ;;
 124    *)
 125        note_="$remote_name of " ;;
 126    esac
 127    remote_1_=$(expr "z$remote_" : 'z\(.*\)\.git/*$') &&
 128        remote_="$remote_1_"
 129    note_="$note_$remote_"
 130
 131    # 2.6.11-tree tag would not be happy to be fed to resolve.
 132    if git-cat-file commit "$head_" >/dev/null 2>&1
 133    then
 134        headc_=$(git-rev-parse --verify "$head_^0") || exit
 135        echo "$headc_   $not_for_merge_ $note_" >>"$GIT_DIR/FETCH_HEAD"
 136    else
 137        echo "$head_    not-for-merge   $note_" >>"$GIT_DIR/FETCH_HEAD"
 138    fi
 139
 140    update_local_ref "$local_name_" "$head_" "$note_"
 141}
 142
 143update_local_ref () {
 144    # If we are storing the head locally make sure that it is
 145    # a fast forward (aka "reverse push").
 146
 147    label_=$(git-cat-file -t $2)
 148    newshort_=$(git-rev-parse --short $2)
 149    if test -z "$1" ; then
 150        [ "$verbose" ] && echo >&2 "* fetched $3"
 151        [ "$verbose" ] && echo >&2 "  $label_: $newshort_"
 152        return 0
 153    fi
 154    oldshort_=$(git show-ref --hash --abbrev "$1" 2>/dev/null)
 155
 156    case "$1" in
 157    refs/tags/*)
 158        # Tags need not be pointing at commits so there
 159        # is no way to guarantee "fast-forward" anyway.
 160        if test -n "$oldshort_"
 161        then
 162                if now_=$(git show-ref --hash "$1") && test "$now_" = "$2"
 163                then
 164                        [ "$verbose" ] && echo >&2 "* $1: same as $3"
 165                        [ "$verbose" ] && echo >&2 "  $label_: $newshort_" ||:
 166                else
 167                        echo >&2 "* $1: updating with $3"
 168                        echo >&2 "  $label_: $newshort_"
 169                        git-update-ref -m "$rloga: updating tag" "$1" "$2"
 170                fi
 171        else
 172                echo >&2 "* $1: storing $3"
 173                echo >&2 "  $label_: $newshort_"
 174                git-update-ref -m "$rloga: storing tag" "$1" "$2"
 175        fi
 176        ;;
 177
 178    refs/heads/* | refs/remotes/*)
 179        # $1 is the ref being updated.
 180        # $2 is the new value for the ref.
 181        local=$(git-rev-parse --verify "$1^0" 2>/dev/null)
 182        if test "$local"
 183        then
 184            # Require fast-forward.
 185            mb=$(git-merge-base "$local" "$2") &&
 186            case "$2,$mb" in
 187            $local,*)
 188                if test -n "$verbose"
 189                then
 190                        echo >&2 "* $1: same as $3"
 191                        echo >&2 "  $label_: $newshort_"
 192                fi
 193                ;;
 194            *,$local)
 195                echo >&2 "* $1: fast forward to $3"
 196                echo >&2 "  old..new: $oldshort_..$newshort_"
 197                git-update-ref -m "$rloga: fast-forward" "$1" "$2" "$local"
 198                ;;
 199            *)
 200                false
 201                ;;
 202            esac || {
 203                case ",$force,$single_force," in
 204                *,t,*)
 205                        echo >&2 "* $1: forcing update to non-fast forward $3"
 206                        echo >&2 "  old...new: $oldshort_...$newshort_"
 207                        git-update-ref -m "$rloga: forced-update" "$1" "$2" "$local"
 208                        ;;
 209                *)
 210                        echo >&2 "* $1: not updating to non-fast forward $3"
 211                        echo >&2 "  old...new: $oldshort_...$newshort_"
 212                        exit 1
 213                        ;;
 214                esac
 215            }
 216        else
 217            echo >&2 "* $1: storing $3"
 218            echo >&2 "  $label_: $newshort_"
 219            git-update-ref -m "$rloga: storing head" "$1" "$2"
 220        fi
 221        ;;
 222    esac
 223}
 224
 225case "$update_head_ok" in
 226'')
 227        orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 228        ;;
 229esac
 230
 231# If --tags (and later --heads or --all) is specified, then we are
 232# not talking about defaults stored in Pull: line of remotes or
 233# branches file, and just fetch those and refspecs explicitly given.
 234# Otherwise we do what we always did.
 235
 236reflist=$(get_remote_refs_for_fetch "$@")
 237if test "$tags"
 238then
 239        taglist=`IFS="  " &&
 240                  echo "$ls_remote_result" |
 241                  while read sha1 name
 242                  do
 243                        case "$sha1" in
 244                        fail)
 245                                exit 1
 246                        esac
 247                        case "$name" in
 248                        *^*) continue ;;
 249                        refs/tags/*) ;;
 250                        *) continue ;;
 251                        esac
 252                        if git-check-ref-format "$name"
 253                        then
 254                            echo ".${name}:${name}"
 255                        else
 256                            echo >&2 "warning: tag ${name} ignored"
 257                        fi
 258                  done` || exit
 259        if test "$#" -gt 1
 260        then
 261                # remote URL plus explicit refspecs; we need to merge them.
 262                reflist="$reflist$LF$taglist"
 263        else
 264                # No explicit refspecs; fetch tags only.
 265                reflist=$taglist
 266        fi
 267fi
 268
 269fetch_main () {
 270  reflist="$1"
 271  refs=
 272  rref=
 273
 274  for ref in $reflist
 275  do
 276      refs="$refs$LF$ref"
 277
 278      # These are relative path from $GIT_DIR, typically starting at refs/
 279      # but may be HEAD
 280      if expr "z$ref" : 'z\.' >/dev/null
 281      then
 282          not_for_merge=t
 283          ref=$(expr "z$ref" : 'z\.\(.*\)')
 284      else
 285          not_for_merge=
 286      fi
 287      if expr "z$ref" : 'z+' >/dev/null
 288      then
 289          single_force=t
 290          ref=$(expr "z$ref" : 'z+\(.*\)')
 291      else
 292          single_force=
 293      fi
 294      remote_name=$(expr "z$ref" : 'z\([^:]*\):')
 295      local_name=$(expr "z$ref" : 'z[^:]*:\(.*\)')
 296
 297      rref="$rref$LF$remote_name"
 298
 299      # There are transports that can fetch only one head at a time...
 300      case "$remote" in
 301      http://* | https://* | ftp://*)
 302          proto=`expr "$remote" : '\([^:]*\):'`
 303          if [ -n "$GIT_SSL_NO_VERIFY" ]; then
 304              curl_extra_args="-k"
 305          fi
 306          if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
 307                "`git-repo-config --bool http.noEPSV`" = true ]; then
 308              noepsv_opt="--disable-epsv"
 309          fi
 310
 311          # Find $remote_name from ls-remote output.
 312          head=$(
 313                IFS='   '
 314                echo "$ls_remote_result" |
 315                while read sha1 name
 316                do
 317                        test "z$name" = "z$remote_name" || continue
 318                        echo "$sha1"
 319                        break
 320                done
 321          )
 322          expr "z$head" : "z$_x40\$" >/dev/null ||
 323                die "No such ref $remote_name at $remote"
 324          echo >&2 "Fetching $remote_name from $remote using $proto"
 325          git-http-fetch -v -a "$head" "$remote/" || exit
 326          ;;
 327      rsync://*)
 328          TMP_HEAD="$GIT_DIR/TMP_HEAD"
 329          rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
 330          head=$(git-rev-parse --verify TMP_HEAD)
 331          rm -f "$TMP_HEAD"
 332          test "$rsync_slurped_objects" || {
 333              rsync -av --ignore-existing --exclude info \
 334                  "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
 335
 336              # Look at objects/info/alternates for rsync -- http will
 337              # support it natively and git native ones will do it on
 338              # the remote end.  Not having that file is not a crime.
 339              rsync -q "$remote/objects/info/alternates" \
 340                  "$GIT_DIR/TMP_ALT" 2>/dev/null ||
 341                  rm -f "$GIT_DIR/TMP_ALT"
 342              if test -f "$GIT_DIR/TMP_ALT"
 343              then
 344                  resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
 345                  while read alt
 346                  do
 347                      case "$alt" in 'bad alternate: '*) die "$alt";; esac
 348                      echo >&2 "Getting alternate: $alt"
 349                      rsync -av --ignore-existing --exclude info \
 350                      "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
 351                  done
 352                  rm -f "$GIT_DIR/TMP_ALT"
 353              fi
 354              rsync_slurped_objects=t
 355          }
 356          ;;
 357      *)
 358          # We will do git native transport with just one call later.
 359          continue ;;
 360      esac
 361
 362      append_fetch_head "$head" "$remote" \
 363          "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit
 364
 365  done
 366
 367  case "$remote" in
 368  http://* | https://* | ftp://* | rsync://* )
 369      ;; # we are already done.
 370  *)
 371    ( : subshell because we muck with IFS
 372      pack_lockfile=
 373      IFS="     $LF"
 374      (
 375          git-fetch-pack --thin $exec $keep "$remote" $rref || echo failed "$remote"
 376      ) |
 377      while read sha1 remote_name
 378      do
 379          case "$sha1" in
 380          failed)
 381                  echo >&2 "Fetch failure: $remote"
 382                  exit 1 ;;
 383          # special line coming from index-pack with the pack name
 384          pack)
 385                  continue ;;
 386          keep)
 387                  pack_lockfile="$GIT_OBJECT_DIRECTORY/pack/pack-$remote_name.keep"
 388                  continue ;;
 389          esac
 390          found=
 391          single_force=
 392          for ref in $refs
 393          do
 394              case "$ref" in
 395              +$remote_name:*)
 396                  single_force=t
 397                  not_for_merge=
 398                  found="$ref"
 399                  break ;;
 400              .+$remote_name:*)
 401                  single_force=t
 402                  not_for_merge=t
 403                  found="$ref"
 404                  break ;;
 405              .$remote_name:*)
 406                  not_for_merge=t
 407                  found="$ref"
 408                  break ;;
 409              $remote_name:*)
 410                  not_for_merge=
 411                  found="$ref"
 412                  break ;;
 413              esac
 414          done
 415          local_name=$(expr "z$found" : 'z[^:]*:\(.*\)')
 416          append_fetch_head "$sha1" "$remote" \
 417                  "$remote_name" "$remote_nick" "$local_name" \
 418                  "$not_for_merge" || exit
 419      done &&
 420      if [ "$pack_lockfile" ]; then rm -f "$pack_lockfile"; fi
 421    ) || exit ;;
 422  esac
 423
 424}
 425
 426fetch_main "$reflist" || exit
 427
 428# automated tag following
 429case "$no_tags$tags" in
 430'')
 431        case "$reflist" in
 432        *:refs/*)
 433                # effective only when we are following remote branch
 434                # using local tracking branch.
 435                taglist=$(IFS=" " &&
 436                echo "$ls_remote_result" |
 437                sed -n  -e 's|^\('"$_x40"'\)    \(refs/tags/.*\)^{}$|\1 \2|p' \
 438                        -e 's|^\('"$_x40"'\)    \(refs/tags/.*\)$|\1 \2|p' |
 439                while read sha1 name
 440                do
 441                        git-show-ref --verify --quiet -- "$name" && continue
 442                        git-check-ref-format "$name" || {
 443                                echo >&2 "warning: tag ${name} ignored"
 444                                continue
 445                        }
 446                        git-cat-file -t "$sha1" >/dev/null 2>&1 || continue
 447                        echo >&2 "Auto-following $name"
 448                        echo ".${name}:${name}"
 449                done)
 450        esac
 451        case "$taglist" in
 452        '') ;;
 453        ?*)
 454                fetch_main "$taglist" || exit ;;
 455        esac
 456esac
 457
 458# If the original head was empty (i.e. no "master" yet), or
 459# if we were told not to worry, we do not have to check.
 460case "$orig_head" in
 461'')
 462        ;;
 463?*)
 464        curr_head=$(git-rev-parse --verify HEAD 2>/dev/null)
 465        if test "$curr_head" != "$orig_head"
 466        then
 467            git-update-ref \
 468                        -m "$rloga: Undoing incorrectly fetched HEAD." \
 469                        HEAD "$orig_head"
 470                die "Cannot fetch into the current branch."
 471        fi
 472        ;;
 473esac