1#!/bin/sh
2# Copyright (c) 2012 Felipe Contreras
3
4# The first argument can be a url when the fetch/push command was a url
5# instead of a configured remote. In this case, use a generic alias.
6if test "$1" = "testgit::$2"; then
7	alias=_
8else
9	alias=$1
10fi
11url=$2
12
13dir="$GIT_DIR/testgit/$alias"
14
15h_refspec="refs/heads/*:refs/testgit/$alias/heads/*"
16t_refspec="refs/tags/*:refs/testgit/$alias/tags/*"
17
18if test -n "$GIT_REMOTE_TESTGIT_NOREFSPEC"
19then
20	h_refspec=""
21	t_refspec=""
22fi
23
24GIT_DIR="$url/.git"
25export GIT_DIR
26
27force=
28
29mkdir -p "$dir"
30
31if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
32then
33	gitmarks="$dir/git.marks"
34	testgitmarks="$dir/testgit.marks"
35	test -e "$gitmarks" || >"$gitmarks"
36	test -e "$testgitmarks" || >"$testgitmarks"
37fi
38
39while read line
40do
41	case $line in
42	capabilities)
43		echo 'import'
44		echo 'export'
45		test -n "$h_refspec" && echo "refspec $h_refspec"
46		test -n "$t_refspec" && echo "refspec $t_refspec"
47		if test -n "$gitmarks"
48		then
49			echo "*import-marks $gitmarks"
50			echo "*export-marks $gitmarks"
51		fi
52		test -n "$GIT_REMOTE_TESTGIT_SIGNED_TAGS" && echo "signed-tags"
53		test -n "$GIT_REMOTE_TESTGIT_NO_PRIVATE_UPDATE" && echo "no-private-update"
54		echo 'option'
55		echo 'object-format'
56		echo
57		;;
58	list)
59		echo ":object-format $(git rev-parse --show-object-format=storage)"
60		git for-each-ref --format='? %(refname)' 'refs/heads/' 'refs/tags/'
61		head=$(git symbolic-ref HEAD)
62		echo "@$head HEAD"
63		echo
64		;;
65	import*)
66		# read all import lines
67		while true
68		do
69			ref="${line#* }"
70			refs="$refs $ref"
71			read line
72			test "${line%% *}" != "import" && break
73		done
74
75		if test -n "$gitmarks"
76		then
77			echo "feature import-marks=$gitmarks"
78			echo "feature export-marks=$gitmarks"
79		fi
80
81		if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
82		then
83			echo "feature done"
84			exit 1
85		fi
86
87		echo "feature done"
88		git fast-export \
89			${h_refspec:+"--refspec=$h_refspec"} \
90			${t_refspec:+"--refspec=$t_refspec"} \
91			${testgitmarks:+"--import-marks=$testgitmarks"} \
92			${testgitmarks:+"--export-marks=$testgitmarks"} \
93			$refs
94		echo "done"
95		;;
96	export)
97		if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
98		then
99			# consume input so fast-export doesn't get SIGPIPE;
100			# git would also notice that case, but we want
101			# to make sure we are exercising the later
102			# error checks
103			while read line; do
104				test "done" = "$line" && break
105			done
106			exit 1
107		fi
108
109		before=$(git for-each-ref --format=' %(refname) %(objectname) ')
110
111		git fast-import \
112			${force:+--force} \
113			${testgitmarks:+"--import-marks=$testgitmarks"} \
114			${testgitmarks:+"--export-marks=$testgitmarks"} \
115			--quiet
116
117		# figure out which refs were updated
118		git for-each-ref --format='%(refname) %(objectname)' |
119		while read ref a
120		do
121			case "$before" in
122			*" $ref $a "*)
123				continue ;;	# unchanged
124			esac
125			if test -z "$GIT_REMOTE_TESTGIT_PUSH_ERROR"
126			then
127				echo "ok $ref"
128			else
129				echo "error $ref $GIT_REMOTE_TESTGIT_PUSH_ERROR"
130			fi
131		done
132
133		echo
134		;;
135	option\ *)
136		read cmd opt val <<-EOF
137		$line
138		EOF
139		case $opt in
140		force)
141			test $val = "true" && force="true" || force=
142			echo "ok"
143			;;
144		object-format)
145			test $val = "true" && object_format="true" || object_format=
146			echo "ok"
147			;;
148		*)
149			echo "unsupported"
150			;;
151		esac
152		;;
153	'')
154		exit
155		;;
156	esac
157done
158