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