Browse Source

Merge branch 'maint-1.7.11' into maint

maint
Junio C Hamano 13 years ago
parent
commit
3503e9ab32
  1. 6
      Documentation/git-checkout.txt
  2. 7
      Documentation/revisions.txt
  3. 68
      builtin/apply.c
  4. 4
      builtin/for-each-ref.c
  5. 16
      builtin/rev-parse.c
  6. 55
      http.c
  7. 1
      http.h
  8. 23
      remote-curl.c
  9. 16
      revision.c
  10. 39
      t/lib-httpd.sh
  11. 25
      t/lib-httpd/apache.conf
  12. 14
      t/t1506-rev-parse-diagnosis.sh
  13. 54
      t/t4103-apply-binary.sh
  14. 7
      t/t4202-log.sh
  15. 17
      t/t5540-http-push.sh
  16. 26
      t/t5541-http-push.sh
  17. 75
      t/t5550-http-fetch.sh
  18. 20
      t/t5551-http-fetch.sh
  19. 10
      t/t6300-for-each-ref.sh

6
Documentation/git-checkout.txt

@ -84,11 +84,11 @@ entries; instead, unmerged entries are ignored. @@ -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. @@ -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

7
Documentation/revisions.txt

@ -213,6 +213,13 @@ of 'r1' and 'r2' and is defined as @@ -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

68
builtin/apply.c

@ -1095,15 +1095,23 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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);
}
}
}
}

4
builtin/for-each-ref.c

@ -962,7 +962,9 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset) @@ -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;

16
builtin/rev-parse.c

@ -230,6 +230,7 @@ static int try_difference(const char *arg) @@ -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) @@ -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);

55
http.c

@ -745,6 +745,35 @@ char *get_remote_object_url(const char *url, const char *hex, @@ -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) @@ -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) @@ -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;
}


1
http.h

@ -78,6 +78,7 @@ extern int start_active_slot(struct active_request_slot *slot); @@ -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);

23
remote-curl.c

@ -362,16 +362,17 @@ static size_t rpc_in(char *ptr, size_t eltsize, @@ -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) @@ -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) @@ -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);

16
revision.c

@ -1134,15 +1134,27 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi @@ -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;

39
t/lib-httpd.sh

@ -167,3 +167,42 @@ test_http_push_nonff() { @@ -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"
}

25
t/lib-httpd/apache.conf

@ -46,24 +46,22 @@ PassEnv GIT_VALGRIND @@ -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 @@ -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

14
t/t1506-rev-parse-diagnosis.sh

@ -182,4 +182,18 @@ test_expect_success '<commit>:file correctly diagnosed after a pathname' ' @@ -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

54
t/t4103-apply-binary.sh

@ -8,30 +8,28 @@ test_description='git apply handling binary patches @@ -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' " @@ -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).' \ @@ -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

7
t/t4202-log.sh

@ -806,4 +806,11 @@ test_expect_success 'log --graph with diff and stats' ' @@ -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

17
t/t5540-http-push.sh

@ -46,15 +46,7 @@ test_expect_success 'create password-protected repository' ' @@ -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 \ @@ -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)' ' @@ -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 &&

26
t/t5541-http-push.sh

@ -36,6 +36,8 @@ test_expect_success 'setup remote repository' ' @@ -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' ' @@ -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

75
t/t5550-http-fetch.sh

@ -41,68 +41,34 @@ test_expect_success 'clone http repository' ' @@ -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' ' @@ -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
'


20
t/t5551-http-fetch.sh

@ -27,6 +27,8 @@ test_expect_success 'create http-accessible bare repository' ' @@ -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)' ' @@ -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' '

10
t/t6300-for-each-ref.sh

@ -456,4 +456,14 @@ test_atom refs/tags/signed-long contents "subject line @@ -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

Loading…
Cancel
Save