git-parse-remote.shon commit git-fetch: rewrite expand_ref_wildcard in C (8655158)
   1#!/bin/sh
   2
   3# git-ls-remote could be called from outside a git managed repository;
   4# this would fail in that case and would issue an error message.
   5GIT_DIR=$(git-rev-parse --git-dir 2>/dev/null) || :;
   6
   7get_data_source () {
   8        case "$1" in
   9        */*)
  10                echo ''
  11                ;;
  12        *)
  13                if test "$(git-config --get "remote.$1.url")"
  14                then
  15                        echo config
  16                elif test -f "$GIT_DIR/remotes/$1"
  17                then
  18                        echo remotes
  19                elif test -f "$GIT_DIR/branches/$1"
  20                then
  21                        echo branches
  22                else
  23                        echo ''
  24                fi ;;
  25        esac
  26}
  27
  28get_remote_url () {
  29        data_source=$(get_data_source "$1")
  30        case "$data_source" in
  31        '')
  32                echo "$1"
  33                ;;
  34        config)
  35                git-config --get "remote.$1.url"
  36                ;;
  37        remotes)
  38                sed -ne '/^URL: */{
  39                        s///p
  40                        q
  41                }' "$GIT_DIR/remotes/$1"
  42                ;;
  43        branches)
  44                sed -e 's/#.*//' "$GIT_DIR/branches/$1"
  45                ;;
  46        *)
  47                die "internal error: get-remote-url $1" ;;
  48        esac
  49}
  50
  51get_default_remote () {
  52        curr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')
  53        origin=$(git-config --get "branch.$curr_branch.remote")
  54        echo ${origin:-origin}
  55}
  56
  57get_remote_default_refs_for_push () {
  58        data_source=$(get_data_source "$1")
  59        case "$data_source" in
  60        '' | branches)
  61                ;; # no default push mapping, just send matching refs.
  62        config)
  63                git-config --get-all "remote.$1.push" ;;
  64        remotes)
  65                sed -ne '/^Push: */{
  66                        s///p
  67                }' "$GIT_DIR/remotes/$1" ;;
  68        *)
  69                die "internal error: get-remote-default-ref-for-push $1" ;;
  70        esac
  71}
  72
  73# Called from canon_refs_list_for_fetch -d "$remote", which
  74# is called from get_remote_default_refs_for_fetch to grok
  75# refspecs that are retrieved from the configuration, but not
  76# from get_remote_refs_for_fetch when it deals with refspecs
  77# supplied on the command line.  $ls_remote_result has the list
  78# of refs available at remote.
  79#
  80# The first token returned is either "explicit" or "glob"; this
  81# is to help prevent randomly "globbed" ref from being chosen as
  82# a merge candidate
  83expand_refs_wildcard () {
  84        git fetch--tool expand-refs-wildcard "$ls_remote_result" "$@"
  85}
  86
  87# Subroutine to canonicalize remote:local notation.
  88canon_refs_list_for_fetch () {
  89        # If called from get_remote_default_refs_for_fetch
  90        # leave the branches in branch.${curr_branch}.merge alone,
  91        # or the first one otherwise; add prefix . to the rest
  92        # to prevent the secondary branches to be merged by default.
  93        merge_branches=
  94        curr_branch=
  95        if test "$1" = "-d"
  96        then
  97                shift ; remote="$1" ; shift
  98                set $(expand_refs_wildcard "$remote" "$@")
  99                is_explicit="$1"
 100                shift
 101                if test "$remote" = "$(get_default_remote)"
 102                then
 103                        curr_branch=$(git-symbolic-ref -q HEAD | \
 104                            sed -e 's|^refs/heads/||')
 105                        merge_branches=$(git-config \
 106                            --get-all "branch.${curr_branch}.merge")
 107                fi
 108                if test -z "$merge_branches" && test $is_explicit != explicit
 109                then
 110                        merge_branches=..this.will.never.match.any.ref..
 111                fi
 112        fi
 113        for ref
 114        do
 115                force=
 116                case "$ref" in
 117                +*)
 118                        ref=$(expr "z$ref" : 'z+\(.*\)')
 119                        force=+
 120                        ;;
 121                esac
 122                expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
 123                remote=$(expr "z$ref" : 'z\([^:]*\):')
 124                local=$(expr "z$ref" : 'z[^:]*:\(.*\)')
 125                dot_prefix=.
 126                if test -z "$merge_branches"
 127                then
 128                        merge_branches=$remote
 129                        dot_prefix=
 130                else
 131                        for merge_branch in $merge_branches
 132                        do
 133                            [ "$remote" = "$merge_branch" ] &&
 134                            dot_prefix= && break
 135                        done
 136                fi
 137                case "$remote" in
 138                '' | HEAD ) remote=HEAD ;;
 139                refs/heads/* | refs/tags/* | refs/remotes/*) ;;
 140                heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
 141                *) remote="refs/heads/$remote" ;;
 142                esac
 143                case "$local" in
 144                '') local= ;;
 145                refs/heads/* | refs/tags/* | refs/remotes/*) ;;
 146                heads/* | tags/* | remotes/* ) local="refs/$local" ;;
 147                *) local="refs/heads/$local" ;;
 148                esac
 149
 150                if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
 151                then
 152                   git-check-ref-format "$local_ref_name" ||
 153                   die "* refusing to create funny ref '$local_ref_name' locally"
 154                fi
 155                echo "${dot_prefix}${force}${remote}:${local}"
 156        done
 157}
 158
 159# Returns list of src: (no store), or src:dst (store)
 160get_remote_default_refs_for_fetch () {
 161        data_source=$(get_data_source "$1")
 162        case "$data_source" in
 163        '')
 164                echo "HEAD:" ;;
 165        config)
 166                canon_refs_list_for_fetch -d "$1" \
 167                        $(git-config --get-all "remote.$1.fetch") ;;
 168        branches)
 169                remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
 170                case "$remote_branch" in '') remote_branch=master ;; esac
 171                echo "refs/heads/${remote_branch}:refs/heads/$1"
 172                ;;
 173        remotes)
 174                canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{
 175                                                s///p
 176                                        }' "$GIT_DIR/remotes/$1")
 177                ;;
 178        *)
 179                die "internal error: get-remote-default-ref-for-push $1" ;;
 180        esac
 181}
 182
 183get_remote_refs_for_push () {
 184        case "$#" in
 185        0) die "internal error: get-remote-refs-for-push." ;;
 186        1) get_remote_default_refs_for_push "$@" ;;
 187        *) shift; echo "$@" ;;
 188        esac
 189}
 190
 191get_remote_refs_for_fetch () {
 192        case "$#" in
 193        0)
 194            die "internal error: get-remote-refs-for-fetch." ;;
 195        1)
 196            get_remote_default_refs_for_fetch "$@" ;;
 197        *)
 198            shift
 199            tag_just_seen=
 200            for ref
 201            do
 202                if test "$tag_just_seen"
 203                then
 204                    echo "refs/tags/${ref}:refs/tags/${ref}"
 205                    tag_just_seen=
 206                    continue
 207                else
 208                    case "$ref" in
 209                    tag)
 210                        tag_just_seen=yes
 211                        continue
 212                        ;;
 213                    esac
 214                fi
 215                canon_refs_list_for_fetch "$ref"
 216            done
 217            ;;
 218        esac
 219}
 220
 221resolve_alternates () {
 222        # original URL (xxx.git)
 223        top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'`
 224        while read path
 225        do
 226                case "$path" in
 227                \#* | '')
 228                        continue ;;
 229                /*)
 230                        echo "$top_$path/" ;;
 231                ../*)
 232                        # relative -- ugly but seems to work.
 233                        echo "$1/objects/$path/" ;;
 234                *)
 235                        # exit code may not be caught by the reader.
 236                        echo "bad alternate: $path"
 237                        exit 1 ;;
 238                esac
 239        done
 240}
 241
 242get_uploadpack () {
 243        data_source=$(get_data_source "$1")
 244        case "$data_source" in
 245        config)
 246                uplp=$(git-config --get "remote.$1.uploadpack")
 247                echo ${uplp:-git-upload-pack}
 248                ;;
 249        *)
 250                echo "git-upload-pack"
 251                ;;
 252        esac
 253}