diff options
| author | Junio C Hamano <gitster@pobox.com> | 2012-09-12 14:08:05 -0700 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2012-09-12 14:08:05 -0700 | 
| commit | 3503e9ab32c7a478d0d985171c50a901a2695162 (patch) | |
| tree | 3fdddd11cc1cfe64e0d69c0ebcc92eac8dc77ced | |
| parent | cbd6b089e821a4ff35970531b26e64a2e621ff04 (diff) | |
| parent | 1403db49b80630cf8c36ba3e8b0f085ea0ab8286 (diff) | |
| download | git-3503e9ab32c7a478d0d985171c50a901a2695162.tar.gz | |
Merge branch 'maint-1.7.11' into maint
| -rw-r--r-- | Documentation/git-checkout.txt | 6 | ||||
| -rw-r--r-- | Documentation/revisions.txt | 7 | ||||
| -rw-r--r-- | builtin/apply.c | 68 | ||||
| -rw-r--r-- | builtin/for-each-ref.c | 4 | ||||
| -rw-r--r-- | builtin/rev-parse.c | 16 | ||||
| -rw-r--r-- | http.c | 55 | ||||
| -rw-r--r-- | http.h | 1 | ||||
| -rw-r--r-- | remote-curl.c | 23 | ||||
| -rw-r--r-- | revision.c | 16 | ||||
| -rw-r--r-- | t/lib-httpd.sh | 39 | ||||
| -rw-r--r-- | t/lib-httpd/apache.conf | 25 | ||||
| -rwxr-xr-x | t/t1506-rev-parse-diagnosis.sh | 14 | ||||
| -rwxr-xr-x | t/t4103-apply-binary.sh | 54 | ||||
| -rwxr-xr-x | t/t4202-log.sh | 7 | ||||
| -rwxr-xr-x | t/t5540-http-push.sh | 17 | ||||
| -rwxr-xr-x | t/t5541-http-push.sh | 26 | ||||
| -rwxr-xr-x | t/t5550-http-fetch.sh | 75 | ||||
| -rwxr-xr-x | t/t5551-http-fetch.sh | 20 | ||||
| -rwxr-xr-x | t/t6300-for-each-ref.sh | 10 | 
19 files changed, 321 insertions, 162 deletions
| diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 63a251612a..11cc7f0588 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -84,11 +84,11 @@ entries; instead, unmerged entries are ignored.  	When checking out paths from the index, check out stage #2  	('ours') or #3 ('theirs') for unmerged paths. --b:: +-b <new_branch>::  	Create a new branch named <new_branch> and start it at  	<start_point>; see linkgit:git-branch[1] for details. --B:: +-B <new_branch>::  	Creates the branch <new_branch> and start it at <start_point>;  	if it already exists, then reset it to <start_point>. This is  	equivalent to running "git branch" with "-f"; see @@ -124,7 +124,7 @@ explicitly give a name with '-b' in such a case.  	<commit> is not a branch name.  See the "DETACHED HEAD" section  	below for details. ---orphan:: +--orphan <new_branch>::  	Create a new 'orphan' branch, named <new_branch>, started from  	<start_point> and switch to it.  The first commit made on this  	new branch will have no parents and it will be the root of a new diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt index dc0070bcb7..69d996bc38 100644 --- a/Documentation/revisions.txt +++ b/Documentation/revisions.txt @@ -213,6 +213,13 @@ of 'r1' and 'r2' and is defined as  It is the set of commits that are reachable from either one of  'r1' or 'r2' but not from both. +In these two shorthands, you can omit one end and let it default to HEAD. +For example, 'origin..' is a shorthand for 'origin..HEAD' and asks "What +did I do since I forked from the origin branch?"  Similarly, '..origin' +is a shorthand for 'HEAD..origin' and asks "What did the origin do since +I forked from them?"  Note that '..' would mean 'HEAD..HEAD' which is an +empty range that is both reachable and unreachable from HEAD. +  Two other shorthands for naming a set that is formed by a commit  and its parent commits exist.  The 'r1{caret}@' notation means all  parents of 'r1'.  'r1{caret}!' includes commit 'r1' but excludes diff --git a/builtin/apply.c b/builtin/apply.c index 3bf71dc452..ca8695ad31 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1095,15 +1095,23 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch)  	return -1;  } -static const char *stop_at_slash(const char *line, int llen) +/* + * Skip p_value leading components from "line"; as we do not accept + * absolute paths, return NULL in that case. + */ +static const char *skip_tree_prefix(const char *line, int llen)  { -	int nslash = p_value; +	int nslash;  	int i; +	if (!p_value) +		return (llen && line[0] == '/') ? NULL : line; + +	nslash = p_value;  	for (i = 0; i < llen; i++) {  		int ch = line[i];  		if (ch == '/' && --nslash <= 0) -			return &line[i]; +			return (i == 0) ? NULL : &line[i + 1];  	}  	return NULL;  } @@ -1133,12 +1141,11 @@ static char *git_header_name(const char *line, int llen)  		if (unquote_c_style(&first, line, &second))  			goto free_and_fail1; -		/* advance to the first slash */ -		cp = stop_at_slash(first.buf, first.len); -		/* we do not accept absolute paths */ -		if (!cp || cp == first.buf) +		/* strip the a/b prefix including trailing slash */ +		cp = skip_tree_prefix(first.buf, first.len); +		if (!cp)  			goto free_and_fail1; -		strbuf_remove(&first, 0, cp + 1 - first.buf); +		strbuf_remove(&first, 0, cp - first.buf);  		/*  		 * second points at one past closing dq of name. @@ -1152,22 +1159,21 @@ static char *git_header_name(const char *line, int llen)  		if (*second == '"') {  			if (unquote_c_style(&sp, second, NULL))  				goto free_and_fail1; -			cp = stop_at_slash(sp.buf, sp.len); -			if (!cp || cp == sp.buf) +			cp = skip_tree_prefix(sp.buf, sp.len); +			if (!cp)  				goto free_and_fail1;  			/* They must match, otherwise ignore */ -			if (strcmp(cp + 1, first.buf)) +			if (strcmp(cp, first.buf))  				goto free_and_fail1;  			strbuf_release(&sp);  			return strbuf_detach(&first, NULL);  		}  		/* unquoted second */ -		cp = stop_at_slash(second, line + llen - second); -		if (!cp || cp == second) +		cp = skip_tree_prefix(second, line + llen - second); +		if (!cp)  			goto free_and_fail1; -		cp++; -		if (line + llen - cp != first.len + 1 || +		if (line + llen - cp != first.len ||  		    memcmp(first.buf, cp, first.len))  			goto free_and_fail1;  		return strbuf_detach(&first, NULL); @@ -1179,10 +1185,9 @@ static char *git_header_name(const char *line, int llen)  	}  	/* unquoted first name */ -	name = stop_at_slash(line, llen); -	if (!name || name == line) +	name = skip_tree_prefix(line, llen); +	if (!name)  		return NULL; -	name++;  	/*  	 * since the first name is unquoted, a dq if exists must be @@ -1196,10 +1201,9 @@ static char *git_header_name(const char *line, int llen)  			if (unquote_c_style(&sp, second, NULL))  				goto free_and_fail2; -			np = stop_at_slash(sp.buf, sp.len); -			if (!np || np == sp.buf) +			np = skip_tree_prefix(sp.buf, sp.len); +			if (!np)  				goto free_and_fail2; -			np++;  			len = sp.buf + sp.len - np;  			if (len < second - name && @@ -1231,13 +1235,27 @@ static char *git_header_name(const char *line, int llen)  		case '\n':  			return NULL;  		case '\t': case ' ': -			second = stop_at_slash(name + len, line_len - len); +			/* +			 * Is this the separator between the preimage +			 * and the postimage pathname?  Again, we are +			 * only interested in the case where there is +			 * no rename, as this is only to set def_name +			 * and a rename patch has the names elsewhere +			 * in an unambiguous form. +			 */ +			if (!name[len + 1]) +				return NULL; /* no postimage name */ +			second = skip_tree_prefix(name + len + 1, +						  line_len - (len + 1));  			if (!second)  				return NULL; -			second++; -			if (second[len] == '\n' && !strncmp(name, second, len)) { +			/* +			 * Does len bytes starting at "name" and "second" +			 * (that are separated by one HT or SP we just +			 * found) exactly match? +			 */ +			if (second[len] == '\n' && !strncmp(name, second, len))  				return xmemdupz(name, len); -			}  		}  	}  } diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index b01d76a243..0c5294e5e8 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -962,7 +962,9 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset)  	if (!arg) /* should --no-sort void the list ? */  		return -1; -	*sort_tail = s = xcalloc(1, sizeof(*s)); +	s = xcalloc(1, sizeof(*s)); +	s->next = *sort_tail; +	*sort_tail = s;  	if (*arg == '-') {  		s->reverse = 1; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 32788a9f86..25e225f067 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -230,6 +230,7 @@ static int try_difference(const char *arg)  	const char *next;  	const char *this;  	int symmetric; +	static const char head_by_default[] = "HEAD";  	if (!(dotdot = strstr(arg, "..")))  		return 0; @@ -241,9 +242,20 @@ static int try_difference(const char *arg)  	next += symmetric;  	if (!*next) -		next = "HEAD"; +		next = head_by_default;  	if (dotdot == arg) -		this = "HEAD"; +		this = head_by_default; + +	if (this == head_by_default && next == head_by_default && +	    !symmetric) { +		/* +		 * Just ".."?  That is not a range but the +		 * pathspec for the parent directory. +		 */ +		*dotdot = '.'; +		return 0; +	} +  	if (!get_sha1_committish(this, sha1) && !get_sha1_committish(next, end)) {  		show_rev(NORMAL, end, next);  		show_rev(symmetric ? NORMAL : REVERSED, sha1, this); @@ -745,6 +745,35 @@ char *get_remote_object_url(const char *url, const char *hex,  	return strbuf_detach(&buf, NULL);  } +int handle_curl_result(struct active_request_slot *slot) +{ +	struct slot_results *results = slot->results; + +	if (results->curl_result == CURLE_OK) { +		credential_approve(&http_auth); +		return HTTP_OK; +	} else if (missing_target(results)) +		return HTTP_MISSING_TARGET; +	else if (results->http_code == 401) { +		if (http_auth.username && http_auth.password) { +			credential_reject(&http_auth); +			return HTTP_NOAUTH; +		} else { +			credential_fill(&http_auth); +			init_curl_http_auth(slot->curl); +			return HTTP_REAUTH; +		} +	} else { +#if LIBCURL_VERSION_NUM >= 0x070c00 +		if (!curl_errorstr[0]) +			strlcpy(curl_errorstr, +				curl_easy_strerror(results->curl_result), +				sizeof(curl_errorstr)); +#endif +		return HTTP_ERROR; +	} +} +  /* http_request() targets */  #define HTTP_REQUEST_STRBUF	0  #define HTTP_REQUEST_FILE	1 @@ -792,28 +821,7 @@ static int http_request(const char *url, void *result, int target, int options)  	if (start_active_slot(slot)) {  		run_active_slot(slot); -		if (results.curl_result == CURLE_OK) -			ret = HTTP_OK; -		else if (missing_target(&results)) -			ret = HTTP_MISSING_TARGET; -		else if (results.http_code == 401) { -			if (http_auth.username && http_auth.password) { -				credential_reject(&http_auth); -				ret = HTTP_NOAUTH; -			} else { -				credential_fill(&http_auth); -				init_curl_http_auth(slot->curl); -				ret = HTTP_REAUTH; -			} -		} else { -#if LIBCURL_VERSION_NUM >= 0x070c00 -			if (!curl_errorstr[0]) -				strlcpy(curl_errorstr, -					curl_easy_strerror(results.curl_result), -					sizeof(curl_errorstr)); -#endif -			ret = HTTP_ERROR; -		} +		ret = handle_curl_result(slot);  	} else {  		error("Unable to start HTTP request for %s", url);  		ret = HTTP_START_FAILED; @@ -822,9 +830,6 @@ static int http_request(const char *url, void *result, int target, int options)  	curl_slist_free_all(headers);  	strbuf_release(&buf); -	if (ret == HTTP_OK) -		credential_approve(&http_auth); -  	return ret;  } @@ -78,6 +78,7 @@ extern int start_active_slot(struct active_request_slot *slot);  extern void run_active_slot(struct active_request_slot *slot);  extern void finish_active_slot(struct active_request_slot *slot);  extern void finish_all_active_slots(void); +extern int handle_curl_result(struct active_request_slot *slot);  #ifdef USE_CURL_MULTI  extern void fill_active_slots(void); diff --git a/remote-curl.c b/remote-curl.c index 04a9d6277d..3ec474fc63 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -362,16 +362,17 @@ static size_t rpc_in(char *ptr, size_t eltsize,  static int run_slot(struct active_request_slot *slot)  { -	int err = 0; +	int err;  	struct slot_results results;  	slot->results = &results;  	slot->curl_result = curl_easy_perform(slot->curl);  	finish_active_slot(slot); -	if (results.curl_result != CURLE_OK) { -		err |= error("RPC failed; result=%d, HTTP code = %ld", -			results.curl_result, results.http_code); +	err = handle_curl_result(slot); +	if (err != HTTP_OK && err != HTTP_REAUTH) { +		error("RPC failed; result=%d, HTTP code = %ld", +		      results.curl_result, results.http_code);  	}  	return err; @@ -436,9 +437,11 @@ static int post_rpc(struct rpc_state *rpc)  	}  	if (large_request) { -		err = probe_rpc(rpc); -		if (err) -			return err; +		do { +			err = probe_rpc(rpc); +		} while (err == HTTP_REAUTH); +		if (err != HTTP_OK) +			return -1;  	}  	slot = get_active_slot(); @@ -525,7 +528,11 @@ static int post_rpc(struct rpc_state *rpc)  	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);  	curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc); -	err = run_slot(slot); +	do { +		err = run_slot(slot); +	} while (err == HTTP_REAUTH && !large_request && !use_gzip); +	if (err != HTTP_OK) +		err = -1;  	curl_slist_free_all(headers);  	free(gzip_body); diff --git a/revision.c b/revision.c index 442a945233..cbcae1086b 100644 --- a/revision.c +++ b/revision.c @@ -1134,15 +1134,27 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi  		const char *this = arg;  		int symmetric = *next == '.';  		unsigned int flags_exclude = flags ^ UNINTERESTING; +		static const char head_by_default[] = "HEAD";  		unsigned int a_flags;  		*dotdot = 0;  		next += symmetric;  		if (!*next) -			next = "HEAD"; +			next = head_by_default;  		if (dotdot == arg) -			this = "HEAD"; +			this = head_by_default; +		if (this == head_by_default && next == head_by_default && +		    !symmetric) { +			/* +			 * Just ".."?  That is not a range but the +			 * pathspec for the parent directory. +			 */ +			if (!cant_be_filename) { +				*dotdot = '.'; +				return -1; +			} +		}  		if (!get_sha1_committish(this, from_sha1) &&  		    !get_sha1_committish(next, sha1)) {  			struct commit *a, *b; diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index d773542680..02f442bfad 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -167,3 +167,42 @@ test_http_push_nonff() {  		test_i18ngrep "Updates were rejected because" output  	'  } + +setup_askpass_helper() { +	test_expect_success 'setup askpass helper' ' +		write_script "$TRASH_DIRECTORY/askpass" <<-\EOF && +		echo >>"$TRASH_DIRECTORY/askpass-query" "askpass: $*" && +		cat "$TRASH_DIRECTORY/askpass-response" +		EOF +		GIT_ASKPASS="$TRASH_DIRECTORY/askpass" && +		export GIT_ASKPASS && +		export TRASH_DIRECTORY +	' +} + +set_askpass() { +	>"$TRASH_DIRECTORY/askpass-query" && +	echo "$*" >"$TRASH_DIRECTORY/askpass-response" +} + +expect_askpass() { +	dest=$HTTPD_DEST +	{ +		case "$1" in +		none) +			;; +		pass) +			echo "askpass: Password for 'http://$2@$dest': " +			;; +		both) +			echo "askpass: Username for 'http://$dest': " +			echo "askpass: Password for 'http://$2@$dest': " +			;; +		*) +			false +			;; +		esac +	} >"$TRASH_DIRECTORY/askpass-expect" && +	test_cmp "$TRASH_DIRECTORY/askpass-expect" \ +		 "$TRASH_DIRECTORY/askpass-query" +} diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 36b1596a10..49d5d877ce 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -46,24 +46,22 @@ PassEnv GIT_VALGRIND  PassEnv GIT_VALGRIND_OPTIONS  Alias /dumb/ www/ -Alias /auth/ www/auth/ +Alias /auth/dumb/ www/auth/dumb/ -<Location /smart/> +<LocationMatch /smart/>  	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}  	SetEnv GIT_HTTP_EXPORT_ALL -</Location> -<Location /smart_noexport/> +</LocationMatch> +<LocationMatch /smart_noexport/>  	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} -</Location> -<Location /smart_custom_env/> +</LocationMatch> +<LocationMatch /smart_custom_env/>  	SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}  	SetEnv GIT_HTTP_EXPORT_ALL  	SetEnv GIT_COMMITTER_NAME "Custom User"  	SetEnv GIT_COMMITTER_EMAIL custom@example.com -</Location> -ScriptAlias /smart/ ${GIT_EXEC_PATH}/git-http-backend/ -ScriptAlias /smart_noexport/ ${GIT_EXEC_PATH}/git-http-backend/ -ScriptAlias /smart_custom_env/ ${GIT_EXEC_PATH}/git-http-backend/ +</LocationMatch> +ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1  <Directory ${GIT_EXEC_PATH}>  	Options FollowSymlinks  </Directory> @@ -94,6 +92,13 @@ SSLEngine On  	Require valid-user  </Location> +<LocationMatch "^/auth-push/.*/git-receive-pack$"> +	AuthType Basic +	AuthName "git-auth" +	AuthUserFile passwd +	Require valid-user +</LocationMatch> +  <IfDefine DAV>  	LoadModule dav_module modules/mod_dav.so  	LoadModule dav_fs_module modules/mod_dav_fs.so diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index c5cb77a0e1..f950c10128 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -182,4 +182,18 @@ test_expect_success '<commit>:file correctly diagnosed after a pathname' '  	test_cmp expect actual  ' +test_expect_success 'dotdot is not an empty set' ' +	( H=$(git rev-parse HEAD) && echo $H && echo ^$H ) >expect && + +	git rev-parse HEAD.. >actual && +	test_cmp expect actual && + +	git rev-parse ..HEAD >actual && +	test_cmp expect actual && + +	echo .. >expect && +	git rev-parse .. >actual && +	test_cmp expect actual +' +  test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index 99627bc6d6..b1b906b1bb 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -8,30 +8,28 @@ test_description='git apply handling binary patches  '  . ./test-lib.sh -# setup - -cat >file1 <<EOF -A quick brown fox jumps over the lazy dog. -A tiny little penguin runs around in circles. -There is a flag with Linux written on it. -A slow black-and-white panda just sits there, -munching on his bamboo. -EOF -cat file1 >file2 -cat file1 >file4 - -test_expect_success 'setup' " +test_expect_success 'setup' ' +	cat >file1 <<-\EOF && +	A quick brown fox jumps over the lazy dog. +	A tiny little penguin runs around in circles. +	There is a flag with Linux written on it. +	A slow black-and-white panda just sits there, +	munching on his bamboo. +	EOF +	cat file1 >file2 && +	cat file1 >file4 && +  	git update-index --add --remove file1 file2 file4 && -	git commit -m 'Initial Version' 2>/dev/null && +	git commit -m "Initial Version" 2>/dev/null &&  	git checkout -b binary && -	"$PERL_PATH" -pe 'y/x/\000/' <file1 >file3 && +	"$PERL_PATH" -pe "y/x/\000/" <file1 >file3 &&  	cat file3 >file4 &&  	git add file2 && -	"$PERL_PATH" -pe 'y/\000/v/' <file3 >file1 && +	"$PERL_PATH" -pe "y/\000/v/" <file3 >file1 &&  	rm -f file2 &&  	git update-index --add --remove file1 file2 file3 file4 && -	git commit -m 'Second Version' && +	git commit -m "Second Version" &&  	git diff-tree -p master binary >B.diff &&  	git diff-tree -p -C master binary >C.diff && @@ -42,17 +40,25 @@ test_expect_success 'setup' "  	git diff-tree -p --full-index master binary >B-index.diff &&  	git diff-tree -p -C --full-index master binary >C-index.diff && +	git diff-tree -p --binary --no-prefix master binary -- file3 >B0.diff && +  	git init other-repo && -	(cd other-repo && -	 git fetch .. master && -	 git reset --hard FETCH_HEAD +	( +		cd other-repo && +		git fetch .. master && +		git reset --hard FETCH_HEAD  	) -" +'  test_expect_success 'stat binary diff -- should not fail.' \  	'git checkout master &&  	 git apply --stat --summary B.diff' +test_expect_success 'stat binary -p0 diff -- should not fail.' ' +	 git checkout master && +	 git apply --stat -p0 B0.diff +' +  test_expect_success 'stat binary diff (copy) -- should not fail.' \  	'git checkout master &&  	 git apply --stat --summary C.diff' @@ -143,4 +149,10 @@ test_expect_success 'apply binary diff (copy).' \  	 git apply --allow-binary-replacement --index CF.diff &&  	 test -z "$(git diff --name-status binary)"' +test_expect_success 'apply binary -p0 diff' ' +	do_reset && +	git apply -p0 --index B0.diff && +	test -z "$(git diff --name-status binary -- file3)" +' +  test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 71be59d446..45058cc8cb 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -806,4 +806,11 @@ test_expect_success 'log --graph with diff and stats' '  	test_cmp expect actual.sanitized  ' +test_expect_success 'dotdot is a parent directory' ' +	mkdir -p a/b && +	( echo sixth && echo fifth ) >expect && +	( cd a/b && git log --format=%s .. ) >actual && +	test_cmp expect actual +' +  test_done diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh index 1eea647656..f141f2d1da 100755 --- a/t/t5540-http-push.sh +++ b/t/t5540-http-push.sh @@ -46,15 +46,7 @@ test_expect_success 'create password-protected repository' '  	       "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git"  ' -test_expect_success 'setup askpass helper' ' -	cat >askpass <<-\EOF && -	#!/bin/sh -	echo user@host -	EOF -	chmod +x askpass && -	GIT_ASKPASS="$PWD/askpass" && -	export GIT_ASKPASS -' +setup_askpass_helper  test_expect_success 'clone remote repository' '  	cd "$ROOT_PATH" && @@ -162,6 +154,7 @@ test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \  test_expect_success 'push to password-protected repository (user in URL)' '  	test_commit pw-user && +	set_askpass user@host &&  	git push "$HTTPD_URL_USER/auth/dumb/test_repo.git" HEAD &&  	git rev-parse --verify HEAD >expect &&  	git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \ @@ -169,9 +162,15 @@ test_expect_success 'push to password-protected repository (user in URL)' '  	test_cmp expect actual  ' +test_expect_failure 'user was prompted only once for password' ' +	expect_askpass pass user@host +' +  test_expect_failure 'push to password-protected repository (no user in URL)' '  	test_commit pw-nouser && +	set_askpass user@host &&  	git push "$HTTPD_URL/auth/dumb/test_repo.git" HEAD && +	expect_askpass both user@host  	git rev-parse --verify HEAD >expect &&  	git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/test_repo.git" \  		rev-parse --verify HEAD >actual && diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh index 312e484090..ef6d6b6e4e 100755 --- a/t/t5541-http-push.sh +++ b/t/t5541-http-push.sh @@ -36,6 +36,8 @@ test_expect_success 'setup remote repository' '  	mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"  ' +setup_askpass_helper +  cat >exp <<EOF  GET  /smart/test_repo.git/info/refs?service=git-upload-pack HTTP/1.1 200  POST /smart/test_repo.git/git-upload-pack HTTP/1.1 200 @@ -266,5 +268,29 @@ test_expect_success 'http push respects GIT_COMMITTER_* in reflog' '  	test_cmp expect actual  ' +test_expect_success 'push over smart http with auth' ' +	cd "$ROOT_PATH/test_repo_clone" && +	echo push-auth-test >expect && +	test_commit push-auth-test && +	set_askpass user@host && +	git push "$HTTPD_URL"/auth/smart/test_repo.git && +	git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ +		log -1 --format=%s >actual && +	expect_askpass both user@host && +	test_cmp expect actual +' + +test_expect_success 'push to auth-only-for-push repo' ' +	cd "$ROOT_PATH/test_repo_clone" && +	echo push-half-auth >expect && +	test_commit push-half-auth && +	set_askpass user@host && +	git push "$HTTPD_URL"/auth-push/smart/test_repo.git && +	git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \ +		log -1 --format=%s >actual && +	expect_askpass both user@host && +	test_cmp expect actual +' +  stop_httpd  test_done diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh index b06f817af3..16ef0419e9 100755 --- a/t/t5550-http-fetch.sh +++ b/t/t5550-http-fetch.sh @@ -41,68 +41,34 @@ test_expect_success 'clone http repository' '  '  test_expect_success 'create password-protected repository' ' -	mkdir "$HTTPD_DOCUMENT_ROOT_PATH/auth/" && +	mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&  	cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \ -	       "$HTTPD_DOCUMENT_ROOT_PATH/auth/repo.git" -' - -test_expect_success 'setup askpass helpers' ' -	cat >askpass <<-EOF && -	#!/bin/sh -	echo >>"$PWD/askpass-query" "askpass: \$*" && -	cat "$PWD/askpass-response" -	EOF -	chmod +x askpass && -	GIT_ASKPASS="$PWD/askpass" && -	export GIT_ASKPASS -' - -expect_askpass() { -	dest=$HTTPD_DEST -	{ -		case "$1" in -		none) -			;; -		pass) -			echo "askpass: Password for 'http://$2@$dest': " -			;; -		both) -			echo "askpass: Username for 'http://$dest': " -			echo "askpass: Password for 'http://$2@$dest': " -			;; -		*) -			false -			;; -		esac -	} >askpass-expect && -	test_cmp askpass-expect askpass-query -} +	       "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git" +' + +setup_askpass_helper  test_expect_success 'cloning password-protected repository can fail' ' -	>askpass-query && -	echo wrong >askpass-response && -	test_must_fail git clone "$HTTPD_URL/auth/repo.git" clone-auth-fail && +	set_askpass wrong && +	test_must_fail git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-fail &&  	expect_askpass both wrong  '  test_expect_success 'http auth can use user/pass in URL' ' -	>askpass-query && -	echo wrong >askpass-response && -	git clone "$HTTPD_URL_USER_PASS/auth/repo.git" clone-auth-none && +	set_askpass wrong && +	git clone "$HTTPD_URL_USER_PASS/auth/dumb/repo.git" clone-auth-none &&  	expect_askpass none  '  test_expect_success 'http auth can use just user in URL' ' -	>askpass-query && -	echo user@host >askpass-response && -	git clone "$HTTPD_URL_USER/auth/repo.git" clone-auth-pass && +	set_askpass user@host && +	git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&  	expect_askpass pass user@host  '  test_expect_success 'http auth can request both user and pass' ' -	>askpass-query && -	echo user@host >askpass-response && -	git clone "$HTTPD_URL/auth/repo.git" clone-auth-both && +	set_askpass user@host && +	git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&  	expect_askpass both user@host  ' @@ -112,25 +78,22 @@ test_expect_success 'http auth respects credential helper config' '  		echo username=user@host  		echo password=user@host  	}; f" && -	>askpass-query && -	echo wrong >askpass-response && -	git clone "$HTTPD_URL/auth/repo.git" clone-auth-helper && +	set_askpass wrong && +	git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-helper &&  	expect_askpass none  '  test_expect_success 'http auth can get username from config' '  	test_config_global "credential.$HTTPD_URL.username" user@host && -	>askpass-query && -	echo user@host >askpass-response && -	git clone "$HTTPD_URL/auth/repo.git" clone-auth-user && +	set_askpass user@host && +	git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&  	expect_askpass pass user@host  '  test_expect_success 'configured username does not override URL' '  	test_config_global "credential.$HTTPD_URL.username" wrong && -	>askpass-query && -	echo user@host >askpass-response && -	git clone "$HTTPD_URL_USER/auth/repo.git" clone-auth-user2 && +	set_askpass user@host && +	git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&  	expect_askpass pass user@host  ' diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh index 91eaf53d1d..2db5c35641 100755 --- a/t/t5551-http-fetch.sh +++ b/t/t5551-http-fetch.sh @@ -27,6 +27,8 @@ test_expect_success 'create http-accessible bare repository' '  	git push public master:master  ' +setup_askpass_helper +  cat >exp <<EOF  > GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1  > Accept: */* @@ -109,6 +111,24 @@ test_expect_success 'follow redirects (302)' '  	git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t  ' +test_expect_success 'clone from password-protected repository' ' +	echo two >expect && +	set_askpass user@host && +	git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth && +	expect_askpass both user@host && +	git --git-dir=smart-auth log -1 --format=%s >actual && +	test_cmp expect actual +' + +test_expect_success 'clone from auth-only-for-push repository' ' +	echo two >expect && +	set_askpass wrong && +	git clone --bare "$HTTPD_URL/auth-push/smart/repo.git" smart-noauth && +	expect_askpass none && +	git --git-dir=smart-noauth log -1 --format=%s >actual && +	test_cmp expect actual +' +  test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE  test_expect_success EXPENSIVE 'create 50,000 tags in the repo' ' diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 172178490a..752f5cb7d0 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -456,4 +456,14 @@ test_atom refs/tags/signed-long contents "subject line  body contents  $sig" +cat >expected <<\EOF +408fe76d02a785a006c2e9c669b7be5589ede96d <committer@example.com> refs/tags/master +90b5ebede4899eda64893bc2a4c8f1d6fb6dfc40 <committer@example.com> refs/tags/bogo +EOF + +test_expect_success 'Verify sort with multiple keys' ' +	git for-each-ref --format="%(objectname) %(taggeremail) %(refname)" --sort=objectname --sort=taggeremail \ +		refs/tags/bogo refs/tags/master > actual && +	test_cmp expected actual +'  test_done | 
