Merge branch 'master' into next

* master:
  Documentation: add submodule.* to the big configuration variable list
  gitmodules.5: url can be a relative path
  gitweb: fix esc_url
  git --paginate: paginate external commands again
  MERGE_RR is in .git, not .git/rr-cache
  merge-tree: fix where two branches share no changes
  add basic tests for merge-tree
  merge-recursive: use "up-to-date" instead of "uptodate" in error message for consistency
  git --paginate: do not commit pager choice too early
  tests: local config file should be honored from subdirs of toplevel
  t7006: test pager configuration for several git commands
  t7006 (pager): introduce helper for parameterized tests
This commit is contained in:
Junio C Hamano
2010-07-15 12:09:48 -07:00
10 changed files with 476 additions and 53 deletions

View File

@@ -1734,6 +1734,15 @@ status.submodulesummary::
summary of commits for modified submodules will be shown (see
--summary-limit option of linkgit:git-submodule[1]).
submodule.<name>.path::
submodule.<name>.url::
submodule.<name>.update::
The path within this project, URL, and the updating strategy
for a submodule. These variables are initially populated
by 'git submodule init'; edit them to override the
URL and other values found in the `.gitmodules` file. See
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
tar.umask::
This variable can be used to restrict the permission bits of
tar archive entries. The default is 0002, which turns off the

View File

@@ -29,6 +29,9 @@ submodule.<name>.path::
submodule.<name>.url::
Defines an url from where the submodule repository can be cloned.
This may be either an absolute URL ready to be passed to
linkgit:git-clone[1] or (if it begins with ./ or ../) a location
relative to the superproject's origin repository.
submodule.<name>.update::
Defines what to do when the submodule is updated by the superproject.

View File

@@ -60,6 +60,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
{
enum object_type type;
struct blob *base, *our, *their;
const char *path = entry->path;
if (!entry->stage)
return read_sha1_file(entry->blob->object.sha1, &type, size);
@@ -76,7 +77,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
their = NULL;
if (entry)
their = entry->blob;
return merge_file(entry->path, base, our, their, size);
return merge_file(path, base, our, their, size);
}
static void *origin(struct merge_list *entry, unsigned long *size)

View File

@@ -135,7 +135,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
if (!has_rerere_resolution(name))
unlink_rr_item(name);
}
unlink_or_warn(git_path("rr-cache/MERGE_RR"));
unlink_or_warn(git_path("MERGE_RR"));
} else if (!strcmp(argv[1], "gc"))
garbage_collect(&merge_rr);
else if (!strcmp(argv[1], "status"))

5
git.c
View File

@@ -167,6 +167,7 @@ static int handle_alias(int *argcp, const char ***argv)
alias_string = alias_lookup(alias_command);
if (alias_string) {
if (alias_string[0] == '!') {
commit_pager_choice();
if (*argcp > 1) {
struct strbuf buf;
@@ -432,6 +433,8 @@ static void execv_dashed_external(const char **argv)
const char *tmp;
int status;
commit_pager_choice();
strbuf_addf(&cmd, "git-%s", argv[0]);
/*
@@ -511,12 +514,12 @@ int main(int argc, const char **argv)
argv++;
argc--;
handle_options(&argv, &argc, NULL);
commit_pager_choice();
if (argc > 0) {
if (!prefixcmp(argv[0], "--"))
argv[0] += 2;
} else {
/* The user didn't specify a command; give them help */
commit_pager_choice();
printf("usage: %s\n\n", git_usage_string);
list_common_cmds_help();
printf("\n%s\n", git_more_info_string);

View File

@@ -1327,8 +1327,7 @@ sub esc_param {
sub esc_url {
my $str = shift;
return undef unless defined $str;
$str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&=])/sprintf("%%%02X", ord($1))/eg;
$str =~ s/\+/%2B/g;
$str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&= ]+)/CGI::escape($1)/eg;
$str =~ s/ /\+/g;
return $str;
}

View File

@@ -1279,7 +1279,7 @@ int merge_trees(struct merge_options *o,
}
if (sha_eq(common->object.sha1, merge->object.sha1)) {
output(o, 0, "Already uptodate!");
output(o, 0, "Already up-to-date!");
*result = head;
return 1;
}

View File

@@ -47,7 +47,7 @@ do
test_must_fail git am$with3 --skip >output &&
test "$(grep "^Applying" output)" = "Applying: 6" &&
test_cmp file-2-expect file-2 &&
test ! -f .git/rr-cache/MERGE_RR
test ! -f .git/MERGE_RR
'
test_expect_success "am --abort goes back after failed am$with3" '
@@ -57,7 +57,7 @@ do
test_cmp expect actual &&
test_cmp file-2-expect file-2 &&
git diff-index --exit-code --cached HEAD &&
test ! -f .git/rr-cache/MERGE_RR
test ! -f .git/MERGE_RR
'
done

257
t/t4300-merge-tree.sh Executable file
View File

@@ -0,0 +1,257 @@
#!/bin/sh
#
# Copyright (c) 2010 Will Palmer
#
test_description='git merge-tree'
. ./test-lib.sh
test_expect_success setup '
test_commit "initial" "initial-file" "initial"
'
test_expect_success 'file add A, !B' '
cat >expected <<\EXPECTED &&
added in remote
their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
@@ -0,0 +1 @@
+AAA
EXPECTED
git reset --hard initial &&
test_commit "add-a-not-b" "ONE" "AAA" &&
git merge-tree initial initial add-a-not-b >actual &&
test_cmp expected actual
'
test_expect_success 'file add !A, B' '
cat >expected <<\EXPECTED &&
added in local
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
EXPECTED
git reset --hard initial &&
test_commit "add-not-a-b" "ONE" "AAA" &&
git merge-tree initial add-not-a-b initial >actual &&
test_cmp expected actual
'
test_expect_success 'file add A, B (same)' '
cat >expected <<\EXPECTED &&
added in both
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
EXPECTED
git reset --hard initial &&
test_commit "add-a-b-same-A" "ONE" "AAA" &&
git reset --hard initial &&
test_commit "add-a-b-same-B" "ONE" "AAA" &&
git merge-tree initial add-a-b-same-A add-a-b-same-B >actual &&
test_cmp expected actual
'
test_expect_success 'file add A, B (different)' '
cat >expected <<\EXPECTED &&
added in both
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
@@ -1 +1,5 @@
+<<<<<<< .our
AAA
+=======
+BBB
+>>>>>>> .their
EXPECTED
git reset --hard initial &&
test_commit "add-a-b-diff-A" "ONE" "AAA" &&
git reset --hard initial &&
test_commit "add-a-b-diff-B" "ONE" "BBB" &&
git merge-tree initial add-a-b-diff-A add-a-b-diff-B >actual &&
test_cmp expected actual
'
test_expect_success 'file change A, !B' '
cat >expected <<\EXPECTED &&
EXPECTED
git reset --hard initial &&
test_commit "change-a-not-b" "initial-file" "BBB" &&
git merge-tree initial change-a-not-b initial >actual &&
test_cmp expected actual
'
test_expect_success 'file change !A, B' '
cat >expected <<\EXPECTED &&
merged
result 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file
our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
@@ -1 +1 @@
-initial
+BBB
EXPECTED
git reset --hard initial &&
test_commit "change-not-a-b" "initial-file" "BBB" &&
git merge-tree initial initial change-not-a-b >actual &&
test_cmp expected actual
'
test_expect_success 'file change A, B (same)' '
cat >expected <<\EXPECTED &&
EXPECTED
git reset --hard initial &&
test_commit "change-a-b-same-A" "initial-file" "AAA" &&
git reset --hard initial &&
test_commit "change-a-b-same-B" "initial-file" "AAA" &&
git merge-tree initial change-a-b-same-A change-a-b-same-B >actual &&
test_cmp expected actual
'
test_expect_success 'file change A, B (different)' '
cat >expected <<\EXPECTED &&
changed in both
base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d initial-file
their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file
@@ -1 +1,5 @@
+<<<<<<< .our
AAA
+=======
+BBB
+>>>>>>> .their
EXPECTED
git reset --hard initial &&
test_commit "change-a-b-diff-A" "initial-file" "AAA" &&
git reset --hard initial &&
test_commit "change-a-b-diff-B" "initial-file" "BBB" &&
git merge-tree initial change-a-b-diff-A change-a-b-diff-B >actual &&
test_cmp expected actual
'
test_expect_success 'file change A, B (mixed)' '
cat >expected <<\EXPECTED &&
changed in both
base 100644 f4f1f998c7776568c4ff38f516d77fef9399b5a7 ONE
our 100644 af14c2c3475337c73759d561ef70b59e5c731176 ONE
their 100644 372d761493f524d44d59bd24700c3bdf914c973c ONE
@@ -7,7 +7,11 @@
AAA
AAA
AAA
+<<<<<<< .our
BBB
+=======
+CCC
+>>>>>>> .their
AAA
AAA
AAA
EXPECTED
git reset --hard initial &&
test_commit "change-a-b-mix-base" "ONE" "
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA
AAA" &&
test_commit "change-a-b-mix-A" "ONE" \
"$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/BBB/;}" <ONE)" &&
git reset --hard change-a-b-mix-base &&
test_commit "change-a-b-mix-B" "ONE" \
"$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/CCC/;}" <ONE)" &&
git merge-tree change-a-b-mix-base change-a-b-mix-A change-a-b-mix-B \
>actual &&
test_cmp expected actual
'
test_expect_success 'file remove A, !B' '
cat >expected <<\EXPECTED &&
removed in local
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
EXPECTED
git reset --hard initial &&
test_commit "rm-a-not-b-base" "ONE" "AAA" &&
git rm ONE &&
git commit -m "rm-a-not-b" &&
git tag "rm-a-not-b" &&
git merge-tree rm-a-not-b-base rm-a-not-b rm-a-not-b-base >actual &&
test_cmp expected actual
'
test_expect_success 'file remove !A, B' '
cat >expected <<\EXPECTED &&
removed in remote
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
@@ -1 +0,0 @@
-AAA
EXPECTED
git reset --hard initial &&
test_commit "rm-not-a-b-base" "ONE" "AAA" &&
git rm ONE &&
git commit -m "rm-not-a-b" &&
git tag "rm-not-a-b" &&
git merge-tree rm-a-not-b-base rm-a-not-b-base rm-a-not-b >actual &&
test_cmp expected actual
'
test_expect_success 'file change A, remove B' '
cat >expected <<\EXPECTED &&
removed in remote
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
@@ -1 +0,0 @@
-BBB
EXPECTED
git reset --hard initial &&
test_commit "change-a-rm-b-base" "ONE" "AAA" &&
test_commit "change-a-rm-b-A" "ONE" "BBB" &&
git reset --hard change-a-rm-b-base &&
git rm ONE &&
git commit -m "change-a-rm-b-B" &&
git tag "change-a-rm-b-B" &&
git merge-tree change-a-rm-b-base change-a-rm-b-A change-a-rm-b-B \
>actual &&
test_cmp expected actual
'
test_expect_success 'file remove A, change B' '
cat >expected <<\EXPECTED &&
removed in local
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
EXPECTED
git reset --hard initial &&
test_commit "rm-a-change-b-base" "ONE" "AAA" &&
git rm ONE &&
git commit -m "rm-a-change-b-A" &&
git tag "rm-a-change-b-A" &&
git reset --hard rm-a-change-b-base &&
test_commit "rm-a-change-b-B" "ONE" "BBB" &&
git merge-tree rm-a-change-b-base rm-a-change-b-A rm-a-change-b-B \
>actual &&
test_cmp expected actual
'
test_done

View File

@@ -164,58 +164,209 @@ then
test_set_prereq SIMPLEPAGERTTY
fi
test_expect_success SIMPLEPAGERTTY 'default pager is used by default' '
unset PAGER GIT_PAGER;
test_might_fail git config --unset core.pager &&
rm -f default_pager_used ||
cleanup_fail &&
# Use this helper to make it easy for the caller of your
# terminal-using function to specify whether it should fail.
# If you write
#
# your_test() {
# parse_args "$@"
#
# $test_expectation "$cmd - behaves well" "
# ...
# $full_command &&
# ...
# "
# }
#
# then your test can be used like this:
#
# your_test expect_(success|failure) [test_must_fail] 'git foo'
#
parse_args() {
test_expectation="test_$1"
shift
if test "$1" = test_must_fail
then
full_command="test_must_fail test_terminal "
shift
else
full_command="test_terminal "
fi
cmd=$1
full_command="$full_command $1"
}
cat >$less <<-\EOF &&
#!/bin/sh
wc >default_pager_used
EOF
chmod +x $less &&
(
PATH=.:$PATH &&
export PATH &&
test_terminal git log
) &&
test -e default_pager_used
test_default_pager() {
parse_args "$@"
$test_expectation SIMPLEPAGERTTY "$cmd - default pager is used by default" "
unset PAGER GIT_PAGER;
test_might_fail git config --unset core.pager &&
rm -f default_pager_used ||
cleanup_fail &&
cat >\$less <<-\EOF &&
#!/bin/sh
wc >default_pager_used
EOF
chmod +x \$less &&
(
PATH=.:\$PATH &&
export PATH &&
$full_command
) &&
test -e default_pager_used
"
}
test_PAGER_overrides() {
parse_args "$@"
$test_expectation TTY "$cmd - PAGER overrides default pager" "
unset GIT_PAGER;
test_might_fail git config --unset core.pager &&
rm -f PAGER_used ||
cleanup_fail &&
PAGER='wc >PAGER_used' &&
export PAGER &&
$full_command &&
test -e PAGER_used
"
}
test_core_pager_overrides() {
if_local_config=
used_if_wanted='overrides PAGER'
test_core_pager "$@"
}
test_local_config_ignored() {
if_local_config='! '
used_if_wanted='is not used'
test_core_pager "$@"
}
test_core_pager() {
parse_args "$@"
$test_expectation TTY "$cmd - repository-local core.pager setting $used_if_wanted" "
unset GIT_PAGER;
rm -f core.pager_used ||
cleanup_fail &&
PAGER=wc &&
export PAGER &&
git config core.pager 'wc >core.pager_used' &&
$full_command &&
${if_local_config}test -e core.pager_used
"
}
test_core_pager_subdir() {
if_local_config=
used_if_wanted='overrides PAGER'
test_pager_subdir_helper "$@"
}
test_no_local_config_subdir() {
if_local_config='! '
used_if_wanted='is not used'
test_pager_subdir_helper "$@"
}
test_pager_subdir_helper() {
parse_args "$@"
$test_expectation TTY "$cmd - core.pager $used_if_wanted from subdirectory" "
unset GIT_PAGER;
rm -f core.pager_used &&
rm -fr sub ||
cleanup_fail &&
PAGER=wc &&
stampname=\$(pwd)/core.pager_used &&
export PAGER stampname &&
git config core.pager 'wc >\"\$stampname\"' &&
mkdir sub &&
(
cd sub &&
$full_command
) &&
${if_local_config}test -e core.pager_used
"
}
test_GIT_PAGER_overrides() {
parse_args "$@"
$test_expectation TTY "$cmd - GIT_PAGER overrides core.pager" "
rm -f GIT_PAGER_used ||
cleanup_fail &&
git config core.pager wc &&
GIT_PAGER='wc >GIT_PAGER_used' &&
export GIT_PAGER &&
$full_command &&
test -e GIT_PAGER_used
"
}
test_doesnt_paginate() {
parse_args "$@"
$test_expectation TTY "no pager for '$cmd'" "
rm -f GIT_PAGER_used ||
cleanup_fail &&
GIT_PAGER='wc >GIT_PAGER_used' &&
export GIT_PAGER &&
$full_command &&
! test -e GIT_PAGER_used
"
}
test_pager_choices() {
test_default_pager expect_success "$@"
test_PAGER_overrides expect_success "$@"
test_core_pager_overrides expect_success "$@"
test_core_pager_subdir expect_success "$@"
test_GIT_PAGER_overrides expect_success "$@"
}
test_expect_success 'setup: some aliases' '
git config alias.aliasedlog log &&
git config alias.true "!true"
'
test_expect_success TTY 'PAGER overrides default pager' '
unset GIT_PAGER;
test_might_fail git config --unset core.pager &&
rm -f PAGER_used ||
cleanup_fail &&
test_pager_choices 'git log'
test_pager_choices 'git -p log'
test_pager_choices 'git aliasedlog'
PAGER="wc >PAGER_used" &&
export PAGER &&
test_terminal git log &&
test -e PAGER_used
'
test_default_pager expect_success 'git -p aliasedlog'
test_PAGER_overrides expect_success 'git -p aliasedlog'
test_core_pager_overrides expect_success 'git -p aliasedlog'
test_core_pager_subdir expect_failure 'git -p aliasedlog'
test_GIT_PAGER_overrides expect_success 'git -p aliasedlog'
test_expect_success TTY 'core.pager overrides PAGER' '
unset GIT_PAGER;
rm -f core.pager_used ||
cleanup_fail &&
test_default_pager expect_success 'git -p true'
test_PAGER_overrides expect_success 'git -p true'
test_core_pager_overrides expect_success 'git -p true'
test_core_pager_subdir expect_failure 'git -p true'
test_GIT_PAGER_overrides expect_success 'git -p true'
PAGER=wc &&
export PAGER &&
git config core.pager "wc >core.pager_used" &&
test_terminal git log &&
test -e core.pager_used
'
test_default_pager expect_success test_must_fail 'git -p request-pull'
test_PAGER_overrides expect_success test_must_fail 'git -p request-pull'
test_core_pager_overrides expect_success test_must_fail 'git -p request-pull'
test_core_pager_subdir expect_failure test_must_fail 'git -p request-pull'
test_GIT_PAGER_overrides expect_success test_must_fail 'git -p request-pull'
test_expect_success TTY 'GIT_PAGER overrides core.pager' '
rm -f GIT_PAGER_used ||
cleanup_fail &&
test_default_pager expect_success test_must_fail 'git -p'
test_PAGER_overrides expect_success test_must_fail 'git -p'
test_local_config_ignored expect_failure test_must_fail 'git -p'
test_no_local_config_subdir expect_success test_must_fail 'git -p'
test_GIT_PAGER_overrides expect_success test_must_fail 'git -p'
git config core.pager wc &&
GIT_PAGER="wc >GIT_PAGER_used" &&
export GIT_PAGER &&
test_terminal git log &&
test -e GIT_PAGER_used
'
test_doesnt_paginate expect_failure test_must_fail 'git -p nonsense'
test_done