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