git-fetch.shon commit Multi-backend merge driver. (91063bb)
   1#!/bin/sh
   2#
   3. git-sh-setup || die "Not a git archive"
   4. git-parse-remote
   5_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
   6_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
   7
   8append=
   9force=
  10update_head_ok=
  11while case "$#" in 0) break ;; esac
  12do
  13        case "$1" in
  14        -a|--a|--ap|--app|--appe|--appen|--append)
  15                append=t
  16                ;;
  17        -f|--f|--fo|--for|--forc|--force)
  18                force=t
  19                ;;
  20        -u|--u|--up|--upd|--upda|--updat|--update|--update-|--update-h|\
  21        --update-he|--update-hea|--update-head|--update-head-|\
  22        --update-head-o|--update-head-ok)
  23                update_head_ok=t
  24                ;;
  25        *)
  26                break
  27                ;;
  28        esac
  29        shift
  30done
  31
  32case "$#" in
  330)
  34        test -f "$GIT_DIR/branches/origin" ||
  35                test -f "$GIT_DIR/remotes/origin" ||
  36                        die "Where do you want to fetch from today?"
  37        set origin ;;
  38esac
  39
  40remote_nick="$1"
  41remote=$(get_remote_url "$@")
  42refs=
  43rref=
  44rsync_slurped_objects=
  45
  46if test "" = "$append"
  47then
  48        : >$GIT_DIR/FETCH_HEAD
  49fi
  50
  51append_fetch_head () {
  52    head_="$1"
  53    remote_="$2"
  54    remote_name_="$3"
  55    remote_nick_="$4"
  56    local_name_="$5"
  57
  58    # remote-nick is the URL given on the command line (or a shorthand)
  59    # remote-name is the $GIT_DIR relative refs/ path we computed
  60    # for this refspec.
  61    case "$remote_name_" in
  62    HEAD)
  63        note_= ;;
  64    refs/heads/*)
  65        note_="$(expr "$remote_name_" : 'refs/heads/\(.*\)')"
  66        note_="branch '$note_' of " ;;
  67    refs/tags/*)
  68        note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
  69        note_="tag '$note_' of " ;;
  70    *)
  71        note_="$remote_name of " ;;
  72    esac
  73    remote_1_=$(expr "$remote_" : '\(.*\)\.git/*$') &&
  74        remote_="$remote_1_"
  75    note_="$note_$remote_"
  76
  77    # 2.6.11-tree tag would not be happy to be fed to resolve.
  78    if git-cat-file commit "$head_" >/dev/null 2>&1
  79    then
  80        headc_=$(git-rev-parse --verify "$head_^0") || exit
  81        echo "$headc_   $note_" >>$GIT_DIR/FETCH_HEAD
  82        echo >&2 "* committish: $head_"
  83        echo >&2 "  $note_"
  84    else
  85        echo >&2 "* non-commit: $head_"
  86        echo >&2 "  $note_"
  87    fi
  88    if test "$local_name_" != ""
  89    then
  90        # We are storing the head locally.  Make sure that it is
  91        # a fast forward (aka "reverse push").
  92        fast_forward_local "$local_name_" "$head_" "$note_"
  93    fi
  94}
  95
  96fast_forward_local () {
  97    mkdir -p "$(dirname "$GIT_DIR/$1")"
  98    case "$1" in
  99    refs/tags/*)
 100        # Tags need not be pointing at commits so there
 101        # is no way to guarantee "fast-forward" anyway.
 102        if test -f "$GIT_DIR/$1"
 103        then
 104                echo >&2 "* $1: updating with $3"
 105        else
 106                echo >&2 "* $1: storing $3"
 107        fi
 108        echo "$2" >"$GIT_DIR/$1" ;;
 109
 110    refs/heads/*)
 111        # NEEDSWORK: use the same cmpxchg protocol here.
 112        echo "$2" >"$GIT_DIR/$1.lock"
 113        if test -f "$GIT_DIR/$1"
 114        then
 115            local=$(git-rev-parse --verify "$1^0") &&
 116            mb=$(git-merge-base "$local" "$2") &&
 117            case "$2,$mb" in
 118            $local,*)
 119                echo >&2 "* $1: same as $3"
 120                ;;
 121            *,$local)
 122                echo >&2 "* $1: fast forward to $3"
 123                ;;
 124            *)
 125                false
 126                ;;
 127            esac || {
 128                echo >&2 "* $1: does not fast forward to $3;"
 129                case "$force,$single_force" in
 130                t,* | *,t)
 131                        echo >&2 "  forcing update."
 132                        ;;
 133                *)
 134                        mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1.remote"
 135                        echo >&2 "  leaving it in '$1.remote'"
 136                        ;;
 137                esac
 138            }
 139        else
 140                echo >&2 "* $1: storing $3"
 141        fi
 142        test -f "$GIT_DIR/$1.lock" &&
 143            mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1"
 144        ;;
 145    esac
 146}
 147
 148case "$update_head_ok" in
 149'')
 150        orig_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
 151        ;;
 152esac
 153
 154for ref in $(get_remote_refs_for_fetch "$@")
 155do
 156    refs="$refs $ref"
 157
 158    # These are relative path from $GIT_DIR, typically starting at refs/
 159    # but may be HEAD
 160    if expr "$ref" : '\+' >/dev/null
 161    then
 162        single_force=t
 163        ref=$(expr "$ref" : '\+\(.*\)')
 164    else
 165        single_force=
 166    fi
 167    remote_name=$(expr "$ref" : '\([^:]*\):')
 168    local_name=$(expr "$ref" : '[^:]*:\(.*\)')
 169
 170    rref="$rref $remote_name"
 171
 172    # There are transports that can fetch only one head at a time...
 173    case "$remote" in
 174    http://* | https://*)
 175        if [ -n "$GIT_SSL_NO_VERIFY" ]; then
 176            curl_extra_args="-k"
 177        fi
 178        head=$(curl -nsf $curl_extra_args "$remote/$remote_name") &&
 179        expr "$head" : "$_x40\$" >/dev/null ||
 180                die "Failed to fetch $remote_name from $remote"
 181        echo Fetching "$remote_name from $remote" using http
 182        git-http-fetch -v -a "$head" "$remote/" || exit
 183        ;;
 184    rsync://*)
 185        TMP_HEAD="$GIT_DIR/TMP_HEAD"
 186        rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
 187        head=$(git-rev-parse TMP_HEAD)
 188        rm -f "$TMP_HEAD"
 189        test "$rsync_slurped_objects" || {
 190            rsync -avz --ignore-existing "$remote/objects/" \
 191                "$GIT_OBJECT_DIRECTORY/" || exit
 192            rsync_slurped_objects=t
 193        }
 194        ;;
 195    *)
 196        # We will do git native transport with just one call later.
 197        continue ;;
 198    esac
 199
 200    append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
 201
 202done
 203
 204case "$remote" in
 205http://* | https://* | rsync://* )
 206    ;; # we are already done.
 207*)
 208    git-fetch-pack "$remote" $rref |
 209    while read sha1 remote_name
 210    do
 211        found=
 212        single_force=
 213        for ref in $refs
 214        do
 215            case "$ref" in
 216            +$remote_name:*)
 217                single_force=t
 218                found="$ref"
 219                break ;;
 220            $remote_name:*)
 221                found="$ref"
 222                break ;;
 223            esac
 224        done
 225
 226        local_name=$(expr "$found" : '[^:]*:\(.*\)')
 227        append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
 228    done
 229    ;;
 230esac
 231
 232# If the original head was empty (i.e. no "master" yet), or
 233# if we were told not to worry, we do not have to check.
 234case ",$update_head_ok,$orig_head," in
 235*,, | t,* )
 236        ;;
 237*)
 238        curr_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
 239        if test "$curr_head" != "$orig_head"
 240        then
 241                echo "$orig_head" >$GIT_DIR/HEAD
 242                die "Cannot fetch into the current branch."
 243        fi
 244        ;;
 245esac