[PATCH] Provide access to git_dir through get_git_dir().
[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
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
96 fast_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
148 case "$update_head_ok" in
149 '')
150         orig_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
151         ;;
152 esac
153
154 for ref in $(get_remote_refs_for_fetch "$@")
155 do
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 >&2 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 -q "$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 -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 ||
198                 rm -f "$GIT_DIR/TMP_ALT"
199             if test -f "$GIT_DIR/TMP_ALT"
200             then
201                 resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
202                 while read alt
203                 do
204                     case "$alt" in 'bad alternate: '*) die "$alt";; esac
205                     echo >&2 "Getting alternate: $alt"
206                     rsync -av --ignore-existing --exclude info \
207                     "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
208                 done
209                 rm -f "$GIT_DIR/TMP_ALT"
210             fi
211             rsync_slurped_objects=t
212         }
213         ;;
214     *)
215         # We will do git native transport with just one call later.
216         continue ;;
217     esac
218
219     append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
220
221 done
222
223 case "$remote" in
224 http://* | https://* | rsync://* )
225     ;; # we are already done.
226 *)
227     (
228         git-fetch-pack "$remote" $rref || echo failed "$remote"
229     ) |
230     while read sha1 remote_name
231     do
232         case "$sha1" in
233         failed)
234                 echo >&2 "Fetch failure: $remote"
235                 exit 1 ;;
236         esac
237         found=
238         single_force=
239         for ref in $refs
240         do
241             case "$ref" in
242             +$remote_name:*)
243                 single_force=t
244                 found="$ref"
245                 break ;;
246             $remote_name:*)
247                 found="$ref"
248                 break ;;
249             esac
250         done
251
252         local_name=$(expr "$found" : '[^:]*:\(.*\)')
253         append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
254     done || exit
255     ;;
256 esac
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.
260 case ",$update_head_ok,$orig_head," in
261 *,, | t,* )
262         ;;
263 *)
264         curr_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
265         if test "$curr_head" != "$orig_head"
266         then
267                 echo "$orig_head" >$GIT_DIR/HEAD
268                 die "Cannot fetch into the current branch."
269         fi
270         ;;
271 esac