[PATCH] rsh.c env and quoting cleanup, take 2
[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 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 "$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 -avz --ignore-existing "$remote/objects/" \
191                 "$GIT_OBJECT_DIRECTORY/" || exit
192             rsync_slurped_objects=t
193         }
194         ;;
195     *)
196         # We will do git native transport with just one call later.
197         continue ;;
198     esac
199
200     append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
201
202 done
203
204 case "$remote" in
205 http://* | https://* | rsync://* )
206     ;; # we are already done.
207 *)
208     (
209         git-fetch-pack "$remote" $rref || echo failed "$remote"
210     ) |
211     while read sha1 remote_name
212     do
213         case "$sha1" in
214         failed)
215                 echo >&2 "Fetch failure: $remote"
216                 exit 1 ;;
217         esac
218         found=
219         single_force=
220         for ref in $refs
221         do
222             case "$ref" in
223             +$remote_name:*)
224                 single_force=t
225                 found="$ref"
226                 break ;;
227             $remote_name:*)
228                 found="$ref"
229                 break ;;
230             esac
231         done
232
233         local_name=$(expr "$found" : '[^:]*:\(.*\)')
234         append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
235     done || exit
236     ;;
237 esac
238
239 # If the original head was empty (i.e. no "master" yet), or
240 # if we were told not to worry, we do not have to check.
241 case ",$update_head_ok,$orig_head," in
242 *,, | t,* )
243         ;;
244 *)
245         curr_head=$(cat "$GIT_DIR/HEAD" 2>/dev/null)
246         if test "$curr_head" != "$orig_head"
247         then
248                 echo "$orig_head" >$GIT_DIR/HEAD
249                 die "Cannot fetch into the current branch."
250         fi
251         ;;
252 esac