git-parse-remote.shon commit t9200: do not test -x bit if the filesystem does not support it. (3c23d66)
   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        remote="$1"
  85        shift
  86        first_one=yes
  87        if test "$#" = 0
  88        then
  89                echo empty
  90                echo >&2 "Nothing specified for fetching with remote.$remote.fetch"
  91        fi
  92        for ref
  93        do
  94                lref=${ref#'+'}
  95                # a non glob pattern is given back as-is.
  96                expr "z$lref" : 'zrefs/.*/\*:refs/.*/\*$' >/dev/null || {
  97                        if test -n "$first_one"
  98                        then
  99                                echo "explicit"
 100                                first_one=
 101                        fi
 102                        echo "$ref"
 103                        continue
 104                }
 105
 106                # glob
 107                if test -n "$first_one"
 108                then
 109                        echo "glob"
 110                        first_one=
 111                fi
 112                from=`expr "z$lref" : 'z\(refs/.*/\)\*:refs/.*/\*$'`
 113                to=`expr "z$lref" : 'zrefs/.*/\*:\(refs/.*/\)\*$'`
 114                local_force=
 115                test "z$lref" = "z$ref" || local_force='+'
 116                echo "$ls_remote_result" |
 117                sed -e '/\^{}$/d' |
 118                (
 119                        IFS='   '
 120                        while read sha1 name
 121                        do
 122                                # ignore the ones that do not start with $from
 123                                mapped=${name#"$from"}
 124                                test "z$name" = "z$mapped" && continue
 125                                echo "${local_force}${name}:${to}${mapped}"
 126                        done
 127                )
 128        done
 129}
 130
 131# Subroutine to canonicalize remote:local notation.
 132canon_refs_list_for_fetch () {
 133        # If called from get_remote_default_refs_for_fetch
 134        # leave the branches in branch.${curr_branch}.merge alone,
 135        # or the first one otherwise; add prefix . to the rest
 136        # to prevent the secondary branches to be merged by default.
 137        merge_branches=
 138        curr_branch=
 139        if test "$1" = "-d"
 140        then
 141                shift ; remote="$1" ; shift
 142                set $(expand_refs_wildcard "$remote" "$@")
 143                is_explicit="$1"
 144                shift
 145                if test "$remote" = "$(get_default_remote)"
 146                then
 147                        curr_branch=$(git-symbolic-ref -q HEAD | \
 148                            sed -e 's|^refs/heads/||')
 149                        merge_branches=$(git-config \
 150                            --get-all "branch.${curr_branch}.merge")
 151                fi
 152                if test -z "$merge_branches" && test $is_explicit != explicit
 153                then
 154                        merge_branches=..this.will.never.match.any.ref..
 155                fi
 156        fi
 157        for ref
 158        do
 159                force=
 160                case "$ref" in
 161                +*)
 162                        ref=$(expr "z$ref" : 'z+\(.*\)')
 163                        force=+
 164                        ;;
 165                esac
 166                expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
 167                remote=$(expr "z$ref" : 'z\([^:]*\):')
 168                local=$(expr "z$ref" : 'z[^:]*:\(.*\)')
 169                dot_prefix=.
 170                if test -z "$merge_branches"
 171                then
 172                        merge_branches=$remote
 173                        dot_prefix=
 174                else
 175                        for merge_branch in $merge_branches
 176                        do
 177                            if  test "$remote" = "$merge_branch" ||
 178                                test "$local" = "$merge_branch"
 179                            then
 180                                    dot_prefix=
 181                                    break
 182                            fi
 183                        done
 184                fi
 185                case "$remote" in
 186                '' | HEAD ) remote=HEAD ;;
 187                refs/heads/* | refs/tags/* | refs/remotes/*) ;;
 188                heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
 189                *) remote="refs/heads/$remote" ;;
 190                esac
 191                case "$local" in
 192                '') local= ;;
 193                refs/heads/* | refs/tags/* | refs/remotes/*) ;;
 194                heads/* | tags/* | remotes/* ) local="refs/$local" ;;
 195                *) local="refs/heads/$local" ;;
 196                esac
 197
 198                if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
 199                then
 200                   git-check-ref-format "$local_ref_name" ||
 201                   die "* refusing to create funny ref '$local_ref_name' locally"
 202                fi
 203                echo "${dot_prefix}${force}${remote}:${local}"
 204        done
 205}
 206
 207# Returns list of src: (no store), or src:dst (store)
 208get_remote_default_refs_for_fetch () {
 209        data_source=$(get_data_source "$1")
 210        case "$data_source" in
 211        '')
 212                echo "HEAD:" ;;
 213        config)
 214                canon_refs_list_for_fetch -d "$1" \
 215                        $(git-config --get-all "remote.$1.fetch") ;;
 216        branches)
 217                remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1")
 218                case "$remote_branch" in '') remote_branch=master ;; esac
 219                echo "refs/heads/${remote_branch}:refs/heads/$1"
 220                ;;
 221        remotes)
 222                canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{
 223                                                s///p
 224                                        }' "$GIT_DIR/remotes/$1")
 225                ;;
 226        *)
 227                die "internal error: get-remote-default-ref-for-push $1" ;;
 228        esac
 229}
 230
 231get_remote_refs_for_push () {
 232        case "$#" in
 233        0) die "internal error: get-remote-refs-for-push." ;;
 234        1) get_remote_default_refs_for_push "$@" ;;
 235        *) shift; echo "$@" ;;
 236        esac
 237}
 238
 239get_remote_refs_for_fetch () {
 240        case "$#" in
 241        0)
 242            die "internal error: get-remote-refs-for-fetch." ;;
 243        1)
 244            get_remote_default_refs_for_fetch "$@" ;;
 245        *)
 246            shift
 247            tag_just_seen=
 248            for ref
 249            do
 250                if test "$tag_just_seen"
 251                then
 252                    echo "refs/tags/${ref}:refs/tags/${ref}"
 253                    tag_just_seen=
 254                    continue
 255                else
 256                    case "$ref" in
 257                    tag)
 258                        tag_just_seen=yes
 259                        continue
 260                        ;;
 261                    esac
 262                fi
 263                canon_refs_list_for_fetch "$ref"
 264            done
 265            ;;
 266        esac
 267}
 268
 269resolve_alternates () {
 270        # original URL (xxx.git)
 271        top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'`
 272        while read path
 273        do
 274                case "$path" in
 275                \#* | '')
 276                        continue ;;
 277                /*)
 278                        echo "$top_$path/" ;;
 279                ../*)
 280                        # relative -- ugly but seems to work.
 281                        echo "$1/objects/$path/" ;;
 282                *)
 283                        # exit code may not be caught by the reader.
 284                        echo "bad alternate: $path"
 285                        exit 1 ;;
 286                esac
 287        done
 288}
 289
 290get_uploadpack () {
 291        data_source=$(get_data_source "$1")
 292        case "$data_source" in
 293        config)
 294                uplp=$(git-config --get "remote.$1.uploadpack")
 295                echo ${uplp:-git-upload-pack}
 296                ;;
 297        *)
 298                echo "git-upload-pack"
 299                ;;
 300        esac
 301}