| #!/bin/sh | 
 |  | 
 | # git-ls-remote could be called from outside a git managed repository; | 
 | # this would fail in that case and would issue an error message. | 
 | GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) || :; | 
 |  | 
 | get_data_source () { | 
 | 	case "$1" in | 
 | 	*/*) | 
 | 		echo '' | 
 | 		;; | 
 | 	.) | 
 | 		echo self | 
 | 		;; | 
 | 	*) | 
 | 		if test "$(git config --get "remote.$1.url")" | 
 | 		then | 
 | 			echo config | 
 | 		elif test -f "$GIT_DIR/remotes/$1" | 
 | 		then | 
 | 			echo remotes | 
 | 		elif test -f "$GIT_DIR/branches/$1" | 
 | 		then | 
 | 			echo branches | 
 | 		else | 
 | 			echo '' | 
 | 		fi ;; | 
 | 	esac | 
 | } | 
 |  | 
 | get_remote_url () { | 
 | 	data_source=$(get_data_source "$1") | 
 | 	case "$data_source" in | 
 | 	'') | 
 | 		echo "$1" | 
 | 		;; | 
 | 	self) | 
 | 		echo "$1" | 
 | 		;; | 
 | 	config) | 
 | 		git config --get "remote.$1.url" | 
 | 		;; | 
 | 	remotes) | 
 | 		sed -ne '/^URL: */{ | 
 | 			s///p | 
 | 			q | 
 | 		}' "$GIT_DIR/remotes/$1" | 
 | 		;; | 
 | 	branches) | 
 | 		sed -e 's/#.*//' "$GIT_DIR/branches/$1" | 
 | 		;; | 
 | 	*) | 
 | 		die "internal error: get-remote-url $1" ;; | 
 | 	esac | 
 | } | 
 |  | 
 | get_default_remote () { | 
 | 	curr_branch=$(git symbolic-ref -q HEAD | sed -e 's|^refs/heads/||') | 
 | 	origin=$(git config --get "branch.$curr_branch.remote") | 
 | 	echo ${origin:-origin} | 
 | } | 
 |  | 
 | get_remote_default_refs_for_push () { | 
 | 	data_source=$(get_data_source "$1") | 
 | 	case "$data_source" in | 
 | 	'' | branches | self) | 
 | 		;; # no default push mapping, just send matching refs. | 
 | 	config) | 
 | 		git config --get-all "remote.$1.push" ;; | 
 | 	remotes) | 
 | 		sed -ne '/^Push: */{ | 
 | 			s///p | 
 | 		}' "$GIT_DIR/remotes/$1" ;; | 
 | 	*) | 
 | 		die "internal error: get-remote-default-ref-for-push $1" ;; | 
 | 	esac | 
 | } | 
 |  | 
 | # Called from canon_refs_list_for_fetch -d "$remote", which | 
 | # is called from get_remote_default_refs_for_fetch to grok | 
 | # refspecs that are retrieved from the configuration, but not | 
 | # from get_remote_refs_for_fetch when it deals with refspecs | 
 | # supplied on the command line.  $ls_remote_result has the list | 
 | # of refs available at remote. | 
 | # | 
 | # The first token returned is either "explicit" or "glob"; this | 
 | # is to help prevent randomly "globbed" ref from being chosen as | 
 | # a merge candidate | 
 | expand_refs_wildcard () { | 
 | 	echo "$ls_remote_result" | | 
 | 	git fetch--tool expand-refs-wildcard "-" "$@" | 
 | } | 
 |  | 
 | # Subroutine to canonicalize remote:local notation. | 
 | canon_refs_list_for_fetch () { | 
 | 	# If called from get_remote_default_refs_for_fetch | 
 | 	# leave the branches in branch.${curr_branch}.merge alone, | 
 | 	# or the first one otherwise; add prefix . to the rest | 
 | 	# to prevent the secondary branches to be merged by default. | 
 | 	merge_branches= | 
 | 	curr_branch= | 
 | 	if test "$1" = "-d" | 
 | 	then | 
 | 		shift ; remote="$1" ; shift | 
 | 		set $(expand_refs_wildcard "$remote" "$@") | 
 | 		is_explicit="$1" | 
 | 		shift | 
 | 		if test "$remote" = "$(get_default_remote)" | 
 | 		then | 
 | 			curr_branch=$(git symbolic-ref -q HEAD | \ | 
 | 			    sed -e 's|^refs/heads/||') | 
 | 			merge_branches=$(git config \ | 
 | 			    --get-all "branch.${curr_branch}.merge") | 
 | 		fi | 
 | 		if test -z "$merge_branches" && test $is_explicit != explicit | 
 | 		then | 
 | 			merge_branches=..this.will.never.match.any.ref.. | 
 | 		fi | 
 | 	fi | 
 | 	for ref | 
 | 	do | 
 | 		force= | 
 | 		case "$ref" in | 
 | 		+*) | 
 | 			ref=$(expr "z$ref" : 'z+\(.*\)') | 
 | 			force=+ | 
 | 			;; | 
 | 		esac | 
 | 		expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" | 
 | 		remote=$(expr "z$ref" : 'z\([^:]*\):') | 
 | 		local=$(expr "z$ref" : 'z[^:]*:\(.*\)') | 
 | 		dot_prefix=. | 
 | 		if test -z "$merge_branches" | 
 | 		then | 
 | 			merge_branches=$remote | 
 | 			dot_prefix= | 
 | 		else | 
 | 			for merge_branch in $merge_branches | 
 | 			do | 
 | 			    [ "$remote" = "$merge_branch" ] && | 
 | 			    dot_prefix= && break | 
 | 			done | 
 | 		fi | 
 | 		case "$remote" in | 
 | 		'' | HEAD ) remote=HEAD ;; | 
 | 		refs/*) ;; | 
 | 		heads/* | tags/* | remotes/* ) remote="refs/$remote" ;; | 
 | 		*) remote="refs/heads/$remote" ;; | 
 | 		esac | 
 | 		case "$local" in | 
 | 		'') local= ;; | 
 | 		refs/*) ;; | 
 | 		heads/* | tags/* | remotes/* ) local="refs/$local" ;; | 
 | 		*) local="refs/heads/$local" ;; | 
 | 		esac | 
 |  | 
 | 		if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)') | 
 | 		then | 
 | 		   git check-ref-format "$local_ref_name" || | 
 | 		   die "* refusing to create funny ref '$local_ref_name' locally" | 
 | 		fi | 
 | 		echo "${dot_prefix}${force}${remote}:${local}" | 
 | 	done | 
 | } | 
 |  | 
 | # Returns list of src: (no store), or src:dst (store) | 
 | get_remote_default_refs_for_fetch () { | 
 | 	data_source=$(get_data_source "$1") | 
 | 	case "$data_source" in | 
 | 	'') | 
 | 		echo "HEAD:" ;; | 
 | 	self) | 
 | 	        canon_refs_list_for_fetch -d "$1" \ | 
 | 			$(git for-each-ref --format='%(refname):') | 
 | 		;; | 
 | 	config) | 
 | 		canon_refs_list_for_fetch -d "$1" \ | 
 | 			$(git config --get-all "remote.$1.fetch") ;; | 
 | 	branches) | 
 | 		remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1") | 
 | 		case "$remote_branch" in '') remote_branch=master ;; esac | 
 | 		echo "refs/heads/${remote_branch}:refs/heads/$1" | 
 | 		;; | 
 | 	remotes) | 
 | 		canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{ | 
 | 						s///p | 
 | 					}' "$GIT_DIR/remotes/$1") | 
 | 		;; | 
 | 	*) | 
 | 		die "internal error: get-remote-default-ref-for-fetch $1" ;; | 
 | 	esac | 
 | } | 
 |  | 
 | get_remote_refs_for_push () { | 
 | 	case "$#" in | 
 | 	0) die "internal error: get-remote-refs-for-push." ;; | 
 | 	1) get_remote_default_refs_for_push "$@" ;; | 
 | 	*) shift; echo "$@" ;; | 
 | 	esac | 
 | } | 
 |  | 
 | get_remote_refs_for_fetch () { | 
 | 	case "$#" in | 
 | 	0) | 
 | 	    die "internal error: get-remote-refs-for-fetch." ;; | 
 | 	1) | 
 | 	    get_remote_default_refs_for_fetch "$@" ;; | 
 | 	*) | 
 | 	    shift | 
 | 	    tag_just_seen= | 
 | 	    for ref | 
 | 	    do | 
 | 		if test "$tag_just_seen" | 
 | 		then | 
 | 		    echo "refs/tags/${ref}:refs/tags/${ref}" | 
 | 		    tag_just_seen= | 
 | 		    continue | 
 | 		else | 
 | 		    case "$ref" in | 
 | 		    tag) | 
 | 			tag_just_seen=yes | 
 | 			continue | 
 | 			;; | 
 | 		    esac | 
 | 		fi | 
 | 		canon_refs_list_for_fetch "$ref" | 
 | 	    done | 
 | 	    ;; | 
 | 	esac | 
 | } | 
 |  | 
 | resolve_alternates () { | 
 | 	# original URL (xxx.git) | 
 | 	top_=`expr "z$1" : 'z\([^:]*:/*[^/]*\)/'` | 
 | 	while read path | 
 | 	do | 
 | 		case "$path" in | 
 | 		\#* | '') | 
 | 			continue ;; | 
 | 		/*) | 
 | 			echo "$top_$path/" ;; | 
 | 		../*) | 
 | 			# relative -- ugly but seems to work. | 
 | 			echo "$1/objects/$path/" ;; | 
 | 		*) | 
 | 			# exit code may not be caught by the reader. | 
 | 			echo "bad alternate: $path" | 
 | 			exit 1 ;; | 
 | 		esac | 
 | 	done | 
 | } | 
 |  | 
 | get_uploadpack () { | 
 | 	data_source=$(get_data_source "$1") | 
 | 	case "$data_source" in | 
 | 	config) | 
 | 		uplp=$(git config --get "remote.$1.uploadpack") | 
 | 		echo ${uplp:-git-upload-pack} | 
 | 		;; | 
 | 	*) | 
 | 		echo "git-upload-pack" | 
 | 		;; | 
 | 	esac | 
 | } |