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