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"$#"in0)break;;esac 12do 13case"$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*) 26break 27;; 28esac 29shift 30done 31 32case"$#"in 330) 34test -f"$GIT_DIR/branches/origin"|| 35test -f"$GIT_DIR/remotes/origin"|| 36 die "Where do you want to fetch from today?" 37set origin ;; 38esac 39 40remote_nick="$1" 41remote=$(get_remote_url "$@") 42refs= 43rref= 44rsync_slurped_objects= 45 46iftest""="$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. 61case"$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_nameof ";; 72esac 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. 78if git-cat-file commit "$head_">/dev/null 2>&1 79then 80 headc_=$(git-rev-parse --verify"$head_^0") ||exit 81echo"$headc_$note_">>$GIT_DIR/FETCH_HEAD 82echo>&2"* committish:$head_" 83echo>&2"$note_" 84else 85echo>&2"* non-commit:$head_" 86echo>&2"$note_" 87fi 88iftest"$local_name_"!="" 89then 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_" 93fi 94} 95 96fast_forward_local () { 97mkdir-p"$(dirname "$GIT_DIR/$1")" 98case"$1"in 99 refs/tags/*) 100# Tags need not be pointing at commits so there 101# is no way to guarantee "fast-forward" anyway. 102iftest -f"$GIT_DIR/$1" 103then 104echo>&2"*$1: updating with$3" 105else 106echo>&2"*$1: storing$3" 107fi 108echo"$2">"$GIT_DIR/$1";; 109 110 refs/heads/*) 111# NEEDSWORK: use the same cmpxchg protocol here. 112echo"$2">"$GIT_DIR/$1.lock" 113iftest -f"$GIT_DIR/$1" 114then 115local=$(git-rev-parse --verify"$1^0") && 116 mb=$(git-merge-base "$local""$2") && 117case"$2,$mb"in 118$local,*) 119echo>&2"*$1: same as$3" 120;; 121*,$local) 122echo>&2"*$1: fast forward to$3" 123;; 124*) 125 false 126;; 127esac|| { 128echo>&2"*$1: does not fast forward to$3;" 129case"$force,$single_force"in 130 t,* | *,t) 131echo>&2" forcing update." 132;; 133*) 134mv"$GIT_DIR/$1.lock""$GIT_DIR/$1.remote" 135echo>&2" leaving it in '$1.remote'" 136;; 137esac 138} 139else 140echo>&2"*$1: storing$3" 141fi 142test -f"$GIT_DIR/$1.lock"&& 143mv"$GIT_DIR/$1.lock""$GIT_DIR/$1" 144;; 145esac 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 160ifexpr"$ref":'\+'>/dev/null 161then 162 single_force=t 163 ref=$(expr"$ref":'\+\(.*\)') 164else 165 single_force= 166fi 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... 173case"$remote"in 174 http://* | https://*) 175if[-n"$GIT_SSL_NO_VERIFY"];then 176 curl_extra_args="-k" 177fi 178head=$(curl -nsf$curl_extra_args"$remote/$remote_name") && 179expr"$head":"$_x40\$">/dev/null || 180 die "Failed to fetch$remote_namefrom$remote" 181echo>&2 Fetching "$remote_namefrom$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 -q"$remote/$remote_name""$TMP_HEAD"||exit1 187head=$(git-rev-parse TMP_HEAD) 188rm-f"$TMP_HEAD" 189test"$rsync_slurped_objects"|| { 190 rsync -av --ignore-existing --exclude info \ 191"$remote/objects/""$GIT_OBJECT_DIRECTORY/"||exit 192 193# Look at objects/info/alternates for rsync -- http will 194# support it natively and git native ones will do it on the remote 195# end. Not having that file is not a crime. 196 rsync -q"$remote/objects/info/alternates" \ 197"$GIT_DIR/TMP_ALT"2>/dev/null || 198rm-f"$GIT_DIR/TMP_ALT" 199iftest -f"$GIT_DIR/TMP_ALT" 200then 201 resolve_alternates "$remote"<"$GIT_DIR/TMP_ALT"| 202whileread alt 203do 204case"$alt"in'bad alternate: '*) die "$alt";;esac 205echo>&2"Getting alternate:$alt" 206 rsync -av --ignore-existing --exclude info \ 207"$alt""$GIT_OBJECT_DIRECTORY/"||exit 208done 209rm-f"$GIT_DIR/TMP_ALT" 210fi 211 rsync_slurped_objects=t 212} 213;; 214*) 215# We will do git native transport with just one call later. 216continue;; 217esac 218 219 append_fetch_head "$head""$remote""$remote_name""$remote_nick""$local_name" 220 221done 222 223case"$remote"in 224http://* | https://* | rsync://* ) 225;;# we are already done. 226*) 227( 228 git-fetch-pack "$remote"$rref||echo failed "$remote" 229) | 230whileread sha1 remote_name 231do 232case"$sha1"in 233 failed) 234echo>&2"Fetch failure:$remote" 235exit1;; 236esac 237 found= 238 single_force= 239for ref in$refs 240do 241case"$ref"in 242+$remote_name:*) 243 single_force=t 244 found="$ref" 245break;; 246$remote_name:*) 247 found="$ref" 248break;; 249esac 250done 251 252 local_name=$(expr"$found":'[^:]*:\(.*\)') 253 append_fetch_head "$sha1""$remote""$remote_name""$remote_nick""$local_name" 254done||exit 255;; 256esac 257 258# If the original head was empty (i.e. no "master" yet), or 259# if we were told not to worry, we do not have to check. 260case",$update_head_ok,$orig_head,"in 261*,, | t,* ) 262;; 263*) 264 curr_head=$(cat"$GIT_DIR/HEAD"2>/dev/null) 265iftest"$curr_head"!="$orig_head" 266then 267echo"$orig_head">$GIT_DIR/HEAD 268 die "Cannot fetch into the current branch." 269fi 270;; 271esac