Teach rsync transport about alternates.
[git.git] / git-parse-remote.sh
1 #!/bin/sh
2
3 . git-sh-setup || die "Not a git archive"
4
5 get_data_source () {
6         case "$1" in
7         */*)
8                 # Not so fast.  This could be the partial URL shorthand...
9                 token=$(expr "$1" : '\([^/]*\)/')
10                 remainder=$(expr "$1" : '[^/]*/\(.*\)')
11                 if test -f "$GIT_DIR/branches/$token"
12                 then
13                         echo branches-partial
14                 else
15                         echo ''
16                 fi
17                 ;;
18         *)
19                 if test -f "$GIT_DIR/remotes/$1"
20                 then
21                         echo remotes
22                 elif test -f "$GIT_DIR/branches/$1"
23                 then
24                         echo branches
25                 else
26                         echo ''
27                 fi ;;
28         esac
29 }
30
31 get_remote_url () {
32         data_source=$(get_data_source "$1")
33         case "$data_source" in
34         '')
35                 echo "$1" ;;
36         remotes)
37                 sed -ne '/^URL: */{
38                         s///p
39                         q
40                 }' "$GIT_DIR/remotes/$1" ;;
41         branches)
42                 sed -e 's/#.*//' "$GIT_DIR/branches/$1" ;;
43         branches-partial)
44                 token=$(expr "$1" : '\([^/]*\)/')
45                 remainder=$(expr "$1" : '[^/]*/\(.*\)')
46                 url=$(sed -e 's/#.*//' "$GIT_DIR/branches/$token")
47                 echo "$url/$remainder"
48                 ;;
49         *)
50                 die "internal error: get-remote-url $1" ;;
51         esac
52 }
53
54 get_remote_default_refs_for_push () {
55         data_source=$(get_data_source "$1")
56         case "$data_source" in
57         '' | branches | branches-partial)
58                 ;; # no default push mapping, just send matching refs.
59         remotes)
60                 sed -ne '/^Push: */{
61                         s///p
62                 }' "$GIT_DIR/remotes/$1" ;;
63         *)
64                 die "internal error: get-remote-default-ref-for-push $1" ;;
65         esac
66 }
67
68 # Subroutine to canonicalize remote:local notation
69 canon_refs_list_for_fetch () {
70         for ref
71         do
72                 force=
73                 case "$ref" in
74                 +*)
75                         ref=$(expr "$ref" : '\+\(.*\)')
76                         force=+
77                         ;;
78                 esac
79                 expr "$ref" : '.*:' >/dev/null || ref="${ref}:"
80                 remote=$(expr "$ref" : '\([^:]*\):')
81                 local=$(expr "$ref" : '[^:]*:\(.*\)')
82                 case "$remote" in
83                 '') remote=HEAD ;;
84                 refs/heads/* | refs/tags/*) ;;
85                 heads/* | tags/* ) remote="refs/$remote" ;;
86                 *) remote="refs/heads/$remote" ;;
87                 esac
88                 case "$local" in
89                 '') local= ;;
90                 refs/heads/* | refs/tags/*) ;;
91                 heads/* | tags/* ) local="refs/$local" ;;
92                 *) local="refs/heads/$local" ;;
93                 esac
94                 echo "${force}${remote}:${local}"
95         done
96 }
97
98 # Returns list of src: (no store), or src:dst (store)
99 get_remote_default_refs_for_fetch () {
100         data_source=$(get_data_source "$1")
101         case "$data_source" in
102         '' | branches-partial)
103                 echo "HEAD:" ;;
104         branches)
105                 remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
106                 case "$remote_branch" in '') remote_branch=master ;; esac
107                 echo "refs/heads/${remote_branch}:refs/heads/$1"
108                 ;;
109         remotes)
110                 canon_refs_list_for_fetch $(sed -ne '/^Pull: */{
111                                                 s///p
112                                         }' "$GIT_DIR/remotes/$1")
113                 ;;
114         *)
115                 die "internal error: get-remote-default-ref-for-push $1" ;;
116         esac
117 }
118
119 get_remote_refs_for_push () {
120         case "$#" in
121         0) die "internal error: get-remote-refs-for-push." ;;
122         1) get_remote_default_refs_for_push "$@" ;;
123         *) shift; echo "$@" ;;
124         esac
125 }
126
127 get_remote_refs_for_fetch () {
128         case "$#" in
129         0)
130             die "internal error: get-remote-refs-for-fetch." ;;
131         1)
132             get_remote_default_refs_for_fetch "$@" ;;
133         *)
134             shift
135             tag_just_seen=
136             for ref
137             do
138                 if test "$tag_just_seen"
139                 then
140                     echo "refs/tags/${ref}:refs/tags/${ref}"
141                     tag_just_seen=
142                     continue
143                 else
144                     case "$ref" in
145                     tag)
146                         tag_just_seen=yes
147                         continue
148                         ;;
149                     esac
150                 fi
151                 canon_refs_list_for_fetch "$ref"
152             done
153             ;;
154         esac
155 }
156
157 resolve_alternates () {
158         # original URL (xxx.git)
159         top_=`expr "$1" : '\([^:]*:/*[^/]*\)/'`
160         while read path
161         do
162                 case "$path" in
163                 \#* | '')
164                         continue ;;
165                 /*)
166                         echo "$top_$path/" ;;
167                 ../*)
168                         # relative -- ugly but seems to work.
169                         echo "$1/objects/$path/" ;;
170                 *)
171                         # exit code may not be caught by the reader.
172                         echo "bad alternate: $path"
173                         exit 1 ;;
174                 esac
175         done
176 }