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