git/t/t4202-log.sh

2387 lines
63 KiB
Bash
Raw Normal View History

#!/bin/sh
test_description='git log'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
tests: mark tests relying on the current default for `init.defaultBranch` In addition to the manual adjustment to let the `linux-gcc` CI job run the test suite with `master` and then with `main`, this patch makes sure that GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME is set in all test scripts that currently rely on the initial branch name being `master by default. To determine which test scripts to mark up, the first step was to force-set the default branch name to `master` in - all test scripts that contain the keyword `master`, - t4211, which expects `t/t4211/history.export` with a hard-coded ref to initialize the default branch, - t5560 because it sources `t/t556x_common` which uses `master`, - t8002 and t8012 because both source `t/annotate-tests.sh` which also uses `master`) This trick was performed by this command: $ sed -i '/^ *\. \.\/\(test-lib\|lib-\(bash\|cvs\|git-svn\)\|gitweb-lib\)\.sh$/i\ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\ ' $(git grep -l master t/t[0-9]*.sh) \ t/t4211*.sh t/t5560*.sh t/t8002*.sh t/t8012*.sh After that, careful, manual inspection revealed that some of the test scripts containing the needle `master` do not actually rely on a specific default branch name: either they mention `master` only in a comment, or they initialize that branch specificially, or they do not actually refer to the current default branch. Therefore, the aforementioned modification was undone in those test scripts thusly: $ git checkout HEAD -- \ t/t0027-auto-crlf.sh t/t0060-path-utils.sh \ t/t1011-read-tree-sparse-checkout.sh \ t/t1305-config-include.sh t/t1309-early-config.sh \ t/t1402-check-ref-format.sh t/t1450-fsck.sh \ t/t2024-checkout-dwim.sh \ t/t2106-update-index-assume-unchanged.sh \ t/t3040-subprojects-basic.sh t/t3301-notes.sh \ t/t3308-notes-merge.sh t/t3423-rebase-reword.sh \ t/t3436-rebase-more-options.sh \ t/t4015-diff-whitespace.sh t/t4257-am-interactive.sh \ t/t5323-pack-redundant.sh t/t5401-update-hooks.sh \ t/t5511-refspec.sh t/t5526-fetch-submodules.sh \ t/t5529-push-errors.sh t/t5530-upload-pack-error.sh \ t/t5548-push-porcelain.sh \ t/t5552-skipping-fetch-negotiator.sh \ t/t5572-pull-submodule.sh t/t5608-clone-2gb.sh \ t/t5614-clone-submodules-shallow.sh \ t/t7508-status.sh t/t7606-merge-custom.sh \ t/t9302-fast-import-unpack-limit.sh We excluded one set of test scripts in these commands, though: the range of `git p4` tests. The reason? `git p4` stores the (foreign) remote branch in the branch called `p4/master`, which is obviously not the default branch. Manual analysis revealed that only five of these tests actually require a specific default branch name to pass; They were modified thusly: $ sed -i '/^ *\. \.\/lib-git-p4\.sh$/i\ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\ ' t/t980[0167]*.sh t/t9811*.sh Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-18 23:44:19 +00:00
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
. "$TEST_DIRECTORY/lib-terminal.sh"
. "$TEST_DIRECTORY/lib-log-graph.sh"
test_cmp_graph () {
lib_test_cmp_graph --format=%s "$@"
}
test_expect_success setup '
echo one >one &&
git add one &&
test_tick &&
git commit -m initial &&
echo ichi >one &&
git add one &&
test_tick &&
git commit -m second &&
git mv one ichi &&
test_tick &&
git commit -m third &&
cp ichi ein &&
git add ein &&
test_tick &&
git commit -m fourth &&
mkdir a &&
echo ni >a/two &&
git add a/two &&
test_tick &&
git commit -m fifth &&
git rm a/two &&
test_tick &&
git commit -m sixth
'
printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial" > expect
test_expect_success 'pretty' '
git log --pretty="format:%s" > actual &&
test_cmp expect actual
'
printf "sixth\nfifth\nfourth\nthird\nsecond\ninitial\n" > expect
test_expect_success 'pretty (tformat)' '
git log --pretty="tformat:%s" > actual &&
test_cmp expect actual
'
test_expect_success 'pretty (shortcut)' '
git log --pretty="%s" > actual &&
test_cmp expect actual
'
test_expect_success 'format' '
git log --format="%s" > actual &&
test_cmp expect actual
'
cat > expect << EOF
This is
the sixth
commit.
This is
the fifth
commit.
EOF
test_expect_success 'format %w(11,1,2)' '
git log -2 --format="%w(11,1,2)This is the %s commit." > actual &&
test_cmp expect actual
'
test_expect_success 'format %w(,1,2)' '
git log -2 --format="%w(,1,2)This is%nthe %s%ncommit." > actual &&
test_cmp expect actual
'
cat > expect << EOF
$(git rev-parse --short :/sixth ) sixth
$(git rev-parse --short :/fifth ) fifth
$(git rev-parse --short :/fourth ) fourth
$(git rev-parse --short :/third ) third
$(git rev-parse --short :/second ) second
$(git rev-parse --short :/initial) initial
EOF
test_expect_success 'oneline' '
git log --oneline > actual &&
test_cmp expect actual
'
test_expect_success 'diff-filter=A' '
git log --no-renames --pretty="format:%s" --diff-filter=A HEAD > actual &&
git log --no-renames --pretty="format:%s" --diff-filter A HEAD > actual-separate &&
printf "fifth\nfourth\nthird\ninitial" > expect &&
test_cmp expect actual &&
test_cmp expect actual-separate
'
test_expect_success 'diff-filter=M' '
git log --pretty="format:%s" --diff-filter=M HEAD >actual &&
printf "second" >expect &&
test_cmp expect actual
'
test_expect_success 'diff-filter=D' '
git log --no-renames --pretty="format:%s" --diff-filter=D HEAD >actual &&
printf "sixth\nthird" >expect &&
test_cmp expect actual
'
test_expect_success 'diff-filter=R' '
git log -M --pretty="format:%s" --diff-filter=R HEAD >actual &&
printf "third" >expect &&
test_cmp expect actual
'
test_expect_success 'multiple --diff-filter bits' '
git log -M --pretty="format:%s" --diff-filter=R HEAD >expect &&
git log -M --pretty="format:%s" --diff-filter=Ra HEAD >actual &&
test_cmp expect actual &&
git log -M --pretty="format:%s" --diff-filter=aR HEAD >actual &&
test_cmp expect actual &&
git log -M --pretty="format:%s" \
--diff-filter=a --diff-filter=R HEAD >actual &&
test_cmp expect actual
'
test_expect_success 'diff-filter=C' '
git log -C -C --pretty="format:%s" --diff-filter=C HEAD >actual &&
printf "fourth" >expect &&
test_cmp expect actual
'
test_expect_success 'git log --follow' '
git log --follow --pretty="format:%s" ichi >actual &&
printf "third\nsecond\ninitial" >expect &&
test_cmp expect actual
'
test_expect_success 'git config log.follow works like --follow' '
test_config log.follow true &&
git log --pretty="format:%s" ichi >actual &&
printf "third\nsecond\ninitial" >expect &&
test_cmp expect actual
'
test_expect_success 'git config log.follow does not die with multiple paths' '
test_config log.follow true &&
git log --pretty="format:%s" ichi ein
'
test_expect_success 'git config log.follow does not die with no paths' '
test_config log.follow true &&
git log --
'
diff: detect pathspec magic not supported by --follow The --follow code doesn't handle most forms of pathspec magic. We check that no unexpected ones have made it to try_to_follow_renames() with a runtime GUARD_PATHSPEC() check, which gives behavior like this: $ git log --follow ':(icase)makefile' >/dev/null BUG: tree-diff.c:596: unsupported magic 10 Aborted The same is true of ":(glob)", ":(attr)", and so on. It's good that we notice the problem rather than continuing and producing a wrong answer. But there are two non-ideal things: 1. The idea of GUARD_PATHSPEC() is to catch programming errors where low-level code gets unexpected pathspecs. We'd usually try to catch unsupported pathspecs by passing a magic_mask to parse_pathspec(), which would give the user a much better message like: pathspec magic not supported by this command: 'icase' That doesn't happen here because git-log usually _does_ support all types of pathspec magic, and so it passes "0" for the mask (this call actually happens in setup_revisions()). It needs to distinguish the normal case from the "--follow" one but currently doesn't. 2. In addition to --follow, we have the log.follow config option. When that is set, we try to turn on --follow mode only when there is a single pathspec (since --follow doesn't handle anything else). But really, that ought to be expanded to "use --follow when the pathspec supports it". Otherwise, we'd complain any time you use an exotic pathspec: $ git config log.follow true $ git log ':(icase)makefile' >/dev/null BUG: tree-diff.c:596: unsupported magic 10 Aborted We should instead just avoid enabling follow mode if it's not supported by this particular invocation. This patch expands our diff_check_follow_pathspec() function to cover pathspec magic, solving both problems. A few final notes: - we could also solve (1) by passing the appropriate mask to parse_pathspec(). But that's not great for two reasons. One is that the error message is less precise. It says "magic not supported by this command", but really it is not the command, but rather the --follow option which is the problem. The second is that it always calls die(). But for our log.follow code, we want to speculatively ask "is this pathspec OK?" and just get a boolean result. - This is obviously the right thing to do for ':(icase)' and most other magic options. But ':(glob)' is a bit odd here. The --follow code doesn't support wildcards, but we allow them anyway. From try_to_follow_renames(): #if 0 /* * We should reject wildcards as well. Unfortunately we * haven't got a reliable way to detect that 'foo\*bar' in * fact has no wildcards. nowildcard_len is merely a hint for * optimization. Let it slip for now until wildmatch is taught * about dry-run mode and returns wildcard info. */ if (opt->pathspec.has_wildcard) BUG("wildcards are not supported"); #endif So something like "git log --follow 'Make*'" is already doing the wrong thing, since ":(glob)" behavior is already the default (it is used only to countermand an earlier --noglob-pathspecs). So we _could_ loosen the guard to allow :(glob), since it just behaves the same as pathspecs do by default. But it seems like a backwards step to do so. It already doesn't work (it hits the BUG() case currently), and given that the user took an explicit step to say "this pathspec should glob", it is reasonable for us to say "no, --follow does not support globbing" (or in the case of log.follow, avoid turning on follow mode). Which is what happens after this patch. - The set of allowed pathspec magic is obviously the same as in GUARD_PATHSPEC(). We could perhaps factor these out to avoid repetition. The point of having separate masks and GUARD calls is that we don't necessarily know which parsed pathspecs will be used where. But in this case, the two are heavily correlated. Still, there may be some value in keeping them separate; it would make anyone think twice about adding new magic to the list in diff_check_follow_pathspec(). They'd need to touch try_to_follow_renames() as well, which is the code that would actually need to be updated to handle more exotic pathspecs. - The documentation for log.follow says that it enables --follow "...when a single <path> is given". We could possibly expand that to say "with no unsupported pathspec magic", but that raises the question of documenting which magic is supported. I think the existing wording of "single <path>" sufficiently encompasses the idea (the forbidden magic is stuff that might match multiple entries), and the spirit remains the same. Reported-by: Jim Pryor <dubiousjim@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-06-01 17:43:51 +00:00
test_expect_success 'git log --follow rejects unsupported pathspec magic' '
test_must_fail git log --follow ":(top,glob,icase)ichi" 2>stderr &&
# check full error message; we want to be sure we mention both
# of the rejected types (glob,icase), but not the allowed one (top)
echo "fatal: pathspec magic not supported by --follow: ${SQ}glob${SQ}, ${SQ}icase${SQ}" >expect &&
test_cmp expect stderr
'
test_expect_success 'log.follow disabled with unsupported pathspec magic' '
test_config log.follow true &&
git log --format=%s ":(glob,icase)ichi" >actual &&
echo third >expect &&
test_cmp expect actual
'
test_expect_success 'git config log.follow is overridden by --no-follow' '
test_config log.follow true &&
git log --no-follow --pretty="format:%s" ichi >actual &&
printf "third" >expect &&
test_cmp expect actual
'
# Note that these commits are intentionally listed out of order.
last_three="$(git rev-parse :/fourth :/sixth :/fifth)"
cat > expect << EOF
$(git rev-parse --short :/sixth ) sixth
$(git rev-parse --short :/fifth ) fifth
$(git rev-parse --short :/fourth) fourth
EOF
test_expect_success 'git log --no-walk <commits> sorts by commit time' '
git log --no-walk --oneline $last_three > actual &&
test_cmp expect actual
'
test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' '
git log --no-walk=sorted --oneline $last_three > actual &&
test_cmp expect actual
'
cat > expect << EOF
=== $(git rev-parse --short :/sixth ) sixth
=== $(git rev-parse --short :/fifth ) fifth
=== $(git rev-parse --short :/fourth) fourth
EOF
test_expect_success 'git log --line-prefix="=== " --no-walk <commits> sorts by commit time' '
git log --line-prefix="=== " --no-walk --oneline $last_three > actual &&
test_cmp expect actual
'
cat > expect << EOF
$(git rev-parse --short :/fourth) fourth
$(git rev-parse --short :/sixth ) sixth
$(git rev-parse --short :/fifth ) fifth
EOF
test_expect_success 'git log --no-walk=unsorted <commits> leaves list of commits as given' '
git log --no-walk=unsorted --oneline $last_three > actual &&
test_cmp expect actual
'
test_expect_success 'git show <commits> leaves list of commits as given' '
git show --oneline -s $last_three > actual &&
test_cmp expect actual
'
test_expect_success 'setup case sensitivity tests' '
echo case >one &&
test_tick &&
git add one &&
git commit -a -m Second
'
test_expect_success 'log --grep' '
echo second >expect &&
git log -1 --pretty="tformat:%s" --grep=sec >actual &&
test_cmp expect actual
'
grep.c: remove "extended" in favor of "pattern_expression", fix segfault Since 79d3696cfb4 (git-grep: boolean expression on pattern matching., 2006-06-30) the "pattern_expression" member has been used for complex queries (AND/OR...), with "pattern_list" being used for the simple OR queries. Since then we've used both "pattern_expression" and its associated boolean "extended" member to see if we have a complex expression. Since f41fb662f57 (revisions API: have release_revisions() release "grep_filter", 2022-04-13) we've had a subtle bug relating to that: If we supplied options that were only used for "complex queries", but didn't supply the query itself we'd set "opt->extended", but would have a NULL "pattern_expression". As a result these would segfault as we tried to call "free_grep_patterns()" from "release_revisions()": git -P log -1 --invert-grep git -P log -1 --all-match The root cause of this is that we were conflating the state management we needed in "compile_grep_patterns()" itself with whether or not we had an "opt->pattern_expression" later on. In this cases as we're going through "compile_grep_patterns()" we have no "opt->pattern_list" but have "opt->no_body_match" or "opt->all_match". So we'd set "opt->extended = 1", but not "return" on "opt->extended" as that's an "else if" in the same "if" statement. That behavior is intentional and required, as the common case is that we have an "opt->pattern_list" that we're about to parse into the "opt->pattern_expression". But we don't need to keep track of this "extended" flag beyond the state management in compile_grep_patterns() itself. It needs it, but once we're out of that function we can rely on "opt->pattern_expression" being non-NULL instead for using these extended patterns. As 79d3696cfb4 itself shows we've assumed that there's a one-to-one mapping between the two since the very beginning. I.e. "match_line()" would check "opt->extended" to see if it should call "match_expr()", and the first thing we do in that function is assume that we have a "opt->pattern_expression". We'd then call "match_expr_eval()", which would have died if that "opt->pattern_expression" was NULL. The "die" was added in c922b01f54c (grep: fix segfault when "git grep '('" is given, 2009-04-27), and can now be removed as it's now clearly unreachable. We still do the right thing in the case that prompted that fix: git grep '(' fatal: unmatched parenthesis Arguably neither the "--invert-grep" option added in [1] nor the earlier "--all-match" option added in [2] were intended to be used stand-alone, and another approach[3] would be to error out in those cases. But since we've been treating them as a NOOP when given without --grep for a long time let's keep doing that. We could also return in "free_pattern_expr()" if the argument is non-NULL, as an alternative fix for this segfault does [4]. That would be more elegant in making the "free_*()" function behave like "free()", but it would also remove a sanity check: The "free_pattern_expr()" function calls itself recursively, and only the top-level is allowed to be NULL, let's not conflate those two conditions. 1. 22dfa8a23de (log: teach --invert-grep option, 2015-01-12) 2. 0ab7befa31d (grep --all-match, 2006-09-27) 3. https://lore.kernel.org/git/patch-1.1-f4b90799fce-20221010T165711Z-avarab@gmail.com/ 4. http://lore.kernel.org/git/7e094882c2a71894416089f894557a9eae07e8f8.1665423686.git.me@ttaylorr.com Reported-by: orygaw <orygaw@protonmail.com> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-10-11 09:48:45 +00:00
for noop_opt in --invert-grep --all-match
do
test_expect_success "log $noop_opt without --grep is a NOOP" '
git log >expect &&
git log $noop_opt >actual &&
test_cmp expect actual
'
done
cat > expect << EOF
second
initial
EOF
test_expect_success 'log --invert-grep --grep' '
# Fixed
git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual &&
test_cmp expect actual &&
# POSIX basic
git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual &&
# POSIX extended
git -c grep.patternType=extended log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual &&
# PCRE
if test_have_prereq PCRE
then
git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual
fi
'
test_expect_success 'log --invert-grep --grep -i' '
echo initial >expect &&
# Fixed
git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep -i --grep=th --grep=Sec >actual &&
test_cmp expect actual &&
# POSIX basic
git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual &&
# POSIX extended
git -c grep.patternType=extended log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual &&
# PCRE
if test_have_prereq PCRE
then
git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
test_cmp expect actual
fi
'
test_expect_success 'log --grep option parsing' '
echo second >expect &&
git log -1 --pretty="tformat:%s" --grep sec >actual &&
test_cmp expect actual &&
test_must_fail git log -1 --pretty="tformat:%s" --grep
'
test_expect_success 'log -i --grep' '
echo Second >expect &&
git log -1 --pretty="tformat:%s" -i --grep=sec >actual &&
test_cmp expect actual
'
test_expect_success 'log --grep -i' '
echo Second >expect &&
# Fixed
git log -1 --pretty="tformat:%s" --grep=sec -i >actual &&
test_cmp expect actual &&
# POSIX basic
git -c grep.patternType=basic log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
test_cmp expect actual &&
# POSIX extended
git -c grep.patternType=extended log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
test_cmp expect actual &&
# PCRE
if test_have_prereq PCRE
then
git -c grep.patternType=perl log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
test_cmp expect actual
fi
'
test_expect_success 'log -F -E --grep=<ere> uses ere' '
echo second >expect &&
# basic would need \(s\) to do the same
git log -1 --pretty="tformat:%s" -F -E --grep="(s).c.nd" >actual &&
test_cmp expect actual
'
test_expect_success PCRE 'log -F -E --perl-regexp --grep=<pcre> uses PCRE' '
test_when_finished "rm -rf num_commits" &&
git init num_commits &&
(
cd num_commits &&
test_commit 1d &&
test_commit 2e
) &&
# In PCRE \d in [\d] is like saying "0-9", and matches the 2
# in 2e...
echo 2e >expect &&
git -C num_commits log -1 --pretty="tformat:%s" -F -E --perl-regexp --grep="[\d]" >actual &&
test_cmp expect actual &&
# ...in POSIX basic and extended it is the same as [d],
# i.e. "d", which matches 1d, but does not match 2e.
echo 1d >expect &&
git -C num_commits log -1 --pretty="tformat:%s" -F -E --grep="[\d]" >actual &&
test_cmp expect actual
'
test_expect_success 'log with grep.patternType configuration' '
git -c grep.patterntype=fixed \
log -1 --pretty=tformat:%s --grep=s.c.nd >actual &&
test_must_be_empty actual
'
test_expect_success 'log with grep.patternType configuration and command line' '
echo second >expect &&
git -c grep.patterntype=fixed \
log -1 --pretty=tformat:%s --basic-regexp --grep=s.c.nd >actual &&
test_cmp expect actual
'
test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurations & command-lines' '
git init pattern-type &&
(
cd pattern-type &&
test_commit 1 file A &&
# The tagname is overridden here because creating a
# tag called "(1|2)" as test_commit would otherwise
# implicitly do would fail on e.g. MINGW.
test_commit "(1|2)" file B 2 &&
echo "(1|2)" >expect.fixed &&
cp expect.fixed expect.basic &&
cp expect.fixed expect.extended &&
cp expect.fixed expect.perl &&
# A strcmp-like match with fixed.
git -c grep.patternType=fixed log --pretty=tformat:%s \
--grep="(1|2)" >actual.fixed &&
# POSIX basic matches (, | and ) literally.
git -c grep.patternType=basic log --pretty=tformat:%s \
--grep="(.|.)" >actual.basic &&
# POSIX extended needs to have | escaped to match it
# literally, whereas under basic this is the same as
# (|2), i.e. it would also match "1". This test checks
# for extended by asserting that it is not matching
# what basic would match.
git -c grep.patternType=extended log --pretty=tformat:%s \
--grep="\|2" >actual.extended &&
if test_have_prereq PCRE
then
# Only PCRE would match [\d]\| with only
# "(1|2)" due to [\d]. POSIX basic would match
# both it and "1" since similarly to the
# extended match above it is the same as
# \([\d]\|\). POSIX extended would
# match neither.
git -c grep.patternType=perl log --pretty=tformat:%s \
--grep="[\d]\|" >actual.perl &&
test_cmp expect.perl actual.perl
fi &&
test_cmp expect.fixed actual.fixed &&
test_cmp expect.basic actual.basic &&
test_cmp expect.extended actual.extended &&
git log --pretty=tformat:%s -F \
--grep="(1|2)" >actual.fixed.short-arg &&
git log --pretty=tformat:%s -E \
--grep="\|2" >actual.extended.short-arg &&
if test_have_prereq PCRE
then
git log --pretty=tformat:%s -P \
--grep="[\d]\|" >actual.perl.short-arg
else
test_must_fail git log -P \
--grep="[\d]\|"
fi &&
test_cmp expect.fixed actual.fixed.short-arg &&
test_cmp expect.extended actual.extended.short-arg &&
if test_have_prereq PCRE
then
test_cmp expect.perl actual.perl.short-arg
fi &&
git log --pretty=tformat:%s --fixed-strings \
--grep="(1|2)" >actual.fixed.long-arg &&
git log --pretty=tformat:%s --basic-regexp \
--grep="(.|.)" >actual.basic.long-arg &&
git log --pretty=tformat:%s --extended-regexp \
--grep="\|2" >actual.extended.long-arg &&
if test_have_prereq PCRE
then
git log --pretty=tformat:%s --perl-regexp \
--grep="[\d]\|" >actual.perl.long-arg &&
test_cmp expect.perl actual.perl.long-arg
else
test_must_fail git log --perl-regexp \
--grep="[\d]\|"
fi &&
test_cmp expect.fixed actual.fixed.long-arg &&
test_cmp expect.basic actual.basic.long-arg &&
test_cmp expect.extended actual.extended.long-arg
)
'
for cmd in show whatchanged reflog format-patch
do
case "$cmd" in
format-patch) myarg="HEAD~.." ;;
*) myarg= ;;
esac
test_expect_success "$cmd: understands grep.patternType, like 'log'" '
git init "pattern-type-$cmd" &&
(
cd "pattern-type-$cmd" &&
test_commit 1 file A &&
test_commit "(1|2)" file B 2 &&
git -c grep.patternType=fixed $cmd --grep="..." $myarg >actual &&
test_must_be_empty actual &&
git -c grep.patternType=basic $cmd --grep="..." $myarg >actual &&
test_file_not_empty actual
)
'
done
test_expect_success 'log --author' '
cat >expect <<-\EOF &&
Author: <BOLD;RED>A U<RESET> Thor <author@example.com>
EOF
git log -1 --color=always --author="A U" >log &&
grep Author log >actual.raw &&
test_decode_color <actual.raw >actual &&
test_cmp expect actual
'
test_expect_success 'log --committer' '
cat >expect <<-\EOF &&
Commit: C O Mitter <committer@<BOLD;RED>example<RESET>.com>
EOF
git log -1 --color=always --pretty=fuller --committer="example" >log &&
grep "Commit:" log >actual.raw &&
test_decode_color <actual.raw >actual &&
test_cmp expect actual
'
test_expect_success 'log -i --grep with color' '
cat >expect <<-\EOF &&
<BOLD;RED>Sec<RESET>ond
<BOLD;RED>sec<RESET>ond
EOF
git log --color=always -i --grep=^sec >log &&
grep -i sec log >actual.raw &&
test_decode_color <actual.raw >actual &&
test_cmp expect actual
'
test_expect_success '-c color.grep.selected log --grep' '
cat >expect <<-\EOF &&
<GREEN>th<RESET><BOLD;RED>ir<RESET><GREEN>d<RESET>
EOF
git -c color.grep.selected="green" log --color=always --grep=ir >log &&
grep ir log >actual.raw &&
test_decode_color <actual.raw >actual &&
test_cmp expect actual
'
test_expect_success '-c color.grep.matchSelected log --grep' '
cat >expect <<-\EOF &&
<BLUE>i<RESET>n<BLUE>i<RESET>t<BLUE>i<RESET>al
EOF
git -c color.grep.matchSelected="blue" log --color=always --grep=i >log &&
grep al log >actual.raw &&
test_decode_color <actual.raw >actual &&
test_cmp expect actual
'
cat > expect <<EOF
* Second
* sixth
* fifth
* fourth
* third
* second
* initial
EOF
test_expect_success 'simple log --graph' '
test_cmp_graph
'
cat > expect <<EOF
123 * Second
123 * sixth
123 * fifth
123 * fourth
123 * third
123 * second
123 * initial
EOF
test_expect_success 'simple log --graph --line-prefix="123 "' '
test_cmp_graph --line-prefix="123 "
'
test_expect_success 'set up merge history' '
git checkout -b side HEAD~4 &&
test_commit side-1 1 1 &&
test_commit side-2 2 2 &&
git checkout main &&
git merge side
'
cat > expect <<\EOF
* Merge branch 'side'
|\
| * side-2
| * side-1
* | Second
* | sixth
* | fifth
* | fourth
|/
* third
* second
* initial
EOF
test_expect_success 'log --graph with merge' '
test_cmp_graph --date-order
'
cat > expect <<\EOF
| | | * Merge branch 'side'
| | | |\
| | | | * side-2
| | | | * side-1
| | | * | Second
| | | * | sixth
| | | * | fifth
| | | * | fourth
| | | |/
| | | * third
| | | * second
| | | * initial
EOF
test_expect_success 'log --graph --line-prefix="| | | " with merge' '
test_cmp_graph --line-prefix="| | | " --date-order
'
cat > expect.colors <<\EOF
* Merge branch 'side'
<BLUE>|<RESET><CYAN>\<RESET>
<BLUE>|<RESET> * side-2
<BLUE>|<RESET> * side-1
* <CYAN>|<RESET> Second
* <CYAN>|<RESET> sixth
* <CYAN>|<RESET> fifth
* <CYAN>|<RESET> fourth
<CYAN>|<RESET><CYAN>/<RESET>
* third
* second
* initial
EOF
test_expect_success 'log --graph with merge with log.graphColors' '
color_parse_mem: allow empty color spec Prior to c2f41bf52 (color.c: fix color_parse_mem() with value_len == 0, 2017-01-19), the empty string was interpreted as a color "reset". This was an accidental outcome, and that commit turned it into an error. However, scripts may pass the empty string as a default value to "git config --get-color" to disable color when the value is not defined. The git-add--interactive script does this. As a result, the script is unusable since c2f41bf52 unless you have color.diff.plain defined (if it is defined, then we don't parse the empty default at all). Our test scripts didn't notice the recent breakage because they run without a terminal, and thus without color. They never hit this code path at all. And nobody noticed the original buggy "reset" behavior, because it was effectively a noop. Let's fix the code to have an empty color name produce an empty sequence of color codes. The tests need a few fixups: - we'll add a new test in t4026 to cover this case. But note that we need to tweak the color() helper. While we're there, let's factor out the literal ANSI ESC character. Otherwise it makes the diff quite hard to read. - we'll add a basic sanity-check in t4026 that "git add -p" works at all when color is enabled. That would have caught this bug, as well as any others that are specific to the color code paths. - 73c727d69 (log --graph: customize the graph lines with config log.graphColors, 2017-01-19) added a test to t4202 that checks some "invalid" graph color config. Since ",, blue" before yielded only "blue" as valid, and now yields "empty, empty, blue", we don't match the expected output. One way to fix this would be to change the expectation to the empty color strings. But that makes the test much less interesting, since we show only two graph lines, both of which would be colorless. Since the empty-string case is now covered by t4026, let's remove them entirely here. They're just in the way of the primary thing the test is supposed to be checking. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-01 00:21:29 +00:00
test_config log.graphColors " blue,invalid-color, cyan, red , " &&
lib_test_cmp_colored_graph --date-order --format=%s
'
test_expect_success 'log --raw --graph -m with merge' '
git log --raw --graph --oneline -m main | head -n 500 >actual &&
grep "initial" actual
'
test_expect_success 'diff-tree --graph' '
git diff-tree --graph main^ | head -n 500 >actual &&
grep "one" actual
'
cat > expect <<\EOF
* commit main
|\ Merge: A B
| | Author: A U Thor <author@example.com>
| |
| | Merge branch 'side'
| |
name-rev: favor describing with tags and use committer date to tiebreak "git name-rev" assigned a phony "far in the future" date to tips of refs that are not pointing at tag objects, and favored names based on a ref with the oldest date. This made it almost impossible for an unannotated tags and branches to be counted as a viable base, which was especially problematic when the command is run with the "--tags" option. If an unannotated tag that points at an ancient commit and an annotated tag that points at a much newer commit reaches the commit that is being named, the old unannotated tag was ignored. Update the "taggerdate" field of the rev-name structure, which is initialized from the tip of ref, to have the committer date if the object at the tip of ref is a commit, not a tag, so that we can optionally take it into account when doing "is this name better?" comparison logic. When "name-rev" is run without the "--tags" option, the general expectation is still to name the commit based on a tag if possible, but use non-tag refs as fallback, and tiebreak among these non-tag refs by favoring names with shorter hops from the tip. The use of a phony "far in the future" date in the original code was an effective way to ensure this expectation is held: a non-tag tip gets the same "far in the future" timestamp, giving precedence to tags, and among non-tag tips, names with shorter hops are preferred over longer hops, without taking the "taggerdate" into account. As we are taking over the "taggerdate" field to store the committer date for tips with commits: (1) keep the original logic when comparing names based on two refs both of which are from refs/tags/; (2) favoring a name based on a ref in refs/tags/ hierarchy over a ref outside the hierarchy; (3) between two names based on a ref both outside refs/tags/, give precedence to a name with shorter hops and use "taggerdate" only to tie-break. A change to t4202 is a natural consequence. The test creates a commit on a branch "side" and points at it with an unannotated tag "refs/tags/side-2". The original code couldn't decide which one to favor at all, and gave a name based on a branch (simply because refs/heads/side sorts earlier than refs/tags/side-2). Because the updated logic is taught to favor refs in refs/tags/ hierarchy, the the test is updated to expect to see tags/side-2 instead. [mjg: open-coded the comparisons in is_better_name(), dropping a helper macro used in the original] Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael J Gruber <git@grubix.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-29 14:39:16 +00:00
| * commit tags/side-2
| | Author: A U Thor <author@example.com>
| |
| | side-2
| |
| * commit tags/side-1
| | Author: A U Thor <author@example.com>
| |
| | side-1
| |
* | commit main~1
| | Author: A U Thor <author@example.com>
| |
| | Second
| |
* | commit main~2
| | Author: A U Thor <author@example.com>
| |
| | sixth
| |
* | commit main~3
| | Author: A U Thor <author@example.com>
| |
| | fifth
| |
* | commit main~4
|/ Author: A U Thor <author@example.com>
|
| fourth
|
* commit tags/side-1~1
| Author: A U Thor <author@example.com>
|
| third
|
* commit tags/side-1~2
| Author: A U Thor <author@example.com>
|
| second
|
* commit tags/side-1~3
Author: A U Thor <author@example.com>
initial
EOF
test_expect_success 'log --graph with full output' '
git log --graph --date-order --pretty=short |
git name-rev --name-only --annotate-stdin |
sed "s/Merge:.*/Merge: A B/;s/ *\$//" >actual &&
test_cmp expect actual
'
test_expect_success 'set up more tangled history' '
git checkout -b tangle HEAD~6 &&
test_commit tangle-a tangle-a a &&
git merge main~3 &&
git update-ref refs/prefetch/merge HEAD &&
git merge side~1 &&
git update-ref refs/rewritten/merge HEAD &&
git checkout main &&
git merge tangle &&
git update-ref refs/hidden/tangle HEAD &&
git checkout -b reach &&
test_commit reach &&
git checkout main &&
git checkout -b octopus-a &&
test_commit octopus-a &&
git checkout main &&
git checkout -b octopus-b &&
test_commit octopus-b &&
git checkout main &&
test_commit seventh &&
git merge octopus-a octopus-b &&
git merge reach
'
cat > expect <<\EOF
* Merge tag 'reach'
|\
| \
| \
*-. \ Merge tags 'octopus-a' and 'octopus-b'
|\ \ \
* | | | seventh
| | * | octopus-b
| |/ /
|/| |
| * | octopus-a
|/ /
| * reach
|/
* Merge branch 'tangle'
|\
| * Merge branch 'side' (early part) into tangle
| |\
| * \ Merge branch 'main' (early part) into tangle
| |\ \
| * | | tangle-a
* | | | Merge branch 'side'
|\ \ \ \
| * | | | side-2
| | |_|/
| |/| |
| * | | side-1
* | | | Second
* | | | sixth
| |_|/
|/| |
* | | fifth
* | | fourth
|/ /
* / third
|/
* second
* initial
EOF
test_expect_success 'log --graph with merge' '
test_cmp_graph --date-order
'
test_expect_success 'log.decorate configuration' '
git log --oneline --no-decorate >expect.none &&
git log --oneline --decorate >expect.short &&
git log --oneline --decorate=full >expect.full &&
echo "[log] decorate" >>.git/config &&
git log --oneline >actual &&
test_cmp expect.short actual &&
test_config log.decorate true &&
git log --oneline >actual &&
test_cmp expect.short actual &&
git log --oneline --decorate=full >actual &&
test_cmp expect.full actual &&
git log --oneline --decorate=no >actual &&
test_cmp expect.none actual &&
test_config log.decorate no &&
git log --oneline >actual &&
test_cmp expect.none actual &&
git log --oneline --decorate >actual &&
test_cmp expect.short actual &&
git log --oneline --decorate=full >actual &&
test_cmp expect.full actual &&
test_config log.decorate 1 &&
git log --oneline >actual &&
test_cmp expect.short actual &&
git log --oneline --decorate=full >actual &&
test_cmp expect.full actual &&
git log --oneline --decorate=no >actual &&
test_cmp expect.none actual &&
test_config log.decorate short &&
git log --oneline >actual &&
test_cmp expect.short actual &&
git log --oneline --no-decorate >actual &&
test_cmp expect.none actual &&
git log --oneline --decorate=full >actual &&
test_cmp expect.full actual &&
test_config log.decorate full &&
git log --oneline >actual &&
test_cmp expect.full actual &&
git log --oneline --no-decorate >actual &&
test_cmp expect.none actual &&
git log --oneline --decorate >actual &&
test_cmp expect.short actual &&
test_unconfig log.decorate &&
git log --pretty=raw >expect.raw &&
test_config log.decorate full &&
git log --pretty=raw >actual &&
test_cmp expect.raw actual
'
config API: add "string" version of *_value_multi(), fix segfaults Fix numerous and mostly long-standing segfaults in consumers of the *_config_*value_multi() API. As discussed in the preceding commit an empty key in the config syntax yields a "NULL" string, which these users would give to strcmp() (or similar), resulting in segfaults. As this change shows, most users users of the *_config_*value_multi() API didn't really want such an an unsafe and low-level API, let's give them something with the safety of git_config_get_string() instead. This fix is similar to what the *_string() functions and others acquired in[1] and [2]. Namely introducing and using a safer "*_get_string_multi()" variant of the low-level "_*value_multi()" function. This fixes segfaults in code introduced in: - d811c8e17c6 (versionsort: support reorder prerelease suffixes, 2015-02-26) - c026557a373 (versioncmp: generalize version sort suffix reordering, 2016-12-08) - a086f921a72 (submodule: decouple url and submodule interest, 2017-03-17) - a6be5e6764a (log: add log.excludeDecoration config option, 2020-04-16) - 92156291ca8 (log: add default decoration filter, 2022-08-05) - 50a044f1e40 (gc: replace config subprocesses with API calls, 2022-09-27) There are now two users ofthe low-level API: - One in "builtin/for-each-repo.c", which we'll convert in a subsequent commit. - The "t/helper/test-config.c" code added in [3]. As seen in the preceding commit we need to give the "t/helper/test-config.c" caller these "NULL" entries. We could also alter the underlying git_configset_get_value_multi() function to be "string safe", but doing so would leave no room for other variants of "*_get_value_multi()" that coerce to other types. Such coercion can't be built on the string version, since as we've established "NULL" is a true value in the boolean context, but if we coerced it to "" for use in a list of strings it'll be subsequently coerced to "false" as a boolean. The callback pattern being used here will make it easy to introduce e.g. a "multi" variant which coerces its values to "bool", "int", "path" etc. 1. 40ea4ed9032 (Add config_error_nonbool() helper function, 2008-02-11) 2. 6c47d0e8f39 (config.c: guard config parser from value=NULL, 2008-02-11). 3. 4c715ebb96a (test-config: add tests for the config_set API, 2014-07-28) Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-28 14:04:27 +00:00
test_expect_success 'parse log.excludeDecoration with no value' '
cp .git/config .git/config.orig &&
test_when_finished mv .git/config.orig .git/config &&
cat >>.git/config <<-\EOF &&
[log]
excludeDecoration
EOF
config API: add "string" version of *_value_multi(), fix segfaults Fix numerous and mostly long-standing segfaults in consumers of the *_config_*value_multi() API. As discussed in the preceding commit an empty key in the config syntax yields a "NULL" string, which these users would give to strcmp() (or similar), resulting in segfaults. As this change shows, most users users of the *_config_*value_multi() API didn't really want such an an unsafe and low-level API, let's give them something with the safety of git_config_get_string() instead. This fix is similar to what the *_string() functions and others acquired in[1] and [2]. Namely introducing and using a safer "*_get_string_multi()" variant of the low-level "_*value_multi()" function. This fixes segfaults in code introduced in: - d811c8e17c6 (versionsort: support reorder prerelease suffixes, 2015-02-26) - c026557a373 (versioncmp: generalize version sort suffix reordering, 2016-12-08) - a086f921a72 (submodule: decouple url and submodule interest, 2017-03-17) - a6be5e6764a (log: add log.excludeDecoration config option, 2020-04-16) - 92156291ca8 (log: add default decoration filter, 2022-08-05) - 50a044f1e40 (gc: replace config subprocesses with API calls, 2022-09-27) There are now two users ofthe low-level API: - One in "builtin/for-each-repo.c", which we'll convert in a subsequent commit. - The "t/helper/test-config.c" code added in [3]. As seen in the preceding commit we need to give the "t/helper/test-config.c" caller these "NULL" entries. We could also alter the underlying git_configset_get_value_multi() function to be "string safe", but doing so would leave no room for other variants of "*_get_value_multi()" that coerce to other types. Such coercion can't be built on the string version, since as we've established "NULL" is a true value in the boolean context, but if we coerced it to "" for use in a list of strings it'll be subsequently coerced to "false" as a boolean. The callback pattern being used here will make it easy to introduce e.g. a "multi" variant which coerces its values to "bool", "int", "path" etc. 1. 40ea4ed9032 (Add config_error_nonbool() helper function, 2008-02-11) 2. 6c47d0e8f39 (config.c: guard config parser from value=NULL, 2008-02-11). 3. 4c715ebb96a (test-config: add tests for the config_set API, 2014-07-28) Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-28 14:04:27 +00:00
cat >expect <<-\EOF &&
error: missing value for '\''log.excludeDecoration'\''
EOF
git log --decorate=short 2>actual &&
test_cmp expect actual
'
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
test_expect_success 'decorate-refs with glob' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh
octopus-b (octopus-b)
octopus-a (octopus-a)
reach
EOF
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
cat >expect.no-decorate <<-\EOF &&
Merge-tag-reach
Merge-tags-octopus-a-and-octopus-b
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
seventh
octopus-b
octopus-a
reach
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs="heads/octopus*" >actual &&
test_cmp expect.decorate actual &&
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
git log -n6 --decorate=short --pretty="tformat:%f%d" \
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
--decorate-refs-exclude="heads/octopus*" \
--decorate-refs="heads/octopus*" >actual &&
test_cmp expect.no-decorate actual &&
git -c log.excludeDecoration="heads/octopus*" log \
-n6 --decorate=short --pretty="tformat:%f%d" \
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
--decorate-refs="heads/octopus*" >actual &&
test_cmp expect.decorate actual
'
test_expect_success 'decorate-refs without globs' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh
octopus-b
octopus-a
reach (tag: reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs="tags/reach" >actual &&
test_cmp expect.decorate actual
'
test_expect_success 'multiple decorate-refs' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh
octopus-b (octopus-b)
octopus-a (octopus-a)
reach (tag: reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs="heads/octopus*" \
--decorate-refs="tags/reach" >actual &&
test_cmp expect.decorate actual
'
test_expect_success 'decorate-refs-exclude with glob' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh (tag: seventh)
octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a)
reach (tag: reach, reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="heads/octopus*" >actual &&
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="heads/octopus*" log \
-n6 --decorate=short --pretty="tformat:%f%d" >actual &&
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
test_cmp expect.decorate actual
'
test_expect_success 'decorate-refs-exclude without globs' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh (tag: seventh)
octopus-b (tag: octopus-b, octopus-b)
octopus-a (tag: octopus-a, octopus-a)
reach (reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="tags/reach" >actual &&
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="tags/reach" log \
-n6 --decorate=short --pretty="tformat:%f%d" >actual &&
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
test_cmp expect.decorate actual
'
test_expect_success 'multiple decorate-refs-exclude' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh (tag: seventh)
octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a)
reach (reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="heads/octopus*" \
--decorate-refs-exclude="tags/reach" >actual &&
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="heads/octopus*" \
-c log.excludeDecoration="tags/reach" log \
-n6 --decorate=short --pretty="tformat:%f%d" >actual &&
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="heads/octopus*" log \
--decorate-refs-exclude="tags/reach" \
-n6 --decorate=short --pretty="tformat:%f%d" >actual &&
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
test_cmp expect.decorate actual
'
test_expect_success 'decorate-refs and decorate-refs-exclude' '
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
cat >expect.no-decorate <<-\EOF &&
Merge-tag-reach (main)
Merge-tags-octopus-a-and-octopus-b
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
seventh
octopus-b
octopus-a
reach (reach)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs="heads/*" \
--decorate-refs-exclude="heads/oc*" >actual &&
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
test_cmp expect.no-decorate actual
'
test_expect_success 'deocrate-refs and log.excludeDecoration' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (main)
Merge-tags-octopus-a-and-octopus-b
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
seventh
octopus-b (octopus-b)
octopus-a (octopus-a)
reach (reach)
EOF
git -c log.excludeDecoration="heads/oc*" log \
--decorate-refs="heads/*" \
-n6 --decorate=short --pretty="tformat:%f%d" >actual &&
log: add option to choose which refs to decorate When `log --decorate` is used, git will decorate commits with all available refs. While in most cases this may give the desired effect, under some conditions it can lead to excessively verbose output. Introduce two command line options, `--decorate-refs=<pattern>` and `--decorate-refs-exclude=<pattern>` to allow the user to select which refs are used in decoration. When "--decorate-refs=<pattern>" is given, only the refs that match the pattern are used in decoration. The refs that match the pattern when "--decorate-refs-exclude=<pattern>" is given, are never used in decoration. These options follow the same convention for mixing negative and positive patterns across the system, assuming that the inclusive default is to match all refs available. (1) if there is no positive pattern given, pretend as if an inclusive default positive pattern was given; (2) for each candidate, reject it if it matches no positive pattern, or if it matches any one of the negative patterns. The rules for what is considered a match are slightly different from the rules used elsewhere. Commands like `log --glob` assume a trailing '/*' when glob chars are not present in the pattern. This makes it difficult to specify a single ref. On the other hand, commands like `describe --match --all` allow specifying exact refs, but do not have the convenience of allowing "shorthand refs" like 'refs/heads' or 'heads' to refer to 'refs/heads/*'. The commands introduced in this patch consider a match if: (a) the pattern contains globs chars, and regular pattern matching returns a match. (b) the pattern does not contain glob chars, and ref '<pattern>' exists, or if ref exists under '<pattern>/' This allows both behaviours (allowing single refs and shorthand refs) yet remaining compatible with existent commands. Helped-by: Kevin Daudt <me@ikke.info> Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Rafael Ascensão <rafa.almas@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-11-21 21:33:41 +00:00
test_cmp expect.decorate actual
'
test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
reach (tag: reach, reach)
seventh (tag: seventh)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="*octopus*" \
--simplify-by-decoration >actual &&
log: add log.excludeDecoration config option In 'git log', the --decorate-refs-exclude option appends a pattern to a string_list. This list is used to prevent showing some refs in the decoration output, or even by --simplify-by-decoration. Users may want to use their refs space to store utility refs that should not appear in the decoration output. For example, Scalar [1] runs a background fetch but places the "new" refs inside the refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/* to avoid updating remote refs when the user is not looking. However, these "hidden" refs appear during regular 'git log' queries. A similar idea to use "hidden" refs is under consideration for core Git [2]. Add the 'log.excludeDecoration' config option so users can exclude some refs from decorations by default instead of needing to use --decorate-refs-exclude manually. The config value is multi-valued much like the command-line option. The documentation is careful to point out that the config value can be overridden by the --decorate-refs option, even though --decorate-refs-exclude would always "win" over --decorate-refs. Since the 'log.excludeDecoration' takes lower precedence to --decorate-refs, and --decorate-refs-exclude takes higher precedence, the struct decoration_filter needed another field. This led also to new logic in load_ref_decorations() and ref_filter_match(). There are several tests in t4202-log.sh that test the --decorate-refs-(include|exclude) options, so these are extended. Since the expected output is already stored as a file, most tests could simply replace a "--decorate-refs-exclude" option with an in-line config setting. Other tests involve the precedence of the config option compared to command-line options and needed more modification. [1] https://github.com/microsoft/scalar [2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/ Helped-by: Junio C Hamano <gister@pobox.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-16 14:15:49 +00:00
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="*octopus*" log \
-n6 --decorate=short --pretty="tformat:%f%d" \
--simplify-by-decoration >actual &&
test_cmp expect.decorate actual
'
log: handle --decorate-refs with userformat "%d" In order to show ref decorations, we first have to load them. If you run: git log --decorate then git-log will recognize the option and load them up front via cmd_log_init(). Likewise if log.decorate is set. If you don't say --decorate explicitly, but do mention "%d" or "%D" in the output format, like so: git log --format=%d then this also works, because we lazy-load the ref decorations. This has been true since 3b3d443feb (add '%d' pretty format specifier to show decoration, 2008-09-04), though the lazy-load was later moved into log-tree.c. But there's one problem: that lazy-load just uses the defaults; it doesn't take into account any --decorate-refs options (or its exclude variant, or their config). So this does not work: git log --decorate-refs=whatever --format=%d It will decorate using all refs, not just the specified ones. This has been true since --decorate-refs was added in 65516f586b (log: add option to choose which refs to decorate, 2017-11-21). Adding further confusion is that it _may_ work because of the auto-decoration feature. If that's in use (and it often is, as it's the default), then if the output is going to stdout, we do enable decorations early (and so load them up front, respecting the extra options). But otherwise we do not. So: git log --decorate-refs=whatever --format=%d >some-file would typically behave differently than it does when the output goes to the pager or terminal! The solution is simple: we should recognize in cmd_log_init() that we're going to show decorations, and make sure we load them there. We already check userformat_find_requirements(), so we can couple this with our existing code there. There are two new tests. The first shows off the actual fix. The second makes sure that our fix doesn't cause us to stomp on an existing --decorate option (see the new comment in the code, as well). Reported-by: Josh Rampersad <josh.rampersad@voiceflow.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-12-02 05:35:43 +00:00
test_expect_success 'decorate-refs with implied decorate from format' '
cat >expect <<-\EOF &&
side-2 (tag: side-2)
side-1
EOF
git log --no-walk --format="%s%d" \
--decorate-refs="*side-2" side-1 side-2 \
>actual &&
test_cmp expect actual
'
test_expect_success 'implied decorate does not override option' '
cat >expect <<-\EOF &&
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
EOF
git log --no-walk --format="%s%d" \
--decorate=full side-1 side-2 \
>actual &&
test_cmp expect actual
'
test_expect_success 'decorate-refs and simplify-by-decoration without output' '
cat >expect <<-\EOF &&
side-2
initial
EOF
# Do not just use a --format without %d here; we want to
# make sure that we did not accidentally turn on displaying
# the decorations, too. And that requires one of the regular
# formats.
git log --decorate-refs="*side-2" --oneline \
--simplify-by-decoration >actual.raw &&
sed "s/^[0-9a-f]* //" <actual.raw >actual &&
test_cmp expect actual
'
test_expect_success 'decorate-refs-exclude HEAD' '
git log --decorate=full --oneline \
--decorate-refs-exclude="HEAD" >actual &&
! grep HEAD actual
'
log: add default decoration filter When a user runs 'git log', they expect a certain set of helpful decorations. This includes: * The HEAD ref * Branches (refs/heads/) * Stashes (refs/stash) * Tags (refs/tags/) * Remote branches (refs/remotes/) * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE) Each of these namespaces was selected due to existing test cases that verify these namespaces appear in the decorations. In particular, stashes and replace refs can have custom colors from the color.decorate.<slot> config option. While one test checks for a decoration from notes, it only applies to the tip of refs/notes/commit (or its configured ref name). Notes form their own kind of decoration instead. Modify the expected output for the tests in t4013 that expect this note decoration. There are several tests throughout the codebase that verify that --decorate-refs, --decorate-refs-exclude, and log.excludeDecoration work as designed and the tests continue to pass without intervention. However, there are other refs that are less helpful to show as decoration: * Prefetch refs (refs/prefetch/) * Rebase refs (refs/rebase-merge/ and refs/rebase-apply/) * Bundle refs (refs/bundle/) [!] [!] The bundle refs are part of a parallel series that bootstraps a repo from a bundle file, storing the bundle's refs into the repo's refs/bundle/ namespace. In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set log.excludeDecoration durin prefetch, 2021-01-19) added logic to add refs/prefetch/ to the log.excludeDecoration config option. Additional feedback pointed out that having such a side-effect can be confusing and perhaps not helpful to users. Instead, we should hide these ref namespaces that are being used by Git for internal reasons but are not helpful for the users to see. The way to provide a seamless user experience without setting the config is to modify the default decoration filters to match our expectation of what refs the user actually wants to see. In builtin/log.c, after parsing the --decorate-refs and --decorate-refs-exclude options from the command-line, call set_default_decoration_filter(). This method populates the exclusions from log.excludeDecoration, then checks if the list of pattern modifications are empty. If none are specified, then the default set is restricted to the set of inclusions mentioned earlier (HEAD, branches, etc.). A previous change introduced the ref_namespaces array, which includes all of these currently-used namespaces. The 'decoration' value is non-zero when that namespace is associated with a special coloring and fits into the list of "expected" decorations as described above, which makes the implementation of this filter very simple. Note that the logic in ref_filter_match() in log-tree.c follows this matching pattern: 1. If there are exclusion patterns and the ref matches one, then ignore the decoration. 2. If there are inclusion patterns and the ref matches one, then definitely include the decoration. 3. If there are config-based exclusions from log.excludeDecoration and the ref matches one, then ignore the decoration. With this logic in mind, we need to ensure that we do not populate our new defaults if any of these filters are manually set. Specifically, if a user runs git -c log.excludeDecoration=HEAD log then we expect the HEAD decoration to not appear. If we left the default inclusions in the set, then HEAD would match that inclusion before reaching the config-based exclusions. A potential alternative would be to check the list of default inclusions at the end, after the config-based exclusions. This would still create a behavior change for some uses of --decorate-refs-exclude=<X>, and could be overwritten somewhat with --decorate-refs=refs/ and --decorate-refs=HEAD. However, it no longer becomes possible to include refs outside of the defaults while also excluding some using log.excludeDecoration. Another alternative would be to exclude the known namespaces that are not intended to be shown. This would reduce the visible effect of the change for expert users who use their own custom ref namespaces. The implementation change would be very simple to swap due to our use of ref_namespaces: int i; struct string_list *exclude = decoration_filter->exclude_ref_pattern; /* * No command-line or config options were given, so * populate with sensible defaults. */ for (i = 0; i < NAMESPACE__COUNT; i++) { if (ref_namespaces[i].decoration) continue; string_list_append(exclude, ref_namespaces[i].ref); } The main downside of this approach is that we expect to add new hidden namespaces in the future, and that means that Git versions will be less stable in how they behave as those namespaces are added. It is critical that we provide ways for expert users to disable this behavior change via command-line options and config keys. These changes will be implemented in a future change. Add a test that checks that the defaults are not added when --decorate-refs is specified. We verify this by showing that HEAD is not included as it normally would. Also add a test that shows that the default filter avoids the unwanted decorations from refs/prefetch, refs/rebase-merge, and refs/bundle. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
test_expect_success 'decorate-refs focus from default' '
git log --decorate=full --oneline \
--decorate-refs="refs/heads" >actual &&
! grep HEAD actual
'
test_expect_success '--clear-decorations overrides defaults' '
cat >expect.default <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b
seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-branch-tangle
Merge-branch-side-early-part-into-tangle (refs/heads/tangle)
Merge-branch-main-early-part-into-tangle
tangle-a (tag: refs/tags/tangle-a)
Merge-branch-side
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
Second
sixth
fifth
fourth
third
second
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" >actual &&
test_cmp expect.default actual &&
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b
seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
tangle-a (tag: refs/tags/tangle-a)
Merge-branch-side
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
Second
sixth
fifth
fourth
third
second
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--clear-decorations >actual &&
test_cmp expect.all actual &&
git -c log.initialDecorationSet=all log \
--decorate=full --pretty="tformat:%f%d" >actual &&
test_cmp expect.all actual
'
test_expect_success '--clear-decorations clears previous exclusions' '
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-tags-octopus-a-and-octopus-b
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
seventh (tag: refs/tags/seventh)
Merge-branch-tangle (refs/hidden/tangle)
Merge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)
Merge-branch-main-early-part-into-tangle (refs/prefetch/merge)
tangle-a (tag: refs/tags/tangle-a)
side-2 (tag: refs/tags/side-2, refs/heads/side)
side-1 (tag: refs/tags/side-1)
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--simplify-by-decoration \
--decorate-refs-exclude="heads/octopus*" \
--decorate-refs="heads" \
--clear-decorations >actual &&
test_cmp expect.all actual &&
cat >expect.filtered <<-\EOF &&
Merge-tags-octopus-a-and-octopus-b
octopus-b (refs/heads/octopus-b)
octopus-a (refs/heads/octopus-a)
initial
EOF
git log --decorate=full --pretty="tformat:%f%d" \
--simplify-by-decoration \
--decorate-refs-exclude="heads/octopus" \
--decorate-refs="heads" \
--clear-decorations \
--decorate-refs-exclude="tags/" \
--decorate-refs="heads/octopus*" >actual &&
test_cmp expect.filtered actual
'
test_expect_success 'log.decorate config parsing' '
git log --oneline --decorate=full >expect.full &&
git log --oneline --decorate=short >expect.short &&
test_config log.decorate full &&
test_config log.mailmap true &&
git log --oneline >actual &&
test_cmp expect.full actual &&
git log --oneline --decorate=short >actual &&
test_cmp expect.short actual
'
test_expect_success TTY 'log output on a TTY' '
git log --color --oneline --decorate >expect.short &&
test_terminal git log --oneline >actual &&
test_cmp expect.short actual
'
test_expect_success 'reflog is expected format' '
git log -g --abbrev-commit --pretty=oneline >expect &&
git reflog >actual &&
test_cmp expect actual
'
test_expect_success 'whatchanged is expected format' '
git log --no-merges --raw >expect &&
git whatchanged >actual &&
test_cmp expect actual
'
test_expect_success 'log.abbrevCommit configuration' '
git log --abbrev-commit >expect.log.abbrev &&
git log --no-abbrev-commit >expect.log.full &&
git log --pretty=raw >expect.log.raw &&
git reflog --abbrev-commit >expect.reflog.abbrev &&
git reflog --no-abbrev-commit >expect.reflog.full &&
git whatchanged --abbrev-commit >expect.whatchanged.abbrev &&
git whatchanged --no-abbrev-commit >expect.whatchanged.full &&
test_config log.abbrevCommit true &&
git log >actual &&
test_cmp expect.log.abbrev actual &&
git log --no-abbrev-commit >actual &&
test_cmp expect.log.full actual &&
git log --pretty=raw >actual &&
test_cmp expect.log.raw actual &&
git reflog >actual &&
test_cmp expect.reflog.abbrev actual &&
git reflog --no-abbrev-commit >actual &&
test_cmp expect.reflog.full actual &&
git whatchanged >actual &&
test_cmp expect.whatchanged.abbrev actual &&
git whatchanged --no-abbrev-commit >actual &&
test_cmp expect.whatchanged.full actual
'
test_expect_success 'show added path under "--follow -M"' '
# This tests for a regression introduced in v1.7.2-rc0~103^2~2
test_create_repo regression &&
(
cd regression &&
test_commit needs-another-commit &&
test_commit foo.bar &&
git log -M --follow -p foo.bar.t &&
git log -M --follow --stat foo.bar.t &&
git log -M --follow --name-only foo.bar.t
)
'
test_expect_success 'git log -c --follow' '
test_create_repo follow-c &&
(
cd follow-c &&
test_commit initial file original &&
git rm file &&
test_commit rename file2 original &&
git reset --hard initial &&
test_commit modify file foo &&
git merge -m merge rename &&
git log -c --follow file2
)
'
cat >expect <<\EOF
* commit COMMIT_OBJECT_NAME
|\ Merge: MERGE_PARENTS
| | Author: A U Thor <author@example.com>
| |
| | Merge HEADS DESCRIPTION
| |
| * commit COMMIT_OBJECT_NAME
| | Author: A U Thor <author@example.com>
| |
| | reach
| | ---
| | reach.t | 1 +
| | 1 file changed, 1 insertion(+)
| |
| | diff --git a/reach.t b/reach.t
| | new file mode 100644
| | index BEFORE..AFTER
| | --- /dev/null
| | +++ b/reach.t
| | @@ -0,0 +1 @@
| | +reach
| |
| \
*-. \ commit COMMIT_OBJECT_NAME
|\ \ \ Merge: MERGE_PARENTS
| | | | Author: A U Thor <author@example.com>
| | | |
| | | | Merge HEADS DESCRIPTION
| | | |
| | * | commit COMMIT_OBJECT_NAME
| | |/ Author: A U Thor <author@example.com>
| | |
| | | octopus-b
| | | ---
| | | octopus-b.t | 1 +
| | | 1 file changed, 1 insertion(+)
| | |
| | | diff --git a/octopus-b.t b/octopus-b.t
| | | new file mode 100644
| | | index BEFORE..AFTER
| | | --- /dev/null
| | | +++ b/octopus-b.t
| | | @@ -0,0 +1 @@
| | | +octopus-b
| | |
| * | commit COMMIT_OBJECT_NAME
| |/ Author: A U Thor <author@example.com>
| |
| | octopus-a
| | ---
| | octopus-a.t | 1 +
| | 1 file changed, 1 insertion(+)
| |
| | diff --git a/octopus-a.t b/octopus-a.t
| | new file mode 100644
| | index BEFORE..AFTER
| | --- /dev/null
| | +++ b/octopus-a.t
| | @@ -0,0 +1 @@
| | +octopus-a
| |
* | commit COMMIT_OBJECT_NAME
|/ Author: A U Thor <author@example.com>
|
| seventh
| ---
| seventh.t | 1 +
| 1 file changed, 1 insertion(+)
|
| diff --git a/seventh.t b/seventh.t
| new file mode 100644
| index BEFORE..AFTER
| --- /dev/null
| +++ b/seventh.t
| @@ -0,0 +1 @@
| +seventh
|
* commit COMMIT_OBJECT_NAME
|\ Merge: MERGE_PARENTS
| | Author: A U Thor <author@example.com>
| |
| | Merge branch 'tangle'
| |
| * commit COMMIT_OBJECT_NAME
| |\ Merge: MERGE_PARENTS
| | | Author: A U Thor <author@example.com>
| | |
| | | Merge branch 'side' (early part) into tangle
| | |
| * | commit COMMIT_OBJECT_NAME
| |\ \ Merge: MERGE_PARENTS
| | | | Author: A U Thor <author@example.com>
| | | |
| | | | Merge branch 'main' (early part) into tangle
| | | |
| * | | commit COMMIT_OBJECT_NAME
| | | | Author: A U Thor <author@example.com>
| | | |
| | | | tangle-a
| | | | ---
| | | | tangle-a | 1 +
| | | | 1 file changed, 1 insertion(+)
| | | |
| | | | diff --git a/tangle-a b/tangle-a
| | | | new file mode 100644
| | | | index BEFORE..AFTER
| | | | --- /dev/null
| | | | +++ b/tangle-a
| | | | @@ -0,0 +1 @@
| | | | +a
| | | |
* | | | commit COMMIT_OBJECT_NAME
|\ \ \ \ Merge: MERGE_PARENTS
| | | | | Author: A U Thor <author@example.com>
| | | | |
| | | | | Merge branch 'side'
| | | | |
| * | | | commit COMMIT_OBJECT_NAME
| | |_|/ Author: A U Thor <author@example.com>
| |/| |
| | | | side-2
| | | | ---
| | | | 2 | 1 +
| | | | 1 file changed, 1 insertion(+)
| | | |
| | | | diff --git a/2 b/2
| | | | new file mode 100644
| | | | index BEFORE..AFTER
| | | | --- /dev/null
| | | | +++ b/2
| | | | @@ -0,0 +1 @@
| | | | +2
| | | |
| * | | commit COMMIT_OBJECT_NAME
| | | | Author: A U Thor <author@example.com>
| | | |
| | | | side-1
| | | | ---
| | | | 1 | 1 +
| | | | 1 file changed, 1 insertion(+)
| | | |
| | | | diff --git a/1 b/1
| | | | new file mode 100644
| | | | index BEFORE..AFTER
| | | | --- /dev/null
| | | | +++ b/1
| | | | @@ -0,0 +1 @@
| | | | +1
| | | |
* | | | commit COMMIT_OBJECT_NAME
| | | | Author: A U Thor <author@example.com>
| | | |
| | | | Second
| | | | ---
| | | | one | 1 +
| | | | 1 file changed, 1 insertion(+)
| | | |
| | | | diff --git a/one b/one
| | | | new file mode 100644
| | | | index BEFORE..AFTER
| | | | --- /dev/null
| | | | +++ b/one
| | | | @@ -0,0 +1 @@
| | | | +case
| | | |
* | | | commit COMMIT_OBJECT_NAME
| |_|/ Author: A U Thor <author@example.com>
|/| |
| | | sixth
| | | ---
| | | a/two | 1 -
| | | 1 file changed, 1 deletion(-)
| | |
| | | diff --git a/a/two b/a/two
| | | deleted file mode 100644
| | | index BEFORE..AFTER
| | | --- a/a/two
| | | +++ /dev/null
| | | @@ -1 +0,0 @@
| | | -ni
| | |
* | | commit COMMIT_OBJECT_NAME
| | | Author: A U Thor <author@example.com>
| | |
| | | fifth
| | | ---
| | | a/two | 1 +
| | | 1 file changed, 1 insertion(+)
| | |
| | | diff --git a/a/two b/a/two
| | | new file mode 100644
| | | index BEFORE..AFTER
| | | --- /dev/null
| | | +++ b/a/two
| | | @@ -0,0 +1 @@
| | | +ni
| | |
* | | commit COMMIT_OBJECT_NAME
|/ / Author: A U Thor <author@example.com>
| |
| | fourth
| | ---
| | ein | 1 +
| | 1 file changed, 1 insertion(+)
| |
| | diff --git a/ein b/ein
| | new file mode 100644
| | index BEFORE..AFTER
| | --- /dev/null
| | +++ b/ein
| | @@ -0,0 +1 @@
| | +ichi
| |
* | commit COMMIT_OBJECT_NAME
|/ Author: A U Thor <author@example.com>
|
| third
| ---
| ichi | 1 +
| one | 1 -
| 2 files changed, 1 insertion(+), 1 deletion(-)
|
| diff --git a/ichi b/ichi
| new file mode 100644
| index BEFORE..AFTER
| --- /dev/null
| +++ b/ichi
| @@ -0,0 +1 @@
| +ichi
| diff --git a/one b/one
| deleted file mode 100644
| index BEFORE..AFTER
| --- a/one
| +++ /dev/null
| @@ -1 +0,0 @@
| -ichi
|
* commit COMMIT_OBJECT_NAME
| Author: A U Thor <author@example.com>
|
| second
| ---
| one | 2 +-
| 1 file changed, 1 insertion(+), 1 deletion(-)
|
| diff --git a/one b/one
| index BEFORE..AFTER 100644
| --- a/one
| +++ b/one
| @@ -1 +1 @@
| -one
| +ichi
|
* commit COMMIT_OBJECT_NAME
Author: A U Thor <author@example.com>
initial
---
one | 1 +
1 file changed, 1 insertion(+)
diff --git a/one b/one
new file mode 100644
index BEFORE..AFTER
--- /dev/null
+++ b/one
@@ -0,0 +1 @@
+one
EOF
test_expect_success 'log --graph with diff and stats' '
lib_test_cmp_short_graph --no-renames --stat -p
'
cat >expect <<\EOF
*** * commit COMMIT_OBJECT_NAME
*** |\ Merge: MERGE_PARENTS
*** | | Author: A U Thor <author@example.com>
*** | |
*** | | Merge HEADS DESCRIPTION
*** | |
*** | * commit COMMIT_OBJECT_NAME
*** | | Author: A U Thor <author@example.com>
*** | |
*** | | reach
*** | | ---
*** | | reach.t | 1 +
*** | | 1 file changed, 1 insertion(+)
*** | |
*** | | diff --git a/reach.t b/reach.t
*** | | new file mode 100644
*** | | index BEFORE..AFTER
*** | | --- /dev/null
*** | | +++ b/reach.t
*** | | @@ -0,0 +1 @@
*** | | +reach
*** | |
*** | \
*** *-. \ commit COMMIT_OBJECT_NAME
*** |\ \ \ Merge: MERGE_PARENTS
*** | | | | Author: A U Thor <author@example.com>
*** | | | |
*** | | | | Merge HEADS DESCRIPTION
*** | | | |
*** | | * | commit COMMIT_OBJECT_NAME
*** | | |/ Author: A U Thor <author@example.com>
*** | | |
*** | | | octopus-b
*** | | | ---
*** | | | octopus-b.t | 1 +
*** | | | 1 file changed, 1 insertion(+)
*** | | |
*** | | | diff --git a/octopus-b.t b/octopus-b.t
*** | | | new file mode 100644
*** | | | index BEFORE..AFTER
*** | | | --- /dev/null
*** | | | +++ b/octopus-b.t
*** | | | @@ -0,0 +1 @@
*** | | | +octopus-b
*** | | |
*** | * | commit COMMIT_OBJECT_NAME
*** | |/ Author: A U Thor <author@example.com>
*** | |
*** | | octopus-a
*** | | ---
*** | | octopus-a.t | 1 +
*** | | 1 file changed, 1 insertion(+)
*** | |
*** | | diff --git a/octopus-a.t b/octopus-a.t
*** | | new file mode 100644
*** | | index BEFORE..AFTER
*** | | --- /dev/null
*** | | +++ b/octopus-a.t
*** | | @@ -0,0 +1 @@
*** | | +octopus-a
*** | |
*** * | commit COMMIT_OBJECT_NAME
*** |/ Author: A U Thor <author@example.com>
*** |
*** | seventh
*** | ---
*** | seventh.t | 1 +
*** | 1 file changed, 1 insertion(+)
*** |
*** | diff --git a/seventh.t b/seventh.t
*** | new file mode 100644
*** | index BEFORE..AFTER
*** | --- /dev/null
*** | +++ b/seventh.t
*** | @@ -0,0 +1 @@
*** | +seventh
*** |
*** * commit COMMIT_OBJECT_NAME
*** |\ Merge: MERGE_PARENTS
*** | | Author: A U Thor <author@example.com>
*** | |
*** | | Merge branch 'tangle'
*** | |
*** | * commit COMMIT_OBJECT_NAME
*** | |\ Merge: MERGE_PARENTS
*** | | | Author: A U Thor <author@example.com>
*** | | |
*** | | | Merge branch 'side' (early part) into tangle
*** | | |
*** | * | commit COMMIT_OBJECT_NAME
*** | |\ \ Merge: MERGE_PARENTS
*** | | | | Author: A U Thor <author@example.com>
*** | | | |
*** | | | | Merge branch 'main' (early part) into tangle
*** | | | |
*** | * | | commit COMMIT_OBJECT_NAME
*** | | | | Author: A U Thor <author@example.com>
*** | | | |
*** | | | | tangle-a
*** | | | | ---
*** | | | | tangle-a | 1 +
*** | | | | 1 file changed, 1 insertion(+)
*** | | | |
*** | | | | diff --git a/tangle-a b/tangle-a
*** | | | | new file mode 100644
*** | | | | index BEFORE..AFTER
*** | | | | --- /dev/null
*** | | | | +++ b/tangle-a
*** | | | | @@ -0,0 +1 @@
*** | | | | +a
*** | | | |
*** * | | | commit COMMIT_OBJECT_NAME
*** |\ \ \ \ Merge: MERGE_PARENTS
*** | | | | | Author: A U Thor <author@example.com>
*** | | | | |
*** | | | | | Merge branch 'side'
*** | | | | |
*** | * | | | commit COMMIT_OBJECT_NAME
*** | | |_|/ Author: A U Thor <author@example.com>
*** | |/| |
*** | | | | side-2
*** | | | | ---
*** | | | | 2 | 1 +
*** | | | | 1 file changed, 1 insertion(+)
*** | | | |
*** | | | | diff --git a/2 b/2
*** | | | | new file mode 100644
*** | | | | index BEFORE..AFTER
*** | | | | --- /dev/null
*** | | | | +++ b/2
*** | | | | @@ -0,0 +1 @@
*** | | | | +2
*** | | | |
*** | * | | commit COMMIT_OBJECT_NAME
*** | | | | Author: A U Thor <author@example.com>
*** | | | |
*** | | | | side-1
*** | | | | ---
*** | | | | 1 | 1 +
*** | | | | 1 file changed, 1 insertion(+)
*** | | | |
*** | | | | diff --git a/1 b/1
*** | | | | new file mode 100644
*** | | | | index BEFORE..AFTER
*** | | | | --- /dev/null
*** | | | | +++ b/1
*** | | | | @@ -0,0 +1 @@
*** | | | | +1
*** | | | |
*** * | | | commit COMMIT_OBJECT_NAME
*** | | | | Author: A U Thor <author@example.com>
*** | | | |
*** | | | | Second
*** | | | | ---
*** | | | | one | 1 +
*** | | | | 1 file changed, 1 insertion(+)
*** | | | |
*** | | | | diff --git a/one b/one
*** | | | | new file mode 100644
*** | | | | index BEFORE..AFTER
*** | | | | --- /dev/null
*** | | | | +++ b/one
*** | | | | @@ -0,0 +1 @@
*** | | | | +case
*** | | | |
*** * | | | commit COMMIT_OBJECT_NAME
*** | |_|/ Author: A U Thor <author@example.com>
*** |/| |
*** | | | sixth
*** | | | ---
*** | | | a/two | 1 -
*** | | | 1 file changed, 1 deletion(-)
*** | | |
*** | | | diff --git a/a/two b/a/two
*** | | | deleted file mode 100644
*** | | | index BEFORE..AFTER
*** | | | --- a/a/two
*** | | | +++ /dev/null
*** | | | @@ -1 +0,0 @@
*** | | | -ni
*** | | |
*** * | | commit COMMIT_OBJECT_NAME
*** | | | Author: A U Thor <author@example.com>
*** | | |
*** | | | fifth
*** | | | ---
*** | | | a/two | 1 +
*** | | | 1 file changed, 1 insertion(+)
*** | | |
*** | | | diff --git a/a/two b/a/two
*** | | | new file mode 100644
*** | | | index BEFORE..AFTER
*** | | | --- /dev/null
*** | | | +++ b/a/two
*** | | | @@ -0,0 +1 @@
*** | | | +ni
*** | | |
*** * | | commit COMMIT_OBJECT_NAME
*** |/ / Author: A U Thor <author@example.com>
*** | |
*** | | fourth
*** | | ---
*** | | ein | 1 +
*** | | 1 file changed, 1 insertion(+)
*** | |
*** | | diff --git a/ein b/ein
*** | | new file mode 100644
*** | | index BEFORE..AFTER
*** | | --- /dev/null
*** | | +++ b/ein
*** | | @@ -0,0 +1 @@
*** | | +ichi
*** | |
*** * | commit COMMIT_OBJECT_NAME
*** |/ Author: A U Thor <author@example.com>
*** |
*** | third
*** | ---
*** | ichi | 1 +
*** | one | 1 -
*** | 2 files changed, 1 insertion(+), 1 deletion(-)
*** |
*** | diff --git a/ichi b/ichi
*** | new file mode 100644
*** | index BEFORE..AFTER
*** | --- /dev/null
*** | +++ b/ichi
*** | @@ -0,0 +1 @@
*** | +ichi
*** | diff --git a/one b/one
*** | deleted file mode 100644
*** | index BEFORE..AFTER
*** | --- a/one
*** | +++ /dev/null
*** | @@ -1 +0,0 @@
*** | -ichi
*** |
*** * commit COMMIT_OBJECT_NAME
*** | Author: A U Thor <author@example.com>
*** |
*** | second
*** | ---
*** | one | 2 +-
*** | 1 file changed, 1 insertion(+), 1 deletion(-)
*** |
*** | diff --git a/one b/one
*** | index BEFORE..AFTER 100644
*** | --- a/one
*** | +++ b/one
*** | @@ -1 +1 @@
*** | -one
*** | +ichi
*** |
*** * commit COMMIT_OBJECT_NAME
*** Author: A U Thor <author@example.com>
***
*** initial
*** ---
*** one | 1 +
*** 1 file changed, 1 insertion(+)
***
*** diff --git a/one b/one
*** new file mode 100644
*** index BEFORE..AFTER
*** --- /dev/null
*** +++ b/one
*** @@ -0,0 +1 @@
*** +one
EOF
test_expect_success 'log --line-prefix="*** " --graph with diff and stats' '
lib_test_cmp_short_graph --line-prefix="*** " --no-renames --stat -p
'
cat >expect <<-\EOF
* reach
|
| A reach.t
* Merge branch 'tangle'
* Merge branch 'side'
|\
| * side-2
|
| A 2
* Second
|
| A one
* sixth
D a/two
EOF
test_expect_success 'log --graph with --name-status' '
test_cmp_graph --name-status tangle..reach
'
cat >expect <<-\EOF
* reach
|
| reach.t
* Merge branch 'tangle'
* Merge branch 'side'
|\
| * side-2
|
| 2
* Second
|
| one
* sixth
a/two
EOF
test_expect_success 'log --graph with --name-only' '
test_cmp_graph --name-only tangle..reach
'
test_expect_success '--no-graph countermands --graph' '
git log >expect &&
git log --graph --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--graph countermands --no-graph' '
git log --graph >expect &&
git log --no-graph --graph >actual &&
test_cmp expect actual
'
test_expect_success '--no-graph does not unset --topo-order' '
git log --topo-order >expect &&
git log --topo-order --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--no-graph does not unset --parents' '
git log --parents >expect &&
git log --parents --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--reverse and --graph conflict' '
test_must_fail git log --reverse --graph 2>stderr &&
test_i18ngrep "cannot be used together" stderr
'
test_expect_success '--reverse --graph --no-graph works' '
git log --reverse >expect &&
git log --reverse --graph --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--show-linear-break and --graph conflict' '
test_must_fail git log --show-linear-break --graph 2>stderr &&
test_i18ngrep "cannot be used together" stderr
'
test_expect_success '--show-linear-break --graph --no-graph works' '
git log --show-linear-break >expect &&
git log --show-linear-break --graph --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--no-walk and --graph conflict' '
test_must_fail git log --no-walk --graph 2>stderr &&
test_i18ngrep "cannot be used together" stderr
'
test_expect_success '--no-walk --graph --no-graph works' '
git log --no-walk >expect &&
git log --no-walk --graph --no-graph >actual &&
test_cmp expect actual
'
test_expect_success '--walk-reflogs and --graph conflict' '
test_must_fail git log --walk-reflogs --graph 2>stderr &&
(test_i18ngrep "cannot combine" stderr ||
test_i18ngrep "cannot be used together" stderr)
'
test_expect_success '--walk-reflogs --graph --no-graph works' '
git log --walk-reflogs >expect &&
git log --walk-reflogs --graph --no-graph >actual &&
test_cmp expect actual
'
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_expect_success GPG 'setup signed branch' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b signed main &&
echo foo >foo &&
git add foo &&
git commit -S -m signed_commit
'
gpg-interface: limit search for primary key fingerprint The VALIDSIG status line from GnuPG with --status-fd is documented to have 9 required and 1 optional fields [1]. The final, and optional, field is used to specify the fingerprint of the primary key that made the signature in case it was made by a subkey. However, this field is only available for OpenPGP signatures; not for CMS/X.509. If the VALIDSIG status line does not have the optional 10th field, the current code will continue reading onto the next status line. And this is the case for non-OpenPGP signatures [1]. The consequence is that a subsequent status line may be considered as the "primary key" for signatures that does not have an actual primary key. Limit the search of these 9 or 10 fields to the single line to avoid this problem. If the 10th field is missing, report that there is no primary key fingerprint. [Reference] [1] GnuPG Details, General status codes https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=6ce340e8c04794add995e84308bb3091450bd28f;hb=HEAD#l483 The documentation says: VALIDSIG <args> The args are: - <fingerprint_in_hex> - <sig_creation_date> - <sig-timestamp> - <expire-timestamp> - <sig-version> - <reserved> - <pubkey-algo> - <hash-algo> - <sig-class> - [ <primary-key-fpr> ] This status indicates that the signature is cryptographically valid. [...] PRIMARY-KEY-FPR is the fingerprint of the primary key or identical to the first argument. The primary-key-fpr parameter is used for OpenPGP and not available for CMS signatures. [...] Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-22 20:23:12 +00:00
test_expect_success GPG 'setup signed branch with subkey' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b signed-subkey main &&
gpg-interface: limit search for primary key fingerprint The VALIDSIG status line from GnuPG with --status-fd is documented to have 9 required and 1 optional fields [1]. The final, and optional, field is used to specify the fingerprint of the primary key that made the signature in case it was made by a subkey. However, this field is only available for OpenPGP signatures; not for CMS/X.509. If the VALIDSIG status line does not have the optional 10th field, the current code will continue reading onto the next status line. And this is the case for non-OpenPGP signatures [1]. The consequence is that a subsequent status line may be considered as the "primary key" for signatures that does not have an actual primary key. Limit the search of these 9 or 10 fields to the single line to avoid this problem. If the 10th field is missing, report that there is no primary key fingerprint. [Reference] [1] GnuPG Details, General status codes https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=6ce340e8c04794add995e84308bb3091450bd28f;hb=HEAD#l483 The documentation says: VALIDSIG <args> The args are: - <fingerprint_in_hex> - <sig_creation_date> - <sig-timestamp> - <expire-timestamp> - <sig-version> - <reserved> - <pubkey-algo> - <hash-algo> - <sig-class> - [ <primary-key-fpr> ] This status indicates that the signature is cryptographically valid. [...] PRIMARY-KEY-FPR is the fingerprint of the primary key or identical to the first argument. The primary-key-fpr parameter is used for OpenPGP and not available for CMS signatures. [...] Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-22 20:23:12 +00:00
echo foo >foo &&
git add foo &&
git commit -SB7227189 -m signed_commit
'
test_expect_success GPGSM 'setup signed branch x509' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b signed-x509 main &&
echo foo >foo &&
git add foo &&
test_config gpg.format x509 &&
test_config user.signingkey $GIT_COMMITTER_EMAIL &&
git commit -S -m signed_commit
'
test_expect_success GPGSSH 'setup sshkey signed branch' '
test_config gpg.format ssh &&
test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b signed-ssh main &&
echo foo >foo &&
git add foo &&
git commit -S -m signed_commit
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'create signed commits with keys having defined lifetimes' '
test_config gpg.format ssh &&
touch file &&
git add file &&
echo expired >file && test_tick && git commit -a -m expired -S"${GPGSSH_KEY_EXPIRED}" &&
git tag expired-signed &&
echo notyetvalid >file && test_tick && git commit -a -m notyetvalid -S"${GPGSSH_KEY_NOTYETVALID}" &&
git tag notyetvalid-signed &&
echo timeboxedvalid >file && test_tick && git commit -a -m timeboxedvalid -S"${GPGSSH_KEY_TIMEBOXEDVALID}" &&
git tag timeboxedvalid-signed &&
echo timeboxedinvalid >file && test_tick && git commit -a -m timeboxedinvalid -S"${GPGSSH_KEY_TIMEBOXEDINVALID}" &&
git tag timeboxedinvalid-signed
'
gpg-interface: limit search for primary key fingerprint The VALIDSIG status line from GnuPG with --status-fd is documented to have 9 required and 1 optional fields [1]. The final, and optional, field is used to specify the fingerprint of the primary key that made the signature in case it was made by a subkey. However, this field is only available for OpenPGP signatures; not for CMS/X.509. If the VALIDSIG status line does not have the optional 10th field, the current code will continue reading onto the next status line. And this is the case for non-OpenPGP signatures [1]. The consequence is that a subsequent status line may be considered as the "primary key" for signatures that does not have an actual primary key. Limit the search of these 9 or 10 fields to the single line to avoid this problem. If the 10th field is missing, report that there is no primary key fingerprint. [Reference] [1] GnuPG Details, General status codes https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=6ce340e8c04794add995e84308bb3091450bd28f;hb=HEAD#l483 The documentation says: VALIDSIG <args> The args are: - <fingerprint_in_hex> - <sig_creation_date> - <sig-timestamp> - <expire-timestamp> - <sig-version> - <reserved> - <pubkey-algo> - <hash-algo> - <sig-class> - [ <primary-key-fpr> ] This status indicates that the signature is cryptographically valid. [...] PRIMARY-KEY-FPR is the fingerprint of the primary key or identical to the first argument. The primary-key-fpr parameter is used for OpenPGP and not available for CMS signatures. [...] Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-22 20:23:12 +00:00
test_expect_success GPGSM 'log x509 fingerprint' '
echo "F8BF62E0693D0694816377099909C779FA23FD65 | " >expect &&
git log -n1 --format="%GF | %GP" signed-x509 >actual &&
test_cmp expect actual
'
test_expect_success GPGSM 'log OpenPGP fingerprint' '
echo "D4BE22311AD3131E5EDA29A461092E85B7227189" > expect &&
git log -n1 --format="%GP" signed-subkey >actual &&
test_cmp expect actual
'
test_expect_success GPGSSH 'log ssh key fingerprint' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2\" | \"}" >expect &&
git log -n1 --format="%GF | %GP" signed-ssh >actual &&
test_cmp expect actual
'
test_expect_success GPG 'log --graph --show-signature' '
git log --graph --show-signature -n1 signed >actual &&
grep "^| gpg: Signature made" actual &&
grep "^| gpg: Good signature" actual
'
test_expect_success GPGSM 'log --graph --show-signature x509' '
git log --graph --show-signature -n1 signed-x509 >actual &&
grep "^| gpgsm: Signature made" actual &&
grep "^| gpgsm: Good signature" actual
'
test_expect_success GPGSSH 'log --graph --show-signature ssh' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git log --graph --show-signature -n1 signed-ssh >actual &&
grep "${GOOD_SIGNATURE_TRUSTED}" actual
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'log shows failure on expired signature key' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git log --graph --show-signature -n1 expired-signed >actual &&
! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'log shows failure on not yet valid signature key' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git log --graph --show-signature -n1 notyetvalid-signed >actual &&
! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'log show success with commit date and key validity matching' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git log --graph --show-signature -n1 timeboxedvalid-signed >actual &&
grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual &&
! grep "${GPGSSH_BAD_SIGNATURE}" actual
'
test_expect_success GPGSSH,GPGSSH_VERIFYTIME 'log shows failure with commit date outside of key validity' '
test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
git log --graph --show-signature -n1 timeboxedinvalid-signed >actual &&
! grep "${GPGSSH_GOOD_SIGNATURE_TRUSTED}" actual
'
test_expect_success GPG 'log --graph --show-signature for merged tag' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain main &&
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged main &&
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag &&
git checkout plain &&
git merge --no-ff -m msg signed_tag &&
git log --graph --show-signature -n1 plain >actual &&
grep "^|\\\ merged tag" actual &&
grep "^| | gpg: Signature made" actual &&
grep "^| | gpg: Good signature" actual
'
test_expect_success GPG 'log --graph --show-signature for merged tag in shallow clone' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain-shallow main &&
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout --detach main &&
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_shallow &&
hash=$(git rev-parse HEAD) &&
git checkout plain-shallow &&
git merge --no-ff -m msg signed_tag_shallow &&
git clone --depth 1 --no-local . shallow &&
test_when_finished "rm -rf shallow" &&
git -C shallow log --graph --show-signature -n1 plain-shallow >actual &&
grep "tag signed_tag_shallow names a non-parent $hash" actual
'
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
test_expect_success GPG 'log --graph --show-signature for merged tag with missing key' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain-nokey main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-nokey main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_nokey &&
git checkout plain-nokey &&
git merge --no-ff -m msg signed_tag_nokey &&
GNUPGHOME=. git log --graph --show-signature -n1 plain-nokey >actual &&
grep "^|\\\ merged tag" actual &&
grep "^| | gpg: Signature made" actual &&
grep -E "^| | gpg: Can'"'"'t check signature: (public key not found|No public key)" actual
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
'
test_expect_success GPG 'log --graph --show-signature for merged tag with bad signature' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain-bad main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-bad main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_bad &&
git cat-file tag signed_tag_bad >raw &&
sed -e "s/signed_tag_msg/forged/" raw >forged &&
git hash-object -w -t tag forged >forged.tag &&
git checkout plain-bad &&
git merge --no-ff -m msg "$(cat forged.tag)" &&
git log --graph --show-signature -n1 plain-bad >actual &&
grep "^|\\\ merged tag" actual &&
grep "^| | gpg: Signature made" actual &&
grep "^| | gpg: BAD signature from" actual
'
test_expect_success GPG 'log --show-signature for merged tag with GPG failure' '
test_when_finished "git reset --hard && git checkout main" &&
git checkout -b plain-fail main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-fail main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_fail &&
git checkout plain-fail &&
git merge --no-ff -m msg signed_tag_fail &&
if ! test_have_prereq VALGRIND
then
TMPDIR="$(pwd)/bogus" git log --show-signature -n1 plain-fail >actual &&
grep "^merged tag" actual &&
grep "^No signature" actual &&
! grep "^gpg: Signature made" actual
fi
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
'
test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' '
test_when_finished "git reset --hard && git checkout main" &&
test_config gpg.format x509 &&
test_config user.signingkey $GIT_COMMITTER_EMAIL &&
git checkout -b plain-x509 main &&
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-x509 main &&
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_x509 &&
git checkout plain-x509 &&
git merge --no-ff -m msg signed_tag_x509 &&
git log --graph --show-signature -n1 plain-x509 >actual &&
grep "^|\\\ merged tag" actual &&
grep "^| | gpgsm: Signature made" actual &&
grep "^| | gpgsm: Good signature" actual
'
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
test_expect_success GPGSM 'log --graph --show-signature for merged tag x509 missing key' '
test_when_finished "git reset --hard && git checkout main" &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
test_config gpg.format x509 &&
test_config user.signingkey $GIT_COMMITTER_EMAIL &&
git checkout -b plain-x509-nokey main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-x509-nokey main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_x509_nokey &&
git checkout plain-x509-nokey &&
git merge --no-ff -m msg signed_tag_x509_nokey &&
GNUPGHOME=. git log --graph --show-signature -n1 plain-x509-nokey >actual &&
grep "^|\\\ merged tag" actual &&
grep -e "^| | gpgsm: certificate not found" \
-e "^| | gpgsm: failed to find the certificate: Not found" actual
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
'
test_expect_success GPGSM 'log --graph --show-signature for merged tag x509 bad signature' '
test_when_finished "git reset --hard && git checkout main" &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
test_config gpg.format x509 &&
test_config user.signingkey $GIT_COMMITTER_EMAIL &&
git checkout -b plain-x509-bad main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo aaa >bar &&
git add bar &&
git commit -m bar_commit &&
git checkout -b tagged-x509-bad main &&
t: increase test coverage of signature verification output There weren't any tests for unsuccessful signature verification of signed merge tags shown in 'git log'. There also weren't any tests for the GPG output from 'git fmt-merge-msg'. This was noticed while investigating a buggy refactor that slipped through the test suite; see commit 72b006f4bfd30b7c5037c163efaf279ab65bea9c. This commit adds signature verification tests to the 'log' and 'fmt-merge-msg' builtins. Thanks to Linus Torvalds for reporting and finding the (now reverted) commit that introduced the regression. Note that the "log --show-signature for merged tag with GPG failure" test case is really hacky. It relies on an implementation detail of verify_signed_buffer() -- namely, it assumes that the signature is written to a temporary file whose path is under TMPDIR. The rationale for that test case is to check whether the code path that yields the "No signature" message is reachable on failure. The functionality in log-tree.c that may show this message does some pre-parsing of a possible signature that prevents the GPG interface from being invoked if a signature is actually missing. And I haven't been able to construct a signature that both 1. satisfies that pre-processing, and 2. causes GPG to fail without any sort of output on stderr along the lines of "this is a bogus/corrupt/... signature" (the "No signature" message should only be shown if GPG produce no output). Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> [jc: fixed missing test title noticed by Dscho] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-03-04 11:48:03 +00:00
echo bbb >baz &&
git add baz &&
git commit -m baz_commit &&
git tag -s -m signed_tag_msg signed_tag_x509_bad &&
git cat-file tag signed_tag_x509_bad >raw &&
sed -e "s/signed_tag_msg/forged/" raw >forged &&
git hash-object -w -t tag forged >forged.tag &&
git checkout plain-x509-bad &&
git merge --no-ff -m msg "$(cat forged.tag)" &&
git log --graph --show-signature -n1 plain-x509-bad >actual &&
grep "^|\\\ merged tag" actual &&
grep "^| | gpgsm: Signature made" actual &&
grep "^| | gpgsm: invalid signature" actual
'
test_expect_success GPG '--no-show-signature overrides --show-signature' '
git log -1 --show-signature --no-show-signature signed >actual &&
! grep "^gpg:" actual
'
test_expect_success GPG 'log.showsignature=true behaves like --show-signature' '
test_config log.showsignature true &&
git log -1 signed >actual &&
grep "gpg: Signature made" actual &&
grep "gpg: Good signature" actual
'
test_expect_success GPG '--no-show-signature overrides log.showsignature=true' '
test_config log.showsignature true &&
git log -1 --no-show-signature signed >actual &&
! grep "^gpg:" actual
'
test_expect_success GPG '--show-signature overrides log.showsignature=false' '
test_config log.showsignature false &&
git log -1 --show-signature signed >actual &&
grep "gpg: Signature made" actual &&
grep "gpg: Good signature" actual
'
test_expect_success 'log --graph --no-walk is forbidden' '
test_must_fail git log --graph --no-walk
'
test_expect_success 'log on empty repo fails' '
git init empty &&
test_when_finished "rm -rf empty" &&
test_must_fail git -C empty log 2>stderr &&
test_i18ngrep does.not.have.any.commits stderr
'
test_expect_success REFFILES 'log diagnoses bogus HEAD hash' '
git init empty &&
test_when_finished "rm -rf empty" &&
echo 1234abcd >empty/.git/refs/heads/main &&
test_must_fail git -C empty log 2>stderr &&
test_i18ngrep broken stderr
'
test_expect_success REFFILES 'log diagnoses bogus HEAD symref' '
git init empty &&
echo "ref: refs/heads/invalid.lock" > empty/.git/HEAD &&
test_must_fail git -C empty log 2>stderr &&
test_i18ngrep broken stderr &&
test_must_fail git -C empty log --default totally-bogus 2>stderr &&
test_i18ngrep broken stderr
'
test_expect_success 'log does not default to HEAD when rev input is given' '
git log --branches=does-not-exist >actual &&
test_must_be_empty actual
'
revision: set rev_input_given in handle_revision_arg() Commit 7ba826290a (revision: add rev_input_given flag, 2017-08-02) added a flag to rev_info to tell whether we got any revision arguments. As explained there, this is necessary because some revision arguments may not produce any pending traversal objects, but should still inhibit default behaviors (e.g., a glob that matches nothing). However, it only set the flag in the globbing code, but not for revisions we get on the command-line or via stdin. This leads to two problems: - the command-line code keeps its own separate got_rev_arg flag; this isn't wrong, but it's confusing and an extra maintenance burden - even specifically-named rev arguments might end up not adding any pending objects: if --ignore-missing is set, then specifying a missing object is a noop rather than an error. And that leads to some user-visible bugs: - when deciding whether a default rev like "HEAD" should kick in, we check both got_rev_arg and rev_input_given. That means that "--ignore-missing $ZERO_OID" works on the command-line (where we set got_rev_arg) but not on --stdin (where we don't) - when rev-list decides whether it should complain that it wasn't given a starting point, it relies on rev_input_given. So it can't even get the command-line "--ignore-missing $ZERO_OID" right Let's consistently set the flag if we got any revision argument. That lets us clean up the redundant got_rev_arg, and fixes both of those bugs (but note there are three new tests: we'll confirm the already working git-log command-line case). A few implementation notes: - conceptually we want to set the flag whenever handle_revision_arg() finds an actual revision arg ("handles" it, you might say). But it covers a ton of cases with early returns. Rather than annotating each one, we just wrap it and use its success exit-code to set the flag in one spot. - the new rev-list test is in t6018, which is titled to cover globs. This isn't exactly a glob, but it made sense to stick it with the other tests that handle the "even though we got a rev, we have no pending objects" case, which are globs. - the tests check for the oid of a missing object, which it's pretty clear --ignore-missing should ignore. You can see the same behavior with "--ignore-missing a-ref-that-does-not-exist", because --ignore-missing treats them both the same. That's perhaps less clearly correct, and we may want to change that in the future. But the way the code and tests here are written, we'd continue to do the right thing even if it does. Reported-by: Bryan Turner <bturner@atlassian.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-08-26 20:13:05 +00:00
test_expect_success 'do not default to HEAD with ignored object on cmdline' '
git log --ignore-missing $ZERO_OID >actual &&
test_must_be_empty actual
'
test_expect_success 'do not default to HEAD with ignored object on stdin' '
echo $ZERO_OID | git log --ignore-missing --stdin >actual &&
test_must_be_empty actual
'
test_expect_success 'set up --source tests' '
git checkout --orphan source-a &&
test_commit one &&
test_commit two &&
git checkout -b source-b HEAD^ &&
test_commit three
'
test_expect_success 'log --source paints branch names' '
cat >expect <<-EOF &&
$(git rev-parse --short :/three) source-b three
$(git rev-parse --short :/two ) source-a two
$(git rev-parse --short :/one ) source-b one
EOF
git log --oneline --source source-a source-b >actual &&
test_cmp expect actual
'
test_expect_success 'log --source paints tag names' '
git tag -m tagged source-tag &&
cat >expect <<-EOF &&
$(git rev-parse --short :/three) source-tag three
$(git rev-parse --short :/two ) source-a two
$(git rev-parse --short :/one ) source-tag one
EOF
git log --oneline --source source-tag source-a >actual &&
test_cmp expect actual
'
handle_revision_arg: reset "dotdot" consistently When we are parsing a range like "a..b", we write a temporary NUL over the first ".", so that we can access the names "a" and "b" as C strings. But our restoration of the original "." is done at inconsistent times, which can lead to confusing results. For most calls, we restore the "." after we resolve the names, but before we call verify_non_filename(). This means that when we later call add_pending_object(), the name for the left-hand "a" has been re-expanded to "a..b". You can see this with: git log --source a...b where "b" will be correctly marked with "b", but "a" will be marked with "a...b". Likewise with "a..b" (though you need to use --boundary to even see "a" at all in that case). To top off the confusion, when the REVARG_CANNOT_BE_FILENAME flag is set, we skip the non-filename check, and leave the NUL in place. That means we do report the correct name for "a" in the pending array. But some code paths try to show the whole "a...b" name in error messages, and these erroneously show only "a" instead of "a...b". E.g.: $ git cherry-pick HEAD:foo...HEAD:foo error: object d95f3ad14dee633a758d2e331151e950dd13e4ed is a blob, not a commit error: object d95f3ad14dee633a758d2e331151e950dd13e4ed is a blob, not a commit fatal: Invalid symmetric difference expression HEAD:foo (That last message should be "HEAD:foo...HEAD:foo"; I used cherry-pick because it passes the CANNOT_BE_FILENAME flag). As an interesting side note, cherry-pick actually looks at and re-resolves the arguments from the pending->name fields. So it would have been visibly broken by the first bug, but the effect was canceled out by the second one. This patch makes the whole function consistent by re-writing the NUL immediately after calling verify_non_filename(), and then restoring the "." as appropriate in some error-printing and early-return code paths. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-23 19:51:32 +00:00
test_expect_success 'log --source paints symmetric ranges' '
cat >expect <<-EOF &&
$(git rev-parse --short :/three) source-b three
$(git rev-parse --short :/two ) source-a two
handle_revision_arg: reset "dotdot" consistently When we are parsing a range like "a..b", we write a temporary NUL over the first ".", so that we can access the names "a" and "b" as C strings. But our restoration of the original "." is done at inconsistent times, which can lead to confusing results. For most calls, we restore the "." after we resolve the names, but before we call verify_non_filename(). This means that when we later call add_pending_object(), the name for the left-hand "a" has been re-expanded to "a..b". You can see this with: git log --source a...b where "b" will be correctly marked with "b", but "a" will be marked with "a...b". Likewise with "a..b" (though you need to use --boundary to even see "a" at all in that case). To top off the confusion, when the REVARG_CANNOT_BE_FILENAME flag is set, we skip the non-filename check, and leave the NUL in place. That means we do report the correct name for "a" in the pending array. But some code paths try to show the whole "a...b" name in error messages, and these erroneously show only "a" instead of "a...b". E.g.: $ git cherry-pick HEAD:foo...HEAD:foo error: object d95f3ad14dee633a758d2e331151e950dd13e4ed is a blob, not a commit error: object d95f3ad14dee633a758d2e331151e950dd13e4ed is a blob, not a commit fatal: Invalid symmetric difference expression HEAD:foo (That last message should be "HEAD:foo...HEAD:foo"; I used cherry-pick because it passes the CANNOT_BE_FILENAME flag). As an interesting side note, cherry-pick actually looks at and re-resolves the arguments from the pending->name fields. So it would have been visibly broken by the first bug, but the effect was canceled out by the second one. This patch makes the whole function consistent by re-writing the NUL immediately after calling verify_non_filename(), and then restoring the "." as appropriate in some error-printing and early-return code paths. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-23 19:51:32 +00:00
EOF
git log --oneline --source source-a...source-b >actual &&
test_cmp expect actual
'
test_expect_success '--exclude-promisor-objects does not BUG-crash' '
test_must_fail git log --exclude-promisor-objects source-a
'
load_ref_decorations(): fix decoration with tags Commit 88473c8bae ("load_ref_decorations(): avoid parsing non-tag objects", 2021-06-22) introduced a shortcut to `add_ref_decoration()`: Rather than calling `parse_object()`, we go for `oid_object_info()` and then `lookup_object_by_type()` using the type just discovered. As detailed in the commit message, this provides a significant time saving. Unfortunately, it also changes the behavior: We lose all annotated tags from the decoration. The reason this happens is in the loop where we try to peel the tags, we won't necessarily have parsed that first object. If we haven't, its `tagged` field will be NULL, so we won't actually add a decoration for the pointed-to object. Make sure to parse the tag object at the top of the peeling loop. This effectively restores the pre-88473c8bae parsing -- but only of tags, allowing us to keep most of the possible speedup from 88473c8bae. On my big ~220k ref test case (where it's mostly non-tags), the timings [using "git log -1 --decorate"] are: - before either patch: 2.945s - with my broken patch: 0.707s - with [this patch]: 0.788s The simplest way to do this is to just conditionally parse before the loop: if (obj->type == OBJ_TAG) parse_object(&obj->oid); But we can observe that our tag-peeling loop needs to peel already, to examine recursive tags-of-tags. So instead of introducing a new call to parse_object(), we can simply move the parsing higher in the loop: instead of parsing the new object before we loop, parse each tag object before we look at its "tagged" field. This has another beneficial side effect: if a tag points at a commit (or other non-tag type), we do not bother to parse the commit at all now. And we know it is a commit without calling oid_object_info(), because parsing the surrounding tag object will have created the correct in-core object based on the "type" field of the tag. Our test coverage for --decorate was obviously not good, since we missed this quite-basic regression. The new tests covers an annotated tag (showing the fix), but also that we correctly show annotations for lightweight tags and double-annotated tag-of-tags. Reported-by: Martin Ågren <martin.agren@gmail.com> Helped-by: Martin Ågren <martin.agren@gmail.com> Signed-off-by: Martin Ågren <martin.agren@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Reviewed-by: Martin Ågren <martin.agren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-14 16:31:36 +00:00
test_expect_success 'log --decorate includes all levels of tag annotated tags' '
git checkout -b branch &&
git commit --allow-empty -m "new commit" &&
git tag lightweight HEAD &&
git tag -m annotated annotated HEAD &&
git tag -m double-0 double-0 HEAD &&
git tag -m double-1 double-1 double-0 &&
cat >expect <<-\EOF &&
HEAD -> branch, tag: lightweight, tag: double-1, tag: double-0, tag: annotated
EOF
git log -1 --format="%D" >actual &&
test_cmp expect actual
'
log: add default decoration filter When a user runs 'git log', they expect a certain set of helpful decorations. This includes: * The HEAD ref * Branches (refs/heads/) * Stashes (refs/stash) * Tags (refs/tags/) * Remote branches (refs/remotes/) * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE) Each of these namespaces was selected due to existing test cases that verify these namespaces appear in the decorations. In particular, stashes and replace refs can have custom colors from the color.decorate.<slot> config option. While one test checks for a decoration from notes, it only applies to the tip of refs/notes/commit (or its configured ref name). Notes form their own kind of decoration instead. Modify the expected output for the tests in t4013 that expect this note decoration. There are several tests throughout the codebase that verify that --decorate-refs, --decorate-refs-exclude, and log.excludeDecoration work as designed and the tests continue to pass without intervention. However, there are other refs that are less helpful to show as decoration: * Prefetch refs (refs/prefetch/) * Rebase refs (refs/rebase-merge/ and refs/rebase-apply/) * Bundle refs (refs/bundle/) [!] [!] The bundle refs are part of a parallel series that bootstraps a repo from a bundle file, storing the bundle's refs into the repo's refs/bundle/ namespace. In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set log.excludeDecoration durin prefetch, 2021-01-19) added logic to add refs/prefetch/ to the log.excludeDecoration config option. Additional feedback pointed out that having such a side-effect can be confusing and perhaps not helpful to users. Instead, we should hide these ref namespaces that are being used by Git for internal reasons but are not helpful for the users to see. The way to provide a seamless user experience without setting the config is to modify the default decoration filters to match our expectation of what refs the user actually wants to see. In builtin/log.c, after parsing the --decorate-refs and --decorate-refs-exclude options from the command-line, call set_default_decoration_filter(). This method populates the exclusions from log.excludeDecoration, then checks if the list of pattern modifications are empty. If none are specified, then the default set is restricted to the set of inclusions mentioned earlier (HEAD, branches, etc.). A previous change introduced the ref_namespaces array, which includes all of these currently-used namespaces. The 'decoration' value is non-zero when that namespace is associated with a special coloring and fits into the list of "expected" decorations as described above, which makes the implementation of this filter very simple. Note that the logic in ref_filter_match() in log-tree.c follows this matching pattern: 1. If there are exclusion patterns and the ref matches one, then ignore the decoration. 2. If there are inclusion patterns and the ref matches one, then definitely include the decoration. 3. If there are config-based exclusions from log.excludeDecoration and the ref matches one, then ignore the decoration. With this logic in mind, we need to ensure that we do not populate our new defaults if any of these filters are manually set. Specifically, if a user runs git -c log.excludeDecoration=HEAD log then we expect the HEAD decoration to not appear. If we left the default inclusions in the set, then HEAD would match that inclusion before reaching the config-based exclusions. A potential alternative would be to check the list of default inclusions at the end, after the config-based exclusions. This would still create a behavior change for some uses of --decorate-refs-exclude=<X>, and could be overwritten somewhat with --decorate-refs=refs/ and --decorate-refs=HEAD. However, it no longer becomes possible to include refs outside of the defaults while also excluding some using log.excludeDecoration. Another alternative would be to exclude the known namespaces that are not intended to be shown. This would reduce the visible effect of the change for expert users who use their own custom ref namespaces. The implementation change would be very simple to swap due to our use of ref_namespaces: int i; struct string_list *exclude = decoration_filter->exclude_ref_pattern; /* * No command-line or config options were given, so * populate with sensible defaults. */ for (i = 0; i < NAMESPACE__COUNT; i++) { if (ref_namespaces[i].decoration) continue; string_list_append(exclude, ref_namespaces[i].ref); } The main downside of this approach is that we expect to add new hidden namespaces in the future, and that means that Git versions will be less stable in how they behave as those namespaces are added. It is critical that we provide ways for expert users to disable this behavior change via command-line options and config keys. These changes will be implemented in a future change. Add a test that checks that the defaults are not added when --decorate-refs is specified. We verify this by showing that HEAD is not included as it normally would. Also add a test that shows that the default filter avoids the unwanted decorations from refs/prefetch, refs/rebase-merge, and refs/bundle. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-08-05 17:58:39 +00:00
test_expect_success 'log --decorate does not include things outside filter' '
reflist="refs/prefetch refs/rebase-merge refs/bundle" &&
for ref in $reflist
do
git update-ref $ref/fake HEAD || return 1
done &&
git log --decorate=full --oneline >actual &&
# None of the refs are visible:
! grep /fake actual
'
test_expect_success 'log --end-of-options' '
git update-ref refs/heads/--source HEAD &&
git log --end-of-options --source >actual &&
git log >expect &&
test_cmp expect actual
'
test_expect_success 'set up commits with different authors' '
git checkout --orphan authors &&
test_commit --author "Jim <jim@example.com>" jim_1 &&
test_commit --author "Val <val@example.com>" val_1 &&
test_commit --author "Val <val@example.com>" val_2 &&
test_commit --author "Jim <jim@example.com>" jim_2 &&
test_commit --author "Val <val@example.com>" val_3 &&
test_commit --author "Jim <jim@example.com>" jim_3
'
test_expect_success 'log --invert-grep --grep --author' '
cat >expect <<-\EOF &&
val_3
val_1
EOF
git log --format=%s --author=Val --grep 2 --invert-grep >actual &&
test_cmp expect actual
'
test_done