a70909e4ff15035d135eed061de8b4ea70ac5060
[git.git] / git-fetch-script
1 #!/bin/sh
2 #
3 . git-sh-setup-script || die "Not a git archive"
4 . git-parse-remote-script
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 case "$#" in
10 0)
11         test -f "$GIT_DIR/branches/origin" ||
12                 test -f "$GIT_DIR/remotes/origin" ||
13                         die "Where do you want to fetch from?"
14         set origin ;;
15 *)
16         case "$1" in
17         -a|--a|--ap|--app|--appe|--appen|--append)
18                 append=t
19                 shift ;;
20         esac
21 esac
22 remote_nick="$1"
23 remote=$(get_remote_url "$@")
24 refs=
25 rref=
26 rsync_slurped_objects=
27
28 if test "" = "$append"
29 then
30         : >$GIT_DIR/FETCH_HEAD
31 fi
32
33 append_fetch_head () {
34     head_="$1"
35     remote_="$2"
36     remote_name_="$3"
37     remote_nick_="$4"
38     local_name_="$5"
39
40     # 2.6.11-tree tag would not be happy to be fed to resolve.
41     if git-cat-file commit "$head_" >/dev/null 2>&1
42     then
43         head_=$(git-rev-parse --verify "$head_^0") || exit
44         note_="$head_   $remote_name_ from $remote_nick_"
45         echo "$note_" >>$GIT_DIR/FETCH_HEAD
46         echo >&2 "* committish: $note_"
47     else
48         echo >&2 "* non-commit: $note_"
49     fi
50     if test "$local_name_" != ""
51     then
52         # We are storing the head locally.  Make sure that it is
53         # a fast forward (aka "reverse push").
54         fast_forward_local "$local_name_" "$head_" "$remote_" "$remote_name_"
55     fi
56 }
57
58 fast_forward_local () {
59     case "$1" in
60     refs/tags/*)
61         # Tags need not be pointing at commits so there
62         # is no way to guarantee "fast-forward" anyway.
63         echo "$2" >"$GIT_DIR/$1" ;;
64     refs/heads/*)
65         # NEEDSWORK: use the same cmpxchg protocol here.
66         echo "$2" >"$GIT_DIR/$1.lock"
67         if test -f "$GIT_DIR/$1"
68         then
69             local=$(git-rev-parse --verify "$1^0") &&
70             mb=$(git-merge-base "$local" "$2") &&
71             case "$2,$mb" in
72             $local,*)
73                 echo >&2 "* $1: same as $4"
74                 echo >&2 "  from $3"
75                 ;;
76             *,$local)
77                 echo >&2 "* $1: fast forward to $4"
78                 echo >&2 "  from $3"
79                 ;;
80             *)
81                 false
82                 ;;
83             esac || {
84                 mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1.remote"
85                 echo >&2 "* $1: does not fast forward to $4"
86                 echo >&2 "  from $3; leaving it in '$1.remote'"
87             }
88         else
89                 echo >&2 "* $1: storing $4"
90                 echo >&2 "  from $3."
91         fi
92         test -f "$GIT_DIR/$1.lock" &&
93             mv "$GIT_DIR/$1.lock" "$GIT_DIR/$1"
94         ;;
95     esac
96 }
97
98 for ref in $(get_remote_refs_for_fetch "$@")
99 do
100     refs="$refs $ref"
101
102     # These are relative path from $GIT_DIR, typically starting at refs/
103     # but may be HEAD
104     remote_name=$(expr "$ref" : '\([^:]*\):')
105     local_name=$(expr "$ref" : '[^:]*:\(.*\)')
106
107     rref="$rref $remote_name"
108
109     # There are transports that can fetch only one head at a time...
110     case "$remote" in
111     http://* | https://*)
112         if [ -n "$GIT_SSL_NO_VERIFY" ]; then
113             curl_extra_args="-k"
114         fi
115         head=$(curl -nsf $curl_extra_args "$remote/$remote_name") &&
116         expr "$head" : "$_x40\$" >/dev/null ||
117             die "Failed to fetch $remote_name from $remote"
118         echo Fetching "$remote_name from $remote" using http
119         git-http-pull -v -a "$head" "$remote/" || exit
120         ;;
121     rsync://*)
122         TMP_HEAD="$GIT_DIR/TMP_HEAD"
123         rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
124         head=$(git-rev-parse TMP_HEAD)
125         rm -f "$TMP_HEAD"
126         test "$rsync_slurped_objects" || {
127             rsync -avz --ignore-existing "$remote/objects/" \
128                 "$GIT_OBJECT_DIRECTORY/" || exit
129             rsync_slurped_objects=t
130         }
131         ;;
132     *)
133         # We will do git native transport with just one call later.
134         continue ;;
135     esac
136
137     append_fetch_head "$head" "$remote" "$remote_name" "$remote_nick" "$local_name"
138
139 done
140
141 case "$remote" in
142 http://* | https://* | rsync://* )
143     ;; # we are already done.
144 *)
145     git-fetch-pack "$remote" $rref |
146     while read sha1 remote_name
147     do
148         found=
149         for ref in $refs
150         do
151             case "$ref" in
152             $remote_name:*)
153                 found="$ref"
154                 break ;;
155             esac
156         done
157
158         local_name=$(expr "$found" : '[^:]*:\(.*\)')
159         append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name"
160     done
161     ;;
162 esac