2aa34b3992f697a37705a9e4647e72eb5bc6a3ba
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 "z$1" : 'z-[^=]*=\(.*\)')
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
88if test -z "$exec"
89then
90 # No command line override and we have configuration for the remote.
91 exec="--upload-pack=$(get_uploadpack $1)"
92fi
93
94remote_nick="$1"
95remote=$(get_remote_url "$@")
96refs=
97rref=
98rsync_slurped_objects=
99
100if test "" = "$append"
101then
102 : >"$GIT_DIR/FETCH_HEAD"
103fi
104
105# Global that is reused later
106ls_remote_result=$(git ls-remote $exec "$remote") ||
107 die "Cannot get the repository state from $remote"
108
109append_fetch_head () {
110 flags=
111 test -n "$verbose" && flags="$flags -v"
112 test -n "$force" && flags="$flags -f"
113 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
114 git-fetch--tool append-fetch-head $flags "$@"
115}
116
117update_local_ref () {
118 flags=
119 test -n "$verbose" && flags="$flags -v"
120 test -n "$force" && flags="$flags -f"
121 GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
122 git-fetch--tool update-local-ref $flags "$@"
123}
124
125# updating the current HEAD with git-fetch in a bare
126# repository is always fine.
127if test -z "$update_head_ok" && test $(is_bare_repository) = false
128then
129 orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
130fi
131
132# If --tags (and later --heads or --all) is specified, then we are
133# not talking about defaults stored in Pull: line of remotes or
134# branches file, and just fetch those and refspecs explicitly given.
135# Otherwise we do what we always did.
136
137reflist=$(get_remote_refs_for_fetch "$@")
138if test "$tags"
139then
140 taglist=`IFS=' ' &&
141 echo "$ls_remote_result" |
142 git-show-ref --exclude-existing=refs/tags/ |
143 while read sha1 name
144 do
145 echo ".${name}:${name}"
146 done` || exit
147 if test "$#" -gt 1
148 then
149 # remote URL plus explicit refspecs; we need to merge them.
150 reflist="$reflist$LF$taglist"
151 else
152 # No explicit refspecs; fetch tags only.
153 reflist=$taglist
154 fi
155fi
156
157fetch_native () {
158 reflist="$1"
159 refs=
160 rref=
161
162 for ref in $reflist
163 do
164 refs="$refs$LF$ref"
165
166 # These are relative path from $GIT_DIR, typically starting at refs/
167 # but may be HEAD
168 if expr "z$ref" : 'z\.' >/dev/null
169 then
170 not_for_merge=t
171 ref=$(expr "z$ref" : 'z\.\(.*\)')
172 else
173 not_for_merge=
174 fi
175 if expr "z$ref" : 'z+' >/dev/null
176 then
177 single_force=t
178 ref=$(expr "z$ref" : 'z+\(.*\)')
179 else
180 single_force=
181 fi
182 remote_name=$(expr "z$ref" : 'z\([^:]*\):')
183 local_name=$(expr "z$ref" : 'z[^:]*:\(.*\)')
184
185 rref="$rref$LF$remote_name"
186 done
187
188 ( : subshell because we muck with IFS
189 IFS=" $LF"
190 (
191 git-fetch-pack --thin $exec $keep $shallow_depth "$remote" $rref ||
192 echo failed "$remote"
193 ) |
194 (
195 trap '
196 if test -n "$keepfile" && test -f "$keepfile"
197 then
198 rm -f "$keepfile"
199 fi
200 ' 0
201
202 keepfile=
203 while read sha1 remote_name
204 do
205 case "$sha1" in
206 failed)
207 echo >&2 "Fetch failure: $remote"
208 exit 1 ;;
209 # special line coming from index-pack with the pack name
210 pack)
211 continue ;;
212 keep)
213 keepfile="$GIT_OBJECT_DIRECTORY/pack/pack-$remote_name.keep"
214 continue ;;
215 esac
216 found=
217 single_force=
218 for ref in $refs
219 do
220 case "$ref" in
221 +$remote_name:*)
222 single_force=t
223 not_for_merge=
224 found="$ref"
225 break ;;
226 .+$remote_name:*)
227 single_force=t
228 not_for_merge=t
229 found="$ref"
230 break ;;
231 .$remote_name:*)
232 not_for_merge=t
233 found="$ref"
234 break ;;
235 $remote_name:*)
236 not_for_merge=
237 found="$ref"
238 break ;;
239 esac
240 done
241 local_name=$(expr "z$found" : 'z[^:]*:\(.*\)')
242 append_fetch_head "$sha1" "$remote" \
243 "$remote_name" "$remote_nick" "$local_name" \
244 "$not_for_merge" || exit
245 done
246 )
247 ) || exit
248
249}
250
251fetch_dumb () {
252 reflist="$1"
253 refs=
254 rref=
255
256 for ref in $reflist
257 do
258 refs="$refs$LF$ref"
259
260 # These are relative path from $GIT_DIR, typically starting at refs/
261 # but may be HEAD
262 if expr "z$ref" : 'z\.' >/dev/null
263 then
264 not_for_merge=t
265 ref=$(expr "z$ref" : 'z\.\(.*\)')
266 else
267 not_for_merge=
268 fi
269 if expr "z$ref" : 'z+' >/dev/null
270 then
271 single_force=t
272 ref=$(expr "z$ref" : 'z+\(.*\)')
273 else
274 single_force=
275 fi
276 remote_name=$(expr "z$ref" : 'z\([^:]*\):')
277 local_name=$(expr "z$ref" : 'z[^:]*:\(.*\)')
278
279 rref="$rref$LF$remote_name"
280
281 # There are transports that can fetch only one head at a time...
282 case "$remote" in
283 http://* | https://* | ftp://*)
284 test -n "$shallow_depth" &&
285 die "shallow clone with http not supported"
286 proto=`expr "$remote" : '\([^:]*\):'`
287 if [ -n "$GIT_SSL_NO_VERIFY" ]; then
288 curl_extra_args="-k"
289 fi
290 if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \
291 "`git-config --bool http.noEPSV`" = true ]; then
292 noepsv_opt="--disable-epsv"
293 fi
294
295 # Find $remote_name from ls-remote output.
296 head=$(
297 IFS=' '
298 echo "$ls_remote_result" |
299 while read sha1 name
300 do
301 test "z$name" = "z$remote_name" || continue
302 echo "$sha1"
303 break
304 done
305 )
306 expr "z$head" : "z$_x40\$" >/dev/null ||
307 die "No such ref $remote_name at $remote"
308 echo >&2 "Fetching $remote_name from $remote using $proto"
309 git-http-fetch -v -a "$head" "$remote/" || exit
310 ;;
311 rsync://*)
312 test -n "$shallow_depth" &&
313 die "shallow clone with rsync not supported"
314 TMP_HEAD="$GIT_DIR/TMP_HEAD"
315 rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
316 head=$(git-rev-parse --verify TMP_HEAD)
317 rm -f "$TMP_HEAD"
318 test "$rsync_slurped_objects" || {
319 rsync -av --ignore-existing --exclude info \
320 "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
321
322 # Look at objects/info/alternates for rsync -- http will
323 # support it natively and git native ones will do it on
324 # the remote end. Not having that file is not a crime.
325 rsync -q "$remote/objects/info/alternates" \
326 "$GIT_DIR/TMP_ALT" 2>/dev/null ||
327 rm -f "$GIT_DIR/TMP_ALT"
328 if test -f "$GIT_DIR/TMP_ALT"
329 then
330 resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
331 while read alt
332 do
333 case "$alt" in 'bad alternate: '*) die "$alt";; esac
334 echo >&2 "Getting alternate: $alt"
335 rsync -av --ignore-existing --exclude info \
336 "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
337 done
338 rm -f "$GIT_DIR/TMP_ALT"
339 fi
340 rsync_slurped_objects=t
341 }
342 ;;
343 esac
344
345 append_fetch_head "$head" "$remote" \
346 "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit
347
348 done
349
350}
351
352fetch_main () {
353 case "$remote" in
354 http://* | https://* | ftp://* | rsync://* )
355 fetch_dumb "$@"
356 ;;
357 *)
358 fetch_native "$@"
359 ;;
360 esac
361}
362
363fetch_main "$reflist" || exit
364
365# automated tag following
366case "$no_tags$tags" in
367'')
368 case "$reflist" in
369 *:refs/*)
370 # effective only when we are following remote branch
371 # using local tracking branch.
372 taglist=$(IFS=' ' &&
373 echo "$ls_remote_result" |
374 git-show-ref --exclude-existing=refs/tags/ |
375 while read sha1 name
376 do
377 git-cat-file -t "$sha1" >/dev/null 2>&1 || continue
378 echo >&2 "Auto-following $name"
379 echo ".${name}:${name}"
380 done)
381 esac
382 case "$taglist" in
383 '') ;;
384 ?*)
385 # do not deepen a shallow tree when following tags
386 shallow_depth=
387 fetch_main "$taglist" || exit ;;
388 esac
389esac
390
391# If the original head was empty (i.e. no "master" yet), or
392# if we were told not to worry, we do not have to check.
393case "$orig_head" in
394'')
395 ;;
396?*)
397 curr_head=$(git-rev-parse --verify HEAD 2>/dev/null)
398 if test "$curr_head" != "$orig_head"
399 then
400 git-update-ref \
401 -m "$GIT_REFLOG_ACTION: Undoing incorrectly fetched HEAD." \
402 HEAD "$orig_head"
403 die "Cannot fetch into the current branch."
404 fi
405 ;;
406esac