Use git-update-ref in scripts.
[git.git] / git-fetch.sh
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
8 append=
9 force=
10 update_head_ok=
11 while case "$#" in 0) break ;; esac
12 do
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
30 done
31
32 case "$#" in
33 0)
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 ;;
38 esac
39
40 remote_nick="$1"
41 remote=$(get_remote_url "$@")
42 refs=
43 rref=
44 rsync_slurped_objects=
45
46 if test "" = "$append"
47 then
48         : >$GIT_DIR/FETCH_HEAD
49 fi
50
51 append_fetch_head () {
52     head_="$1"
53     remote_="$2"
54     remote_name_="$3"
55     remote_nick_="$4"
56     local_name_="$5"
57     case "$6" in
58     t) not_for_merge_='not-for-merge' ;;
59     '') not_for_merge_= ;;
60     esac
61
62     # remote-nick is the URL given on the command line (or a shorthand)
63     # remote-name is the $GIT_DIR relative refs/ path we computed
64     # for this refspec.
65     case "$remote_name_" in
66     HEAD)
67         note_= ;;
68     refs/heads/*)
69         note_="$(expr "$remote_name_" : 'refs/heads/\(.*\)')"
70         note_="branch '$note_' of " ;;
71     refs/tags/*)
72         note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
73         note_="tag '$note_' of " ;;
74     *)
75         note_="$remote_name of " ;;
76     esac
77     remote_1_=$(expr "$remote_" : '\(.*\)\.git/*$') &&
78         remote_="$remote_1_"
79     note_="$note_$remote_"
80
81     # 2.6.11-tree tag would not be happy to be fed to resolve.
82     if git-cat-file commit "$head_" >/dev/null 2>&1
83     then
84         headc_=$(git-rev-parse --verify "$head_^0") || exit
85         echo "$headc_   $not_for_merge_ $note_" >>$GIT_DIR/FETCH_HEAD
86         echo >&2 "* committish: $head_"
87         echo >&2 "  $note_"
88     else
89         echo "$head_    not-for-merge   $note_" >>$GIT_DIR/FETCH_HEAD
90         echo >&2 "* non-commit: $head_"
91         echo >&2 "  $note_"
92     fi
93     if test "$local_name_" != ""
94     then
95         # We are storing the head locally.  Make sure that it is
96         # a fast forward (aka "reverse push").
97         fast_forward_local "$local_name_" "$head_" "$note_"
98     fi
99 }
100
101 fast_forward_local () {
102     mkdir -p "$(dirname "$GIT_DIR/$1")"
103     case "$1" in
104     refs/tags/*)
105         # Tags need not be pointing at commits so there
106         # is no way to guarantee "fast-forward" anyway.
107         if test -f "$GIT_DIR/$1"
108         then
109                 echo >&2 "* $1: updating with $3"
110         else
111                 echo >&2 "* $1: storing $3"
112         fi
113         git-update-ref "$1" "$2" 
114         ;;
115
116     refs/heads/*)
117         # $1 is the ref being updated.
118         # $2 is the new value for the ref.
119         local=$(git-rev-parse --verify "$1^0" 2>/dev/null)
120         if test "$local"
121         then
122             # Require fast-forward.
123             mb=$(git-merge-base "$local" "$2") &&
124             case "$2,$mb" in
125             $local,*)
126                 echo >&2 "* $1: same as $3"
127                 ;;
128             *,$local)
129                 echo >&2 "* $1: fast forward to $3"
130                 git-update-ref "$1" "$2" "$local"
131                 ;;
132             *)
133                 false
134                 ;;
135             esac || {
136                 echo >&2 "* $1: does not fast forward to $3;"
137                 case ",$force,$single_force," in
138                 *,t,*)
139                         echo >&2 "  forcing update."
140                         git-update-ref "$1" "$2" "$local"
141                         ;;
142                 *)
143                         echo >&2 "  not updating."
144                         ;;
145                 esac
146             }
147         else
148             echo >&2 "* $1: storing $3"
149             git-update-ref "$1" "$2"
150         fi
151         ;;
152     esac
153 }
154
155 case "$update_head_ok" in
156 '')
157         orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
158         ;;
159 esac
160
161 for ref in $(get_remote_refs_for_fetch "$@")
162 do
163     refs="$refs $ref"
164
165     # These are relative path from $GIT_DIR, typically starting at refs/
166     # but may be HEAD
167     if expr "$ref" : '\.' >/dev/null
168     then
169         not_for_merge=t
170         ref=$(expr "$ref" : '\.\(.*\)')
171     else
172         not_for_merge=
173     fi
174     if expr "$ref" : '\+' >/dev/null
175     then
176         single_force=t
177         ref=$(expr "$ref" : '\+\(.*\)')
178     else
179         single_force=
180     fi
181     remote_name=$(expr "$ref" : '\([^:]*\):')
182     local_name=$(expr "$ref" : '[^:]*:\(.*\)')
183
184     rref="$rref $remote_name"
185
186     # There are transports that can fetch only one head at a time...
187     case "$remote" in
188     http://* | https://*)
189         if [ -n "$GIT_SSL_NO_VERIFY" ]; then
190             curl_extra_args="-k"
191         fi
192         head=$(curl -nsf $curl_extra_args "$remote/$remote_name") &&
193         expr "$head" : "$_x40\$" >/dev/null ||
194                 die "Failed to fetch $remote_name from $remote"
195         echo >&2 Fetching "$remote_name from $remote" using http
196         git-http-fetch -v -a "$head" "$remote/" || exit
197         ;;
198     rsync://*)
199         TMP_HEAD="$GIT_DIR/TMP_HEAD"
200         rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
201         head=$(git-rev-parse --verify TMP_HEAD)
202         rm -f "$TMP_HEAD"
203         test "$rsync_slurped_objects" || {
204             rsync -av --ignore-existing --exclude info \
205                 "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
206
207             # Look at objects/info/alternates for rsync -- http will
208             # support it natively and git native ones will do it on the remote
209             # end.  Not having that file is not a crime.
210             rsync -q "$remote/objects/info/alternates" \
211                 "$GIT_DIR/TMP_ALT" 2>/dev/null ||
212                 rm -f "$GIT_DIR/TMP_ALT"
213             if test -f "$GIT_DIR/TMP_ALT"
214             then
215                 resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
216                 while read alt
217                 do
218                     case "$alt" in 'bad alternate: '*) die "$alt";; esac
219                     echo >&2 "Getting alternate: $alt"
220                     rsync -av --ignore-existing --exclude info \
221                     "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
222                 done
223                 rm -f "$GIT_DIR/TMP_ALT"
224             fi
225             rsync_slurped_objects=t
226         }
227         ;;
228     *)
229         # We will do git native transport with just one call later.
230         continue ;;
231     esac
232
233     append_fetch_head "$head" "$remote" \
234         "$remote_name" "$remote_nick" "$local_name" "$not_for_merge"
235
236 done
237
238 case "$remote" in
239 http://* | https://* | rsync://* )
240     ;; # we are already done.
241 *)
242     (
243         git-fetch-pack "$remote" $rref || echo failed "$remote"
244     ) |
245     while read sha1 remote_name
246     do
247         case "$sha1" in
248         failed)
249                 echo >&2 "Fetch failure: $remote"
250                 exit 1 ;;
251         esac
252         found=
253         single_force=
254         for ref in $refs
255         do
256             case "$ref" in
257             +$remote_name:*)
258                 single_force=t
259                 not_for_merge=
260                 found="$ref"
261                 break ;;
262             .+$remote_name:*)
263                 single_force=t
264                 not_for_merge=t
265                 found="$ref"
266                 break ;;
267             .$remote_name:*)
268                 not_for_merge=t
269                 found="$ref"
270                 break ;;
271             $remote_name:*)
272                 not_for_merge=
273                 found="$ref"
274                 break ;;
275             esac
276         done
277         local_name=$(expr "$found" : '[^:]*:\(.*\)')
278         append_fetch_head "$sha1" "$remote" \
279                 "$remote_name" "$remote_nick" "$local_name" "$not_for_merge"
280     done || exit
281     ;;
282 esac
283
284 # If the original head was empty (i.e. no "master" yet), or
285 # if we were told not to worry, we do not have to check.
286 case ",$update_head_ok,$orig_head," in
287 *,, | t,* )
288         ;;
289 *)
290         curr_head=$(git-rev-parse --verify HEAD 2>/dev/null)
291         if test "$curr_head" != "$orig_head"
292         then
293                 git-update-ref HEAD "$orig_head"
294                 die "Cannot fetch into the current branch."
295         fi
296         ;;
297 esac