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