2007-10-02 13:02:57 +02:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (c) 2007 Andy Parkins
|
|
|
|
#
|
|
|
|
|
|
|
|
test_description='for-each-ref test'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
2011-09-07 19:46:08 +02:00
|
|
|
. "$TEST_DIRECTORY"/lib-gpg.sh
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
. "$TEST_DIRECTORY"/lib-terminal.sh
|
2007-10-02 13:02:57 +02:00
|
|
|
|
2015-09-03 23:49:00 +02:00
|
|
|
# Mon Jul 3 23:18:43 2006 +0000
|
|
|
|
datestamp=1151968723
|
2007-10-02 13:02:57 +02:00
|
|
|
setdate_and_increment () {
|
|
|
|
GIT_COMMITTER_DATE="$datestamp +0200"
|
|
|
|
datestamp=$(expr "$datestamp" + 1)
|
|
|
|
GIT_AUTHOR_DATE="$datestamp +0200"
|
|
|
|
datestamp=$(expr "$datestamp" + 1)
|
|
|
|
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
|
|
|
|
}
|
|
|
|
|
2013-11-18 18:39:08 +01:00
|
|
|
test_expect_success setup '
|
2020-02-22 21:17:32 +01:00
|
|
|
test_oid_cache <<-EOF &&
|
|
|
|
disklen sha1:138
|
|
|
|
disklen sha256:154
|
|
|
|
EOF
|
2007-10-02 13:02:57 +02:00
|
|
|
setdate_and_increment &&
|
|
|
|
echo "Using $datestamp" > one &&
|
|
|
|
git add one &&
|
|
|
|
git commit -m "Initial" &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git branch -M main &&
|
2007-10-02 13:02:57 +02:00
|
|
|
setdate_and_increment &&
|
2013-11-18 18:39:08 +01:00
|
|
|
git tag -a -m "Tagging at $datestamp" testtag &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git update-ref refs/remotes/origin/main main &&
|
2009-04-07 09:09:39 +02:00
|
|
|
git remote add origin nowhere &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git config branch.main.remote origin &&
|
|
|
|
git config branch.main.merge refs/heads/main &&
|
2015-05-21 06:45:55 +02:00
|
|
|
git remote add myfork elsewhere &&
|
|
|
|
git config remote.pushdefault myfork &&
|
|
|
|
git config push.default current
|
2009-04-07 09:09:39 +02:00
|
|
|
'
|
|
|
|
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom() {
|
|
|
|
case "$1" in
|
2020-12-06 14:15:59 +01:00
|
|
|
head) ref=refs/heads/main ;;
|
2008-06-26 10:08:41 +02:00
|
|
|
tag) ref=refs/tags/testtag ;;
|
2017-01-10 09:49:42 +01:00
|
|
|
sym) ref=refs/heads/sym ;;
|
2011-09-07 19:43:28 +02:00
|
|
|
*) ref=$1 ;;
|
2008-06-26 10:08:41 +02:00
|
|
|
esac
|
|
|
|
printf '%s\n' "$3" >expected
|
2011-09-07 19:46:08 +02:00
|
|
|
test_expect_${4:-success} $PREREQ "basic atom: $1 $2" "
|
2008-06-26 10:08:41 +02:00
|
|
|
git for-each-ref --format='%($2)' $ref >actual &&
|
2011-09-07 19:46:08 +02:00
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
test_cmp expected actual.clean
|
2008-06-26 10:08:41 +02:00
|
|
|
"
|
2020-07-16 14:19:40 +02:00
|
|
|
# Automatically test "contents:size" atom after testing "contents"
|
|
|
|
if test "$2" = "contents"
|
|
|
|
then
|
2021-08-21 03:36:33 +02:00
|
|
|
# for commit leg, $3 is changed there
|
|
|
|
expect=$(printf '%s' "$3" | wc -c)
|
2020-07-31 20:26:07 +02:00
|
|
|
test_expect_${4:-success} $PREREQ "basic atom: $1 contents:size" '
|
2021-08-21 03:36:33 +02:00
|
|
|
type=$(git cat-file -t "$ref") &&
|
|
|
|
case $type in
|
|
|
|
tag)
|
|
|
|
# We cannot use $3 as it expects sanitize_pgp to run
|
2021-08-21 03:36:34 +02:00
|
|
|
git cat-file tag $ref >out &&
|
|
|
|
expect=$(tail -n +6 out | wc -c) &&
|
|
|
|
rm -f out ;;
|
2021-08-21 03:36:33 +02:00
|
|
|
tree | blob)
|
|
|
|
expect="" ;;
|
|
|
|
commit)
|
|
|
|
: "use the calculated expect" ;;
|
|
|
|
*)
|
|
|
|
BUG "unknown object type" ;;
|
|
|
|
esac &&
|
|
|
|
# Leave $expect unquoted to lose possible leading whitespaces
|
|
|
|
echo $expect >expected &&
|
2020-07-16 14:19:40 +02:00
|
|
|
git for-each-ref --format="%(contents:size)" "$ref" >actual &&
|
2020-07-31 20:26:07 +02:00
|
|
|
test_cmp expected actual
|
2020-07-16 14:19:40 +02:00
|
|
|
'
|
|
|
|
fi
|
2008-06-26 10:08:41 +02:00
|
|
|
}
|
|
|
|
|
2020-02-22 21:17:32 +01:00
|
|
|
hexlen=$(test_oid hexsz)
|
|
|
|
disklen=$(test_oid disklen)
|
|
|
|
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head refname refs/heads/main
|
|
|
|
test_atom head refname: refs/heads/main
|
|
|
|
test_atom head refname:short main
|
|
|
|
test_atom head refname:lstrip=1 heads/main
|
|
|
|
test_atom head refname:lstrip=2 main
|
|
|
|
test_atom head refname:lstrip=-1 main
|
|
|
|
test_atom head refname:lstrip=-2 heads/main
|
2017-01-10 09:49:49 +01:00
|
|
|
test_atom head refname:rstrip=1 refs/heads
|
|
|
|
test_atom head refname:rstrip=2 refs
|
|
|
|
test_atom head refname:rstrip=-1 refs
|
|
|
|
test_atom head refname:rstrip=-2 refs/heads
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head refname:strip=1 heads/main
|
|
|
|
test_atom head refname:strip=2 main
|
|
|
|
test_atom head refname:strip=-1 main
|
|
|
|
test_atom head refname:strip=-2 heads/main
|
|
|
|
test_atom head upstream refs/remotes/origin/main
|
|
|
|
test_atom head upstream:short origin/main
|
|
|
|
test_atom head upstream:lstrip=2 origin/main
|
|
|
|
test_atom head upstream:lstrip=-2 origin/main
|
2017-01-10 09:49:49 +01:00
|
|
|
test_atom head upstream:rstrip=2 refs/remotes
|
|
|
|
test_atom head upstream:rstrip=-2 refs/remotes
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head upstream:strip=2 origin/main
|
|
|
|
test_atom head upstream:strip=-2 origin/main
|
|
|
|
test_atom head push refs/remotes/myfork/main
|
|
|
|
test_atom head push:short myfork/main
|
|
|
|
test_atom head push:lstrip=1 remotes/myfork/main
|
|
|
|
test_atom head push:lstrip=-1 main
|
2017-01-10 09:49:49 +01:00
|
|
|
test_atom head push:rstrip=1 refs/remotes/myfork
|
|
|
|
test_atom head push:rstrip=-1 refs
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head push:strip=1 remotes/myfork/main
|
|
|
|
test_atom head push:strip=-1 main
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head objecttype commit
|
2020-02-22 21:17:32 +01:00
|
|
|
test_atom head objectsize $((131 + hexlen))
|
|
|
|
test_atom head objectsize:disk $disklen
|
|
|
|
test_atom head deltabase $ZERO_OID
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head objectname $(git rev-parse refs/heads/main)
|
|
|
|
test_atom head objectname:short $(git rev-parse --short refs/heads/main)
|
|
|
|
test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
|
|
|
|
test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
|
|
|
|
test_atom head tree $(git rev-parse refs/heads/main^{tree})
|
|
|
|
test_atom head tree:short $(git rev-parse --short refs/heads/main^{tree})
|
|
|
|
test_atom head tree:short=1 $(git rev-parse --short=1 refs/heads/main^{tree})
|
|
|
|
test_atom head tree:short=10 $(git rev-parse --short=10 refs/heads/main^{tree})
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head parent ''
|
2020-08-21 23:41:48 +02:00
|
|
|
test_atom head parent:short ''
|
|
|
|
test_atom head parent:short=1 ''
|
|
|
|
test_atom head parent:short=10 ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head numparent 0
|
|
|
|
test_atom head object ''
|
|
|
|
test_atom head type ''
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_atom head raw "$(git cat-file commit refs/heads/main)
|
|
|
|
"
|
2013-10-30 07:50:16 +01:00
|
|
|
test_atom head '*objectname' ''
|
|
|
|
test_atom head '*objecttype' ''
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head authorname 'A U Thor'
|
|
|
|
test_atom head authoremail '<author@example.com>'
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom head authoremail:trim 'author@example.com'
|
|
|
|
test_atom head authoremail:localpart 'author'
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
|
|
|
|
test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head committername 'C O Mitter'
|
|
|
|
test_atom head committeremail '<committer@example.com>'
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom head committeremail:trim 'committer@example.com'
|
|
|
|
test_atom head committeremail:localpart 'committer'
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head tag ''
|
|
|
|
test_atom head tagger ''
|
|
|
|
test_atom head taggername ''
|
|
|
|
test_atom head taggeremail ''
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom head taggeremail:trim ''
|
|
|
|
test_atom head taggeremail:localpart ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head taggerdate ''
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
|
|
|
|
test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head subject 'Initial'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom head subject:sanitize 'Initial'
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom head contents:subject 'Initial'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head body ''
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom head contents:body ''
|
|
|
|
test_atom head contents:signature ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom head contents 'Initial
|
|
|
|
'
|
2013-11-18 18:39:10 +01:00
|
|
|
test_atom head HEAD '*'
|
2008-06-26 10:08:41 +02:00
|
|
|
|
|
|
|
test_atom tag refname refs/tags/testtag
|
2016-01-25 00:08:18 +01:00
|
|
|
test_atom tag refname:short testtag
|
2009-04-07 09:09:39 +02:00
|
|
|
test_atom tag upstream ''
|
2015-05-21 06:45:55 +02:00
|
|
|
test_atom tag push ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag objecttype tag
|
2020-02-22 21:17:32 +01:00
|
|
|
test_atom tag objectsize $((114 + hexlen))
|
|
|
|
test_atom tag objectsize:disk $disklen
|
|
|
|
test_atom tag '*objectsize:disk' $disklen
|
|
|
|
test_atom tag deltabase $ZERO_OID
|
|
|
|
test_atom tag '*deltabase' $ZERO_OID
|
2013-11-18 18:39:09 +01:00
|
|
|
test_atom tag objectname $(git rev-parse refs/tags/testtag)
|
2016-01-25 00:08:18 +01:00
|
|
|
test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
|
2020-12-06 14:15:59 +01:00
|
|
|
test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/main)
|
|
|
|
test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/main)
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag tree ''
|
2020-08-21 23:41:47 +02:00
|
|
|
test_atom tag tree:short ''
|
|
|
|
test_atom tag tree:short=1 ''
|
|
|
|
test_atom tag tree:short=10 ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag parent ''
|
2020-08-21 23:41:48 +02:00
|
|
|
test_atom tag parent:short ''
|
|
|
|
test_atom tag parent:short=1 ''
|
|
|
|
test_atom tag parent:short=10 ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag numparent ''
|
2013-11-18 18:39:09 +01:00
|
|
|
test_atom tag object $(git rev-parse refs/tags/testtag^0)
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag type 'commit'
|
2020-02-22 21:17:32 +01:00
|
|
|
test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{})
|
2013-10-30 07:50:16 +01:00
|
|
|
test_atom tag '*objecttype' 'commit'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag author ''
|
|
|
|
test_atom tag authorname ''
|
|
|
|
test_atom tag authoremail ''
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom tag authoremail:trim ''
|
|
|
|
test_atom tag authoremail:localpart ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag authordate ''
|
|
|
|
test_atom tag committer ''
|
|
|
|
test_atom tag committername ''
|
|
|
|
test_atom tag committeremail ''
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom tag committeremail:trim ''
|
|
|
|
test_atom tag committeremail:localpart ''
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag committerdate ''
|
|
|
|
test_atom tag tag 'testtag'
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag taggername 'C O Mitter'
|
|
|
|
test_atom tag taggeremail '<committer@example.com>'
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom tag taggeremail:trim 'committer@example.com'
|
|
|
|
test_atom tag taggeremail:localpart 'committer'
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
|
|
|
|
test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
|
|
|
|
test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
|
|
|
|
test_atom tag subject 'Tagging at 1151968727'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom tag subject:sanitize 'Tagging-at-1151968727'
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom tag contents:subject 'Tagging at 1151968727'
|
2008-06-26 10:08:41 +02:00
|
|
|
test_atom tag body ''
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom tag contents:body ''
|
|
|
|
test_atom tag contents:signature ''
|
2015-09-03 23:49:00 +02:00
|
|
|
test_atom tag contents 'Tagging at 1151968727
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
2013-11-18 18:39:10 +01:00
|
|
|
test_atom tag HEAD ' '
|
2007-10-02 13:02:57 +02:00
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success 'basic atom: refs/tags/testtag *raw' '
|
|
|
|
git cat-file commit refs/tags/testtag^{} >expected &&
|
|
|
|
git for-each-ref --format="%(*raw)" refs/tags/testtag >actual &&
|
|
|
|
sanitize_pgp <expected >expected.clean &&
|
|
|
|
echo >>expected.clean &&
|
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
test_cmp expected.clean actual.clean
|
|
|
|
'
|
|
|
|
|
2008-02-01 10:50:53 +01:00
|
|
|
test_expect_success 'Check invalid atoms names are errors' '
|
2008-09-03 10:59:29 +02:00
|
|
|
test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Check format specifiers are ignored in naming date atoms' '
|
2008-09-03 10:59:29 +02:00
|
|
|
git for-each-ref --format="%(authordate)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Check valid format specifiers for date fields' '
|
2008-09-03 10:59:29 +02:00
|
|
|
git for-each-ref --format="%(authordate:default)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:relative)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:short)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:local)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
|
|
|
|
git for-each-ref --format="%(authordate:rfc2822)" refs/heads
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2008-02-01 10:50:53 +01:00
|
|
|
test_expect_success 'Check invalid format specifiers are errors' '
|
2008-09-03 10:59:29 +02:00
|
|
|
test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2017-01-10 09:49:37 +01:00
|
|
|
test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
|
|
|
|
test_must_fail git for-each-ref --format="%(objectname:short=0)" &&
|
|
|
|
test_must_fail git for-each-ref --format="%(objectname:short=-1)" &&
|
|
|
|
test_must_fail git for-each-ref --format="%(objectname:short=foo)"
|
|
|
|
'
|
|
|
|
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date () {
|
|
|
|
f=$1 &&
|
|
|
|
committer_date=$2 &&
|
|
|
|
author_date=$3 &&
|
|
|
|
tagger_date=$4 &&
|
|
|
|
cat >expected <<-EOF &&
|
2020-12-06 14:15:59 +01:00
|
|
|
'refs/heads/main' '$committer_date' '$author_date'
|
2015-09-03 23:48:56 +02:00
|
|
|
'refs/tags/testtag' '$tagger_date'
|
|
|
|
EOF
|
|
|
|
(
|
|
|
|
git for-each-ref --shell \
|
|
|
|
--format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
|
|
|
|
refs/heads &&
|
|
|
|
git for-each-ref --shell \
|
|
|
|
--format="%(refname) %(taggerdate${f:+:$f})" \
|
|
|
|
refs/tags
|
|
|
|
) >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
}
|
2007-10-02 13:02:57 +02:00
|
|
|
|
|
|
|
test_expect_success 'Check unformatted date fields output' '
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date "" \
|
2015-09-03 23:49:00 +02:00
|
|
|
"Tue Jul 4 01:18:43 2006 +0200" \
|
|
|
|
"Tue Jul 4 01:18:44 2006 +0200" \
|
|
|
|
"Tue Jul 4 01:18:45 2006 +0200"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Check format "default" formatted date fields output' '
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date default \
|
2015-09-03 23:49:00 +02:00
|
|
|
"Tue Jul 4 01:18:43 2006 +0200" \
|
|
|
|
"Tue Jul 4 01:18:44 2006 +0200" \
|
|
|
|
"Tue Jul 4 01:18:45 2006 +0200"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format "default-local" date fields output' '
|
|
|
|
test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
# Don't know how to do relative check because I can't know when this script
|
|
|
|
# is going to be run and can't fake the current time to git, and hence can't
|
|
|
|
# provide expected output. Instead, I'll just make sure that "relative"
|
|
|
|
# doesn't exit in error
|
|
|
|
test_expect_success 'Check format "relative" date fields output' '
|
|
|
|
f=relative &&
|
|
|
|
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
|
|
|
|
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
|
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
# We just check that this is the same as "relative" for now.
|
|
|
|
test_expect_success 'Check format "relative-local" date fields output' '
|
|
|
|
test_date relative-local \
|
|
|
|
"$(git for-each-ref --format="%(committerdate:relative)" refs/heads)" \
|
|
|
|
"$(git for-each-ref --format="%(authordate:relative)" refs/heads)" \
|
|
|
|
"$(git for-each-ref --format="%(taggerdate:relative)" refs/tags)"
|
|
|
|
'
|
2007-10-02 13:02:57 +02:00
|
|
|
|
|
|
|
test_expect_success 'Check format "short" date fields output' '
|
2015-09-03 23:49:00 +02:00
|
|
|
test_date short 2006-07-04 2006-07-04 2006-07-04
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format "short-local" date fields output' '
|
|
|
|
test_date short-local 2006-07-03 2006-07-03 2006-07-03
|
|
|
|
'
|
2007-10-02 13:02:57 +02:00
|
|
|
|
|
|
|
test_expect_success 'Check format "local" date fields output' '
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date local \
|
2015-09-03 23:49:00 +02:00
|
|
|
"Mon Jul 3 23:18:43 2006" \
|
|
|
|
"Mon Jul 3 23:18:44 2006" \
|
|
|
|
"Mon Jul 3 23:18:45 2006"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Check format "iso8601" date fields output' '
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date iso8601 \
|
2015-09-03 23:49:00 +02:00
|
|
|
"2006-07-04 01:18:43 +0200" \
|
|
|
|
"2006-07-04 01:18:44 +0200" \
|
|
|
|
"2006-07-04 01:18:45 +0200"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format "iso8601-local" date fields output' '
|
|
|
|
test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
|
|
|
|
'
|
2007-10-02 13:02:57 +02:00
|
|
|
|
|
|
|
test_expect_success 'Check format "rfc2822" date fields output' '
|
2015-09-03 23:48:56 +02:00
|
|
|
test_date rfc2822 \
|
2015-09-03 23:49:00 +02:00
|
|
|
"Tue, 4 Jul 2006 01:18:43 +0200" \
|
|
|
|
"Tue, 4 Jul 2006 01:18:44 +0200" \
|
|
|
|
"Tue, 4 Jul 2006 01:18:45 +0200"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format "rfc2822-local" date fields output' '
|
|
|
|
test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
|
|
|
|
'
|
|
|
|
|
2015-09-03 23:48:57 +02:00
|
|
|
test_expect_success 'Check format "raw" date fields output' '
|
2015-09-03 23:49:00 +02:00
|
|
|
test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
|
2015-09-03 23:48:57 +02:00
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format "raw-local" date fields output' '
|
|
|
|
test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
|
2007-10-02 13:02:57 +02:00
|
|
|
'
|
|
|
|
|
2015-06-25 18:55:45 +02:00
|
|
|
test_expect_success 'Check format of strftime date fields' '
|
2015-09-03 23:49:00 +02:00
|
|
|
echo "my date is 2006-07-04" >expected &&
|
2015-06-25 18:55:45 +02:00
|
|
|
git for-each-ref \
|
|
|
|
--format="%(authordate:format:my date is %Y-%m-%d)" \
|
|
|
|
refs/heads >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2015-09-03 23:49:01 +02:00
|
|
|
test_expect_success 'Check format of strftime-local date fields' '
|
|
|
|
echo "my date is 2006-07-03" >expected &&
|
|
|
|
git for-each-ref \
|
|
|
|
--format="%(authordate:format-local:my date is %Y-%m-%d)" \
|
|
|
|
refs/heads >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2015-06-30 15:26:53 +02:00
|
|
|
test_expect_success 'exercise strftime with odd fields' '
|
|
|
|
echo >expected &&
|
|
|
|
git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
|
|
|
|
test_cmp expected actual &&
|
2018-05-13 04:24:13 +02:00
|
|
|
long="long format -- $ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID$ZERO_OID" &&
|
2015-06-30 15:26:53 +02:00
|
|
|
echo $long >expected &&
|
|
|
|
git for-each-ref --format="%(authordate:format:$long)" refs/heads >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2007-11-10 17:47:54 +01:00
|
|
|
cat >expected <<\EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
refs/heads/main
|
|
|
|
refs/remotes/origin/main
|
2007-11-10 17:47:54 +01:00
|
|
|
refs/tags/testtag
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Verify ascending sort' '
|
2008-09-03 10:59:29 +02:00
|
|
|
git for-each-ref --format="%(refname)" --sort=refname >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
2007-11-10 17:47:54 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
|
|
|
|
cat >expected <<\EOF
|
|
|
|
refs/tags/testtag
|
2020-12-06 14:15:59 +01:00
|
|
|
refs/remotes/origin/main
|
|
|
|
refs/heads/main
|
2007-11-10 17:47:54 +01:00
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Verify descending sort' '
|
2008-09-03 10:59:29 +02:00
|
|
|
git for-each-ref --format="%(refname)" --sort=-refname >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
ref-filter.c: find disjoint pattern prefixes
Since cfe004a5a9 (ref-filter: limit traversal to prefix, 2017-05-22),
the ref-filter code has sought to limit the traversals to a prefix of
the given patterns.
That code stopped short of handling more than one pattern, because it
means invoking 'for_each_ref_in' multiple times. If we're not careful
about which patterns overlap, we will output the same refs multiple
times.
For instance, consider the set of patterns 'refs/heads/a/*',
'refs/heads/a/b/c', and 'refs/tags/v1.0.0'. If we naïvely ran:
for_each_ref_in("refs/heads/a/*", ...);
for_each_ref_in("refs/heads/a/b/c", ...);
for_each_ref_in("refs/tags/v1.0.0", ...);
we would see 'refs/heads/a/b/c' (and everything underneath it) twice.
Instead, we want to partition the patterns into disjoint sets, where we
know that no ref will be matched by any two patterns in different sets.
In the above, these are:
- {'refs/heads/a/*', 'refs/heads/a/b/c'}, and
- {'refs/tags/v1.0.0'}
Given one of these disjoint sets, what is a suitable pattern to pass to
'for_each_ref_in'? One approach is to compute the longest common prefix
over all elements in that disjoint set, and let the caller cull out the
refs they didn't want. Computing the longest prefix means that in most
cases, we won't match too many things the caller would like to ignore.
The longest common prefixes of the above are:
- {'refs/heads/a/*', 'refs/heads/a/b/c'} -> refs/heads/a/*
- {'refs/tags/v1.0.0'} -> refs/tags/v1.0.0
We instead invoke:
for_each_ref_in("refs/heads/a/*", ...);
for_each_ref_in("refs/tags/v1.0.0", ...);
Which provides us with the refs we were looking for with a minimal
amount of extra cruft, but never a duplicate of the ref we asked for.
Implemented here is an algorithm which accomplishes the above, which
works as follows:
1. Lexicographically sort the given list of patterns.
2. Initialize 'prefix' to the empty string, where our goal is to
build each element in the above set of longest common prefixes.
3. Consider each pattern in the given set, and emit 'prefix' if it
reaches the end of a pattern, or touches a wildcard character. The
end of a string is treated as if it precedes a wildcard. (Note that
there is some room for future work to detect that, e.g., 'a?b' and
'abc' are disjoint).
4. Otherwise, recurse on step (3) with the slice of the list
corresponding to our current prefix (i.e., the subset of patterns
that have our prefix as a literal string prefix.)
This algorithm is 'O(kn + n log(n))', where 'k' is max(len(pattern)) for
each pattern in the list, and 'n' is len(patterns).
By discovering this set of interesting patterns, we reduce the runtime
of multi-pattern 'git for-each-ref' (and other ref traversals) from
O(N) to O(n log(N)), where 'N' is the total number of packed references.
Running 'git for-each-ref refs/tags/a refs/tags/b' on a repository with
10,000,000 refs in 'refs/tags/huge-N', my best-of-five times drop from:
real 0m5.805s
user 0m5.188s
sys 0m0.468s
to:
real 0m0.001s
user 0m0.000s
sys 0m0.000s
On linux.git, the times to dig out two of the latest -rc tags drops from
0.002s to 0.001s, so the change on repositories with fewer tags is much
less noticeable.
Co-authored-by: Jeff King <peff@peff.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-06-27 00:41:48 +02:00
|
|
|
'
|
|
|
|
|
for-each-ref: delay parsing of --sort=<atom> options
The for-each-ref family of commands invoke parsers immediately when
it sees each --sort=<atom> option, and die before even seeing the
other options on the command line when the <atom> is unrecognised.
Instead, accumulate them in a string list, and have them parsed into
a ref_sorting structure after the command line parsing is done. As
a consequence, "git branch --sort=bogus -h" used to fail to give the
brief help, which arguably may have been a feature, now does so,
which is more consistent with how other options work.
The patch is smaller than the actual extent of the "damage" to the
codebase, thanks to the fact that the original code consistently
used OPT_REF_SORT() macro to handle command line options. We only
needed to replace the variable used for the list, and implementation
of the callback function used in the macro.
The old rule was for the users of the API to:
- Declare ref_sorting and ref_sorting_tail variables;
- OPT_REF_SORT() macro will instantiate ref_sorting instance (which
may barf and die) and append it to the tail;
- Append to the tail each ref_sorting read from the configuration
by parsing in the config callback (which may barf and die);
- See if ref_sorting is null and use ref_sorting_default() instead.
Now the rule is not all that different but is simpler:
- Declare ref_sorting_options string list.
- OPT_REF_SORT() macro will append it to the string list;
- Append to the string list the sort key read from the
configuration;
- call ref_sorting_options() to turn the string list to ref_sorting
structure (which also deals with the default value).
As side effects, this change also cleans up a few issues:
- 95be717c (parse_opt_ref_sorting: always use with NONEG flag,
2019-03-20) muses that "git for-each-ref --no-sort" should simply
clear the sort keys accumulated so far; it now does.
- The implementation detail of "struct ref_sorting" and the helper
function parse_ref_sorting() can now be private to the ref-filter
API implementation.
- If you set branch.sort to a bogus value, the any "git branch"
invocation, not only the listing mode, would abort with the
original code; now it doesn't
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-10-20 21:23:53 +02:00
|
|
|
test_expect_success 'Give help even with invalid sort atoms' '
|
|
|
|
test_expect_code 129 git for-each-ref --sort=bogus -h >actual 2>&1 &&
|
|
|
|
grep "^usage: git for-each-ref" actual
|
|
|
|
'
|
|
|
|
|
ref-filter.c: find disjoint pattern prefixes
Since cfe004a5a9 (ref-filter: limit traversal to prefix, 2017-05-22),
the ref-filter code has sought to limit the traversals to a prefix of
the given patterns.
That code stopped short of handling more than one pattern, because it
means invoking 'for_each_ref_in' multiple times. If we're not careful
about which patterns overlap, we will output the same refs multiple
times.
For instance, consider the set of patterns 'refs/heads/a/*',
'refs/heads/a/b/c', and 'refs/tags/v1.0.0'. If we naïvely ran:
for_each_ref_in("refs/heads/a/*", ...);
for_each_ref_in("refs/heads/a/b/c", ...);
for_each_ref_in("refs/tags/v1.0.0", ...);
we would see 'refs/heads/a/b/c' (and everything underneath it) twice.
Instead, we want to partition the patterns into disjoint sets, where we
know that no ref will be matched by any two patterns in different sets.
In the above, these are:
- {'refs/heads/a/*', 'refs/heads/a/b/c'}, and
- {'refs/tags/v1.0.0'}
Given one of these disjoint sets, what is a suitable pattern to pass to
'for_each_ref_in'? One approach is to compute the longest common prefix
over all elements in that disjoint set, and let the caller cull out the
refs they didn't want. Computing the longest prefix means that in most
cases, we won't match too many things the caller would like to ignore.
The longest common prefixes of the above are:
- {'refs/heads/a/*', 'refs/heads/a/b/c'} -> refs/heads/a/*
- {'refs/tags/v1.0.0'} -> refs/tags/v1.0.0
We instead invoke:
for_each_ref_in("refs/heads/a/*", ...);
for_each_ref_in("refs/tags/v1.0.0", ...);
Which provides us with the refs we were looking for with a minimal
amount of extra cruft, but never a duplicate of the ref we asked for.
Implemented here is an algorithm which accomplishes the above, which
works as follows:
1. Lexicographically sort the given list of patterns.
2. Initialize 'prefix' to the empty string, where our goal is to
build each element in the above set of longest common prefixes.
3. Consider each pattern in the given set, and emit 'prefix' if it
reaches the end of a pattern, or touches a wildcard character. The
end of a string is treated as if it precedes a wildcard. (Note that
there is some room for future work to detect that, e.g., 'a?b' and
'abc' are disjoint).
4. Otherwise, recurse on step (3) with the slice of the list
corresponding to our current prefix (i.e., the subset of patterns
that have our prefix as a literal string prefix.)
This algorithm is 'O(kn + n log(n))', where 'k' is max(len(pattern)) for
each pattern in the list, and 'n' is len(patterns).
By discovering this set of interesting patterns, we reduce the runtime
of multi-pattern 'git for-each-ref' (and other ref traversals) from
O(N) to O(n log(N)), where 'N' is the total number of packed references.
Running 'git for-each-ref refs/tags/a refs/tags/b' on a repository with
10,000,000 refs in 'refs/tags/huge-N', my best-of-five times drop from:
real 0m5.805s
user 0m5.188s
sys 0m0.468s
to:
real 0m0.001s
user 0m0.000s
sys 0m0.000s
On linux.git, the times to dig out two of the latest -rc tags drops from
0.002s to 0.001s, so the change on repositories with fewer tags is much
less noticeable.
Co-authored-by: Jeff King <peff@peff.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-06-27 00:41:48 +02:00
|
|
|
cat >expected <<\EOF
|
|
|
|
refs/tags/testtag
|
|
|
|
refs/tags/testtag-2
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'exercise patterns with prefixes' '
|
|
|
|
git tag testtag-2 &&
|
|
|
|
test_when_finished "git tag -d testtag-2" &&
|
|
|
|
git for-each-ref --format="%(refname)" \
|
|
|
|
refs/tags/testtag refs/tags/testtag-2 >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<\EOF
|
|
|
|
refs/tags/testtag
|
|
|
|
refs/tags/testtag-2
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'exercise glob patterns with prefixes' '
|
|
|
|
git tag testtag-2 &&
|
|
|
|
test_when_finished "git tag -d testtag-2" &&
|
|
|
|
git for-each-ref --format="%(refname)" \
|
|
|
|
refs/tags/testtag "refs/tags/testtag-*" >actual &&
|
|
|
|
test_cmp expected actual
|
2007-11-10 17:47:54 +01:00
|
|
|
'
|
|
|
|
|
2007-12-06 13:24:39 +01:00
|
|
|
cat >expected <<\EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
'refs/heads/main'
|
|
|
|
'refs/remotes/origin/main'
|
2007-12-06 13:24:39 +01:00
|
|
|
'refs/tags/testtag'
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Quoting style: shell' '
|
|
|
|
git for-each-ref --shell --format="%(refname)" >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
2007-12-06 13:24:39 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Quoting style: perl' '
|
|
|
|
git for-each-ref --perl --format="%(refname)" >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
2007-12-06 13:24:39 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Quoting style: python' '
|
|
|
|
git for-each-ref --python --format="%(refname)" >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
2007-12-06 13:24:39 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<\EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
"refs/heads/main"
|
|
|
|
"refs/remotes/origin/main"
|
2007-12-06 13:24:39 +01:00
|
|
|
"refs/tags/testtag"
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Quoting style: tcl' '
|
|
|
|
git for-each-ref --tcl --format="%(refname)" >actual &&
|
2008-05-24 07:28:56 +02:00
|
|
|
test_cmp expected actual
|
2007-12-06 13:24:39 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
|
|
|
|
test_expect_success "more than one quoting style: $i" "
|
2018-02-13 01:36:01 +01:00
|
|
|
test_must_fail git for-each-ref $i 2>err &&
|
|
|
|
grep '^error: more than one quoting style' err
|
2007-12-06 13:24:39 +01:00
|
|
|
"
|
|
|
|
done
|
2007-11-10 17:47:54 +01:00
|
|
|
|
2013-11-18 18:39:11 +01:00
|
|
|
test_expect_success 'setup for upstream:track[short]' '
|
|
|
|
test_commit two
|
|
|
|
'
|
|
|
|
|
2016-01-25 00:08:18 +01:00
|
|
|
test_atom head upstream:track '[ahead 1]'
|
|
|
|
test_atom head upstream:trackshort '>'
|
2017-01-10 09:49:41 +01:00
|
|
|
test_atom head upstream:track,nobracket 'ahead 1'
|
|
|
|
test_atom head upstream:nobracket,track 'ahead 1'
|
2019-04-16 14:16:46 +02:00
|
|
|
|
|
|
|
test_expect_success 'setup for push:track[short]' '
|
|
|
|
test_commit third &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git update-ref refs/remotes/myfork/main main &&
|
|
|
|
git reset main~1
|
2019-04-16 14:16:46 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_atom head push:track '[behind 1]'
|
|
|
|
test_atom head push:trackshort '<'
|
2013-11-18 18:39:11 +01:00
|
|
|
|
|
|
|
test_expect_success 'Check that :track[short] cannot be used with other atoms' '
|
|
|
|
test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
|
|
|
|
test_must_fail git for-each-ref --format="%(refname:trackshort)" 2>/dev/null
|
|
|
|
'
|
|
|
|
|
2015-01-05 10:58:55 +01:00
|
|
|
test_expect_success 'Check that :track[short] works when upstream is invalid' '
|
|
|
|
cat >expected <<-\EOF &&
|
2017-01-10 09:49:40 +01:00
|
|
|
[gone]
|
2015-01-05 10:58:55 +01:00
|
|
|
|
|
|
|
EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
test_when_finished "git config branch.main.merge refs/heads/main" &&
|
|
|
|
git config branch.main.merge refs/heads/does-not-exist &&
|
2015-01-05 10:58:55 +01:00
|
|
|
git for-each-ref \
|
|
|
|
--format="%(upstream:track)$LF%(upstream:trackshort)" \
|
|
|
|
refs/heads >actual &&
|
|
|
|
test_cmp expected actual
|
2015-05-21 06:45:55 +02:00
|
|
|
'
|
|
|
|
|
2008-09-05 23:16:23 +02:00
|
|
|
test_expect_success 'Check for invalid refname format' '
|
|
|
|
test_must_fail git for-each-ref --format="%(refname:INVALID)"
|
|
|
|
'
|
|
|
|
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
test_expect_success 'set up color tests' '
|
|
|
|
cat >expected.color <<-EOF &&
|
2020-12-06 14:15:59 +01:00
|
|
|
$(git rev-parse --short refs/heads/main) <GREEN>main<RESET>
|
|
|
|
$(git rev-parse --short refs/remotes/myfork/main) <GREEN>myfork/main<RESET>
|
|
|
|
$(git rev-parse --short refs/remotes/origin/main) <GREEN>origin/main<RESET>
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
$(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET>
|
2019-04-16 14:16:46 +02:00
|
|
|
$(git rev-parse --short refs/tags/third) <GREEN>third<RESET>
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
$(git rev-parse --short refs/tags/two) <GREEN>two<RESET>
|
|
|
|
EOF
|
|
|
|
sed "s/<[^>]*>//g" <expected.color >expected.bare &&
|
|
|
|
color_format="%(objectname:short) %(color:green)%(refname:short)"
|
|
|
|
'
|
2013-11-18 18:39:12 +01:00
|
|
|
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
test_expect_success TTY '%(color) shows color with a tty' '
|
2017-10-03 15:39:34 +02:00
|
|
|
test_terminal git for-each-ref --format="$color_format" >actual.raw &&
|
2017-07-13 16:58:41 +02:00
|
|
|
test_decode_color <actual.raw >actual &&
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
test_cmp expected.color actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(color) does not show color without tty' '
|
|
|
|
TERM=vt100 git for-each-ref --format="$color_format" >actual &&
|
|
|
|
test_cmp expected.bare actual
|
|
|
|
'
|
|
|
|
|
2017-10-03 15:45:47 +02:00
|
|
|
test_expect_success '--color can override tty check' '
|
|
|
|
git for-each-ref --color --format="$color_format" >actual.raw &&
|
ref-filter: consult want_color() before emitting colors
When color placeholders like %(color:red) are used in a
ref-filter format, we unconditionally output the colors,
even if the user has asked us for no colors. This usually
isn't a problem when the user is constructing a --format on
the command line, but it means we may do the wrong thing
when the format is fed from a script or alias. For example:
$ git config alias.b 'branch --format=%(color:green)%(refname)'
$ git b --no-color
should probably omit the green color. Likewise, running:
$ git b >branches
should probably also omit the color, just as we would for
all baked-in coloring (and as we recently started to do for
user-specified colors in --pretty formats).
This commit makes both of those cases work by teaching
the ref-filter code to consult want_color() before
outputting any color. The color flag in ref_format defaults
to "-1", which means we'll consult color.ui, which in turn
defaults to the usual isatty() check on stdout. However,
callers like git-branch which support their own color config
(and command-line options) can override that.
The new tests independently cover all three of the callers
of ref-filter (for-each-ref, tag, and branch). Even though
these seem redundant, it confirms that we've correctly
plumbed through all of the necessary config to make colors
work by default.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-13 17:09:32 +02:00
|
|
|
test_decode_color <actual.raw >actual &&
|
|
|
|
test_cmp expected.color actual
|
2013-11-18 18:39:12 +01:00
|
|
|
'
|
|
|
|
|
tag: respect color.ui config
Since 11b087adfd (ref-filter: consult want_color() before
emitting colors, 2017-07-13), we expect that setting
"color.ui" to "always" will enable color tag formats even
without a tty. As that commit was built on top of
136c8c8b8f (color: check color.ui in git_default_config(),
2017-07-13) from the same series, we didn't need to touch
tag's config parsing at all.
However, since we reverted 136c8c8b8f, we now need to
explicitly call git_color_default_config() to make this
work.
Let's do so, and also restore the test dropped in 0c88bf5050
(provide --color option for all ref-filter users,
2017-10-03). That commit swapped out our "color.ui=always"
test for "--color" in preparation for "always" going away.
But since it is here to stay, we should test both cases.
Note that for-each-ref also lost its color.ui support as
part of reverting 136c8c8b8f. But as a plumbing command, it
should _not_ respect the color.ui config. Since it also
gained a --color option in 0c88bf5050, that's the correct
way to ask it for color. We'll continue to test that, and
confirm that "color.ui" is not respected.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-10-13 19:26:02 +02:00
|
|
|
test_expect_success 'color.ui=always does not override tty check' '
|
|
|
|
git -c color.ui=always for-each-ref --format="$color_format" >actual &&
|
|
|
|
test_cmp expected.bare actual
|
|
|
|
'
|
|
|
|
|
2008-09-05 23:16:23 +02:00
|
|
|
cat >expected <<\EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
heads/main
|
|
|
|
tags/main
|
2008-09-05 23:16:23 +02:00
|
|
|
EOF
|
|
|
|
|
2009-04-13 12:25:47 +02:00
|
|
|
test_expect_success 'Check ambiguous head and tag refs (strict)' '
|
|
|
|
git config --bool core.warnambiguousrefs true &&
|
2008-09-05 23:16:23 +02:00
|
|
|
git checkout -b newtag &&
|
|
|
|
echo "Using $datestamp" > one &&
|
|
|
|
git add one &&
|
|
|
|
git commit -m "Branch" &&
|
|
|
|
setdate_and_increment &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git tag -m "Tagging at $datestamp" main &&
|
|
|
|
git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
|
2008-09-05 23:16:23 +02:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2009-04-13 12:25:47 +02:00
|
|
|
cat >expected <<\EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
heads/main
|
|
|
|
main
|
2009-04-13 12:25:47 +02:00
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Check ambiguous head and tag refs (loose)' '
|
|
|
|
git config --bool core.warnambiguousrefs false &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git for-each-ref --format "%(refname:short)" refs/heads/main refs/tags/main >actual &&
|
2009-04-13 12:25:47 +02:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2008-09-05 23:16:23 +02:00
|
|
|
cat >expected <<\EOF
|
|
|
|
heads/ambiguous
|
|
|
|
ambiguous
|
|
|
|
EOF
|
|
|
|
|
2009-04-13 12:25:47 +02:00
|
|
|
test_expect_success 'Check ambiguous head and tag refs II (loose)' '
|
2020-12-06 14:15:59 +01:00
|
|
|
git checkout main &&
|
2008-09-05 23:16:23 +02:00
|
|
|
git tag ambiguous testtag^0 &&
|
|
|
|
git branch ambiguous testtag^0 &&
|
|
|
|
git for-each-ref --format "%(refname:short)" refs/heads/ambiguous refs/tags/ambiguous >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2019-08-17 23:51:07 +02:00
|
|
|
test_expect_success 'create tag without tagger' '
|
|
|
|
git tag -a -m "Broken tag" taggerless &&
|
|
|
|
git tag -f taggerless $(git cat-file tag taggerless |
|
|
|
|
sed -e "/^tagger /d" |
|
|
|
|
git hash-object --stdin -w -t tag)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_atom refs/tags/taggerless type 'commit'
|
|
|
|
test_atom refs/tags/taggerless tag 'taggerless'
|
|
|
|
test_atom refs/tags/taggerless tagger ''
|
|
|
|
test_atom refs/tags/taggerless taggername ''
|
|
|
|
test_atom refs/tags/taggerless taggeremail ''
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom refs/tags/taggerless taggeremail:trim ''
|
|
|
|
test_atom refs/tags/taggerless taggeremail:localpart ''
|
2019-08-17 23:51:07 +02:00
|
|
|
test_atom refs/tags/taggerless taggerdate ''
|
|
|
|
test_atom refs/tags/taggerless committer ''
|
|
|
|
test_atom refs/tags/taggerless committername ''
|
|
|
|
test_atom refs/tags/taggerless committeremail ''
|
2020-08-21 23:41:43 +02:00
|
|
|
test_atom refs/tags/taggerless committeremail:trim ''
|
|
|
|
test_atom refs/tags/taggerless committeremail:localpart ''
|
2019-08-17 23:51:07 +02:00
|
|
|
test_atom refs/tags/taggerless committerdate ''
|
|
|
|
test_atom refs/tags/taggerless subject 'Broken tag'
|
|
|
|
|
2008-08-20 21:29:27 +02:00
|
|
|
test_expect_success 'an unusual tag with an incomplete line' '
|
|
|
|
|
|
|
|
git tag -m "bogo" bogo &&
|
|
|
|
bogo=$(git cat-file tag bogo) &&
|
|
|
|
bogo=$(printf "%s" "$bogo" | git mktag) &&
|
|
|
|
git tag -f bogo "$bogo" &&
|
|
|
|
git for-each-ref --format "%(body)" refs/tags/bogo
|
|
|
|
|
|
|
|
'
|
|
|
|
|
2011-09-07 19:43:28 +02:00
|
|
|
test_expect_success 'create tag with subject and body content' '
|
|
|
|
cat >>msg <<-\EOF &&
|
|
|
|
the subject line
|
|
|
|
|
|
|
|
first body line
|
|
|
|
second body line
|
|
|
|
EOF
|
|
|
|
git tag -F msg subject-body
|
|
|
|
'
|
|
|
|
test_atom refs/tags/subject-body subject 'the subject line'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom refs/tags/subject-body subject:sanitize 'the-subject-line'
|
2011-09-07 19:43:28 +02:00
|
|
|
test_atom refs/tags/subject-body body 'first body line
|
|
|
|
second body line
|
|
|
|
'
|
|
|
|
test_atom refs/tags/subject-body contents 'the subject line
|
|
|
|
|
|
|
|
first body line
|
|
|
|
second body line
|
|
|
|
'
|
|
|
|
|
2011-09-07 19:44:56 +02:00
|
|
|
test_expect_success 'create tag with multiline subject' '
|
|
|
|
cat >msg <<-\EOF &&
|
|
|
|
first subject line
|
|
|
|
second subject line
|
|
|
|
|
|
|
|
first body line
|
|
|
|
second body line
|
|
|
|
EOF
|
|
|
|
git tag -F msg multiline
|
|
|
|
'
|
|
|
|
test_atom refs/tags/multiline subject 'first subject line second subject line'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom refs/tags/multiline subject:sanitize 'first-subject-line-second-subject-line'
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/multiline contents:subject 'first subject line second subject line'
|
2011-09-07 19:44:56 +02:00
|
|
|
test_atom refs/tags/multiline body 'first body line
|
|
|
|
second body line
|
|
|
|
'
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/multiline contents:body 'first body line
|
|
|
|
second body line
|
|
|
|
'
|
|
|
|
test_atom refs/tags/multiline contents:signature ''
|
2011-09-07 19:44:56 +02:00
|
|
|
test_atom refs/tags/multiline contents 'first subject line
|
|
|
|
second subject line
|
|
|
|
|
|
|
|
first body line
|
|
|
|
second body line
|
|
|
|
'
|
|
|
|
|
2011-09-07 19:46:08 +02:00
|
|
|
test_expect_success GPG 'create signed tags' '
|
|
|
|
git tag -s -m "" signed-empty &&
|
|
|
|
git tag -s -m "subject line" signed-short &&
|
|
|
|
cat >msg <<-\EOF &&
|
|
|
|
subject line
|
|
|
|
|
|
|
|
body contents
|
|
|
|
EOF
|
|
|
|
git tag -s -F msg signed-long
|
|
|
|
'
|
|
|
|
|
|
|
|
sig='-----BEGIN PGP SIGNATURE-----
|
|
|
|
-----END PGP SIGNATURE-----
|
|
|
|
'
|
|
|
|
|
|
|
|
PREREQ=GPG
|
|
|
|
test_atom refs/tags/signed-empty subject ''
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom refs/tags/signed-empty subject:sanitize ''
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/signed-empty contents:subject ''
|
|
|
|
test_atom refs/tags/signed-empty body "$sig"
|
|
|
|
test_atom refs/tags/signed-empty contents:body ''
|
|
|
|
test_atom refs/tags/signed-empty contents:signature "$sig"
|
|
|
|
test_atom refs/tags/signed-empty contents "$sig"
|
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
|
|
|
|
git cat-file tag refs/tags/signed-empty >expected &&
|
|
|
|
git for-each-ref --format="%(raw)" refs/tags/signed-empty >actual &&
|
|
|
|
sanitize_pgp <expected >expected.clean &&
|
|
|
|
echo >>expected.clean &&
|
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
test_cmp expected.clean actual.clean
|
|
|
|
'
|
|
|
|
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/signed-short subject 'subject line'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom refs/tags/signed-short subject:sanitize 'subject-line'
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/signed-short contents:subject 'subject line'
|
|
|
|
test_atom refs/tags/signed-short body "$sig"
|
|
|
|
test_atom refs/tags/signed-short contents:body ''
|
|
|
|
test_atom refs/tags/signed-short contents:signature "$sig"
|
|
|
|
test_atom refs/tags/signed-short contents "subject line
|
|
|
|
$sig"
|
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
|
|
|
|
git cat-file tag refs/tags/signed-short >expected &&
|
|
|
|
git for-each-ref --format="%(raw)" refs/tags/signed-short >actual &&
|
|
|
|
sanitize_pgp <expected >expected.clean &&
|
|
|
|
echo >>expected.clean &&
|
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
test_cmp expected.clean actual.clean
|
|
|
|
'
|
|
|
|
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/signed-long subject 'subject line'
|
2020-08-21 23:41:50 +02:00
|
|
|
test_atom refs/tags/signed-long subject:sanitize 'subject-line'
|
2011-09-07 19:46:08 +02:00
|
|
|
test_atom refs/tags/signed-long contents:subject 'subject line'
|
|
|
|
test_atom refs/tags/signed-long body "body contents
|
|
|
|
$sig"
|
|
|
|
test_atom refs/tags/signed-long contents:body 'body contents
|
|
|
|
'
|
|
|
|
test_atom refs/tags/signed-long contents:signature "$sig"
|
|
|
|
test_atom refs/tags/signed-long contents "subject line
|
|
|
|
|
|
|
|
body contents
|
|
|
|
$sig"
|
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
|
|
|
|
git cat-file tag refs/tags/signed-long >expected &&
|
|
|
|
git for-each-ref --format="%(raw)" refs/tags/signed-long >actual &&
|
|
|
|
sanitize_pgp <expected >expected.clean &&
|
|
|
|
echo >>expected.clean &&
|
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
test_cmp expected.clean actual.clean
|
|
|
|
'
|
|
|
|
|
2020-07-10 18:47:38 +02:00
|
|
|
test_expect_success 'set up refs pointing to tree and blob' '
|
2020-12-06 14:15:59 +01:00
|
|
|
git update-ref refs/mytrees/first refs/heads/main^{tree} &&
|
|
|
|
git update-ref refs/myblobs/first refs/heads/main:one
|
2020-07-10 18:47:38 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_atom refs/mytrees/first subject ""
|
|
|
|
test_atom refs/mytrees/first contents:subject ""
|
|
|
|
test_atom refs/mytrees/first body ""
|
|
|
|
test_atom refs/mytrees/first contents:body ""
|
|
|
|
test_atom refs/mytrees/first contents:signature ""
|
|
|
|
test_atom refs/mytrees/first contents ""
|
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success 'basic atom: refs/mytrees/first raw' '
|
|
|
|
git cat-file tree refs/mytrees/first >expected &&
|
|
|
|
echo >>expected &&
|
|
|
|
git for-each-ref --format="%(raw)" refs/mytrees/first >actual &&
|
|
|
|
test_cmp expected actual &&
|
|
|
|
git cat-file -s refs/mytrees/first >expected &&
|
|
|
|
git for-each-ref --format="%(raw:size)" refs/mytrees/first >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2020-07-10 18:47:38 +02:00
|
|
|
test_atom refs/myblobs/first subject ""
|
|
|
|
test_atom refs/myblobs/first contents:subject ""
|
|
|
|
test_atom refs/myblobs/first body ""
|
|
|
|
test_atom refs/myblobs/first contents:body ""
|
|
|
|
test_atom refs/myblobs/first contents:signature ""
|
|
|
|
test_atom refs/myblobs/first contents ""
|
|
|
|
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
test_expect_success 'basic atom: refs/myblobs/first raw' '
|
|
|
|
git cat-file blob refs/myblobs/first >expected &&
|
|
|
|
echo >>expected &&
|
|
|
|
git for-each-ref --format="%(raw)" refs/myblobs/first >actual &&
|
|
|
|
test_cmp expected actual &&
|
|
|
|
git cat-file -s refs/myblobs/first >expected &&
|
|
|
|
git for-each-ref --format="%(raw:size)" refs/myblobs/first >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'set up refs pointing to binary blob' '
|
|
|
|
printf "a\0b\0c" >blob1 &&
|
|
|
|
printf "a\0c\0b" >blob2 &&
|
|
|
|
printf "\0a\0b\0c" >blob3 &&
|
|
|
|
printf "abc" >blob4 &&
|
|
|
|
printf "\0 \0 \0 " >blob5 &&
|
|
|
|
printf "\0 \0a\0 " >blob6 &&
|
|
|
|
printf " " >blob7 &&
|
|
|
|
>blob8 &&
|
|
|
|
obj=$(git hash-object -w blob1) &&
|
|
|
|
git update-ref refs/myblobs/blob1 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob2) &&
|
|
|
|
git update-ref refs/myblobs/blob2 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob3) &&
|
|
|
|
git update-ref refs/myblobs/blob3 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob4) &&
|
|
|
|
git update-ref refs/myblobs/blob4 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob5) &&
|
|
|
|
git update-ref refs/myblobs/blob5 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob6) &&
|
|
|
|
git update-ref refs/myblobs/blob6 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob7) &&
|
|
|
|
git update-ref refs/myblobs/blob7 "$obj" &&
|
|
|
|
obj=$(git hash-object -w blob8) &&
|
|
|
|
git update-ref refs/myblobs/blob8 "$obj"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Verify sorts with raw' '
|
|
|
|
cat >expected <<-EOF &&
|
|
|
|
refs/myblobs/blob8
|
|
|
|
refs/myblobs/blob5
|
|
|
|
refs/myblobs/blob6
|
|
|
|
refs/myblobs/blob3
|
|
|
|
refs/myblobs/blob7
|
|
|
|
refs/mytrees/first
|
|
|
|
refs/myblobs/first
|
|
|
|
refs/myblobs/blob1
|
|
|
|
refs/myblobs/blob2
|
|
|
|
refs/myblobs/blob4
|
|
|
|
refs/heads/main
|
|
|
|
EOF
|
|
|
|
git for-each-ref --format="%(refname)" --sort=raw \
|
|
|
|
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'Verify sorts with raw:size' '
|
|
|
|
cat >expected <<-EOF &&
|
|
|
|
refs/myblobs/blob8
|
|
|
|
refs/myblobs/first
|
|
|
|
refs/myblobs/blob7
|
|
|
|
refs/heads/main
|
|
|
|
refs/myblobs/blob4
|
|
|
|
refs/myblobs/blob1
|
|
|
|
refs/myblobs/blob2
|
|
|
|
refs/myblobs/blob3
|
|
|
|
refs/myblobs/blob5
|
|
|
|
refs/myblobs/blob6
|
|
|
|
refs/mytrees/first
|
|
|
|
EOF
|
|
|
|
git for-each-ref --format="%(refname)" --sort=raw:size \
|
|
|
|
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'validate raw atom with %(if:equals)' '
|
|
|
|
cat >expected <<-EOF &&
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
refs/myblobs/blob4
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
not equals
|
|
|
|
EOF
|
|
|
|
git for-each-ref --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
|
|
|
|
refs/myblobs/ refs/heads/ >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'validate raw atom with %(if:notequals)' '
|
|
|
|
cat >expected <<-EOF &&
|
|
|
|
refs/heads/ambiguous
|
|
|
|
refs/heads/main
|
|
|
|
refs/heads/newtag
|
|
|
|
refs/myblobs/blob1
|
|
|
|
refs/myblobs/blob2
|
|
|
|
refs/myblobs/blob3
|
|
|
|
equals
|
|
|
|
refs/myblobs/blob5
|
|
|
|
refs/myblobs/blob6
|
|
|
|
refs/myblobs/blob7
|
|
|
|
refs/myblobs/blob8
|
|
|
|
refs/myblobs/first
|
|
|
|
EOF
|
|
|
|
git for-each-ref --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
|
|
|
|
refs/myblobs/ refs/heads/ >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'empty raw refs with %(if)' '
|
|
|
|
cat >expected <<-EOF &&
|
|
|
|
refs/myblobs/blob1 not empty
|
|
|
|
refs/myblobs/blob2 not empty
|
|
|
|
refs/myblobs/blob3 not empty
|
|
|
|
refs/myblobs/blob4 not empty
|
|
|
|
refs/myblobs/blob5 not empty
|
|
|
|
refs/myblobs/blob6 not empty
|
|
|
|
refs/myblobs/blob7 empty
|
|
|
|
refs/myblobs/blob8 empty
|
|
|
|
refs/myblobs/first not empty
|
|
|
|
EOF
|
|
|
|
git for-each-ref --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
|
|
|
|
refs/myblobs/ >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(raw) with --python must fail' '
|
|
|
|
test_must_fail git for-each-ref --format="%(raw)" --python
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(raw) with --tcl must fail' '
|
|
|
|
test_must_fail git for-each-ref --format="%(raw)" --tcl
|
|
|
|
'
|
|
|
|
|
2021-07-26 05:26:48 +02:00
|
|
|
test_expect_success '%(raw) with --perl' '
|
|
|
|
git for-each-ref --format="\$name= %(raw);
|
|
|
|
print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
|
|
|
|
cmp blob1 actual &&
|
|
|
|
git for-each-ref --format="\$name= %(raw);
|
|
|
|
print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
|
|
|
|
cmp blob3 actual &&
|
|
|
|
git for-each-ref --format="\$name= %(raw);
|
|
|
|
print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
|
|
|
|
cmp blob8 actual &&
|
|
|
|
git for-each-ref --format="\$name= %(raw);
|
|
|
|
print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
|
|
|
|
cmp one actual &&
|
|
|
|
git cat-file tree refs/mytrees/first > expected &&
|
|
|
|
git for-each-ref --format="\$name= %(raw);
|
|
|
|
print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
|
|
|
|
cmp expected actual
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(raw) with --shell must fail' '
|
|
|
|
test_must_fail git for-each-ref --format="%(raw)" --shell
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(raw) with --shell and --sort=raw must fail' '
|
|
|
|
test_must_fail git for-each-ref --format="%(raw)" --sort=raw --shell
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '%(raw:size) with --shell' '
|
2021-12-09 06:11:02 +01:00
|
|
|
git for-each-ref --format="%(raw:size)" | sed "s/^/$SQ/;s/$/$SQ/" >expect &&
|
ref-filter: add %(raw) atom
Add new formatting option `%(raw)`, which will print the raw
object data without any changes. It will help further to migrate
all cat-file formatting logic from cat-file to ref-filter.
The raw data of blob, tree objects may contain '\0', but most of
the logic in `ref-filter` depends on the output of the atom being
text (specifically, no embedded NULs in it).
E.g. `quote_formatting()` use `strbuf_addstr()` or `*._quote_buf()`
add the data to the buffer. The raw data of a tree object is
`100644 one\0...`, only the `100644 one` will be added to the buffer,
which is incorrect.
Therefore, we need to find a way to record the length of the
atom_value's member `s`. Although strbuf can already record the
string and its length, if we want to replace the type of atom_value's
member `s` with strbuf, many places in ref-filter that are filled
with dynamically allocated mermory in `v->s` are not easy to replace.
At the same time, we need to check if `v->s == NULL` in
populate_value(), and strbuf cannot easily distinguish NULL and empty
strings, but c-style "const char *" can do it. So add a new member in
`struct atom_value`: `s_size`, which can record raw object size, it
can help us add raw object data to the buffer or compare two buffers
which contain raw object data.
Note that `--format=%(raw)` cannot be used with `--python`, `--shell`,
`--tcl`, and `--perl` because if the binary raw data is passed to a
variable in such languages, these may not support arbitrary binary data
in their string variable type.
Reviewed-by: Jacob Keller <jacob.keller@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Hariom Verma <hariom18599@gmail.com>
Helped-by: Bagas Sanjaya <bagasdotme@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Felipe Contreras <felipe.contreras@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Olga Telezhnaya <olyatelezhnaya@gmail.com>
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-07-26 05:26:47 +02:00
|
|
|
git for-each-ref --format="%(raw:size)" --shell >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'for-each-ref --format compare with cat-file --batch' '
|
|
|
|
git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
|
|
|
|
git for-each-ref --format="%(objectname) %(objecttype) %(objectsize)
|
|
|
|
%(raw)" refs/mytrees/first >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
ref-filter: apply fallback refname sort only after all user sorts
Commit 9e468334b4 (ref-filter: fallback on alphabetical comparison,
2015-10-30) taught ref-filter's sort to fallback to comparing refnames.
But it did it at the wrong level, overriding the comparison result for a
single "--sort" key from the user, rather than after all sort keys have
been exhausted.
This worked correctly for a single "--sort" option, but not for multiple
ones. We'd break any ties in the first key with the refname and never
evaluate the second key at all.
To make matters even more interesting, we only applied this fallback
sometimes! For a field like "taggeremail" which requires a string
comparison, we'd truly return the result of strcmp(), even if it was 0.
But for numerical "value" fields like "taggerdate", we did apply the
fallback. And that's why our multiple-sort test missed this: it uses
taggeremail as the main comparison.
So let's start by adding a much more rigorous test. We'll have a set of
commits expressing every combination of two tagger emails, dates, and
refnames. Then we can confirm that our sort is applied with the correct
precedence, and we'll be hitting both the string and value comparators.
That does show the bug, and the fix is simple: moving the fallback to
the outer compare_refs() function, after all ref_sorting keys have been
exhausted.
Note that in the outer function we don't have an "ignore_case" flag, as
it's part of each individual ref_sorting element. It's debatable what
such a fallback should do, since we didn't use the user's keys to match.
But until now we have been trying to respect that flag, so the
least-invasive thing is to try to continue to do so. Since all callers
in the current code either set the flag for all keys or for none, we can
just pull the flag from the first key. In a hypothetical world where the
user really can flip the case-insensitivity of keys separately, we may
want to extend the code to distinguish that case from a blanket
"--ignore-case".
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-05-03 11:13:09 +02:00
|
|
|
test_expect_success 'set up multiple-sort tags' '
|
|
|
|
for when in 100000 200000
|
|
|
|
do
|
|
|
|
for email in user1 user2
|
|
|
|
do
|
|
|
|
for ref in ref1 ref2
|
|
|
|
do
|
|
|
|
GIT_COMMITTER_DATE="@$when +0000" \
|
|
|
|
GIT_COMMITTER_EMAIL="$email@example.com" \
|
|
|
|
git tag -m "tag $ref-$when-$email" \
|
|
|
|
multi-$ref-$when-$email || return 1
|
|
|
|
done
|
|
|
|
done
|
|
|
|
done
|
|
|
|
'
|
2012-08-21 09:46:06 +02:00
|
|
|
|
2012-08-21 09:47:26 +02:00
|
|
|
test_expect_success 'Verify sort with multiple keys' '
|
ref-filter: apply fallback refname sort only after all user sorts
Commit 9e468334b4 (ref-filter: fallback on alphabetical comparison,
2015-10-30) taught ref-filter's sort to fallback to comparing refnames.
But it did it at the wrong level, overriding the comparison result for a
single "--sort" key from the user, rather than after all sort keys have
been exhausted.
This worked correctly for a single "--sort" option, but not for multiple
ones. We'd break any ties in the first key with the refname and never
evaluate the second key at all.
To make matters even more interesting, we only applied this fallback
sometimes! For a field like "taggeremail" which requires a string
comparison, we'd truly return the result of strcmp(), even if it was 0.
But for numerical "value" fields like "taggerdate", we did apply the
fallback. And that's why our multiple-sort test missed this: it uses
taggeremail as the main comparison.
So let's start by adding a much more rigorous test. We'll have a set of
commits expressing every combination of two tagger emails, dates, and
refnames. Then we can confirm that our sort is applied with the correct
precedence, and we'll be hitting both the string and value comparators.
That does show the bug, and the fix is simple: moving the fallback to
the outer compare_refs() function, after all ref_sorting keys have been
exhausted.
Note that in the outer function we don't have an "ignore_case" flag, as
it's part of each individual ref_sorting element. It's debatable what
such a fallback should do, since we didn't use the user's keys to match.
But until now we have been trying to respect that flag, so the
least-invasive thing is to try to continue to do so. Since all callers
in the current code either set the flag for all keys or for none, we can
just pull the flag from the first key. In a hypothetical world where the
user really can flip the case-insensitivity of keys separately, we may
want to extend the code to distinguish that case from a blanket
"--ignore-case".
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-05-03 11:13:09 +02:00
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
|
|
|
|
EOF
|
|
|
|
git for-each-ref \
|
|
|
|
--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
|
|
|
|
--sort=-refname \
|
|
|
|
--sort=taggeremail \
|
|
|
|
--sort=taggerdate \
|
|
|
|
"refs/tags/multi-*" >actual &&
|
2012-08-21 09:46:06 +02:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
2016-11-19 00:21:12 +01:00
|
|
|
|
ref-filter: apply fallback refname sort only after all user sorts
Commit 9e468334b4 (ref-filter: fallback on alphabetical comparison,
2015-10-30) taught ref-filter's sort to fallback to comparing refnames.
But it did it at the wrong level, overriding the comparison result for a
single "--sort" key from the user, rather than after all sort keys have
been exhausted.
This worked correctly for a single "--sort" option, but not for multiple
ones. We'd break any ties in the first key with the refname and never
evaluate the second key at all.
To make matters even more interesting, we only applied this fallback
sometimes! For a field like "taggeremail" which requires a string
comparison, we'd truly return the result of strcmp(), even if it was 0.
But for numerical "value" fields like "taggerdate", we did apply the
fallback. And that's why our multiple-sort test missed this: it uses
taggeremail as the main comparison.
So let's start by adding a much more rigorous test. We'll have a set of
commits expressing every combination of two tagger emails, dates, and
refnames. Then we can confirm that our sort is applied with the correct
precedence, and we'll be hitting both the string and value comparators.
That does show the bug, and the fix is simple: moving the fallback to
the outer compare_refs() function, after all ref_sorting keys have been
exhausted.
Note that in the outer function we don't have an "ignore_case" flag, as
it's part of each individual ref_sorting element. It's debatable what
such a fallback should do, since we didn't use the user's keys to match.
But until now we have been trying to respect that flag, so the
least-invasive thing is to try to continue to do so. Since all callers
in the current code either set the flag for all keys or for none, we can
just pull the flag from the first key. In a hypothetical world where the
user really can flip the case-insensitivity of keys separately, we may
want to extend the code to distinguish that case from a blanket
"--ignore-case".
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-05-03 11:13:09 +02:00
|
|
|
test_expect_success 'equivalent sorts fall back on refname' '
|
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
|
|
|
|
EOF
|
|
|
|
git for-each-ref \
|
|
|
|
--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
|
|
|
|
--sort=taggerdate \
|
|
|
|
"refs/tags/multi-*" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
2017-01-10 09:49:42 +01:00
|
|
|
|
for-each-ref: delay parsing of --sort=<atom> options
The for-each-ref family of commands invoke parsers immediately when
it sees each --sort=<atom> option, and die before even seeing the
other options on the command line when the <atom> is unrecognised.
Instead, accumulate them in a string list, and have them parsed into
a ref_sorting structure after the command line parsing is done. As
a consequence, "git branch --sort=bogus -h" used to fail to give the
brief help, which arguably may have been a feature, now does so,
which is more consistent with how other options work.
The patch is smaller than the actual extent of the "damage" to the
codebase, thanks to the fact that the original code consistently
used OPT_REF_SORT() macro to handle command line options. We only
needed to replace the variable used for the list, and implementation
of the callback function used in the macro.
The old rule was for the users of the API to:
- Declare ref_sorting and ref_sorting_tail variables;
- OPT_REF_SORT() macro will instantiate ref_sorting instance (which
may barf and die) and append it to the tail;
- Append to the tail each ref_sorting read from the configuration
by parsing in the config callback (which may barf and die);
- See if ref_sorting is null and use ref_sorting_default() instead.
Now the rule is not all that different but is simpler:
- Declare ref_sorting_options string list.
- OPT_REF_SORT() macro will append it to the string list;
- Append to the string list the sort key read from the
configuration;
- call ref_sorting_options() to turn the string list to ref_sorting
structure (which also deals with the default value).
As side effects, this change also cleans up a few issues:
- 95be717c (parse_opt_ref_sorting: always use with NONEG flag,
2019-03-20) muses that "git for-each-ref --no-sort" should simply
clear the sort keys accumulated so far; it now does.
- The implementation detail of "struct ref_sorting" and the helper
function parse_ref_sorting() can now be private to the ref-filter
API implementation.
- If you set branch.sort to a bogus value, the any "git branch"
invocation, not only the listing mode, would abort with the
original code; now it doesn't
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-10-20 21:23:53 +02:00
|
|
|
test_expect_success '--no-sort cancels the previous sort keys' '
|
|
|
|
cat >expected <<-\EOF &&
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
|
|
|
|
100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
|
|
|
|
100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
|
|
|
|
200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
|
|
|
|
200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
|
|
|
|
EOF
|
|
|
|
git for-each-ref \
|
|
|
|
--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
|
|
|
|
--sort=-refname \
|
|
|
|
--sort=taggeremail \
|
|
|
|
--no-sort \
|
|
|
|
--sort=taggerdate \
|
|
|
|
"refs/tags/multi-*" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2016-11-19 00:21:12 +01:00
|
|
|
test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
|
2020-12-06 14:15:59 +01:00
|
|
|
test_when_finished "git checkout main" &&
|
2016-11-19 00:21:12 +01:00
|
|
|
git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
|
|
|
|
sed -e "s/^\* / /" actual >expect &&
|
2017-02-27 10:29:31 +01:00
|
|
|
git checkout --orphan orphaned-branch &&
|
2016-11-19 00:21:12 +01:00
|
|
|
git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2016-11-19 01:58:15 +01:00
|
|
|
cat >trailers <<EOF
|
|
|
|
Reviewed-by: A U Thor <author@example.com>
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
2017-10-02 07:25:22 +02:00
|
|
|
[ v2 updated patch description ]
|
|
|
|
Acked-by: A U Thor
|
|
|
|
<author@example.com>
|
2016-11-19 01:58:15 +01:00
|
|
|
EOF
|
|
|
|
|
2017-10-02 07:25:23 +02:00
|
|
|
unfold () {
|
|
|
|
perl -0pe 's/\n\s+/ /g'
|
|
|
|
}
|
2017-10-02 07:25:22 +02:00
|
|
|
|
|
|
|
test_expect_success 'set up trailers for next test' '
|
2016-11-19 01:58:15 +01:00
|
|
|
echo "Some contents" > two &&
|
|
|
|
git add two &&
|
2017-10-02 07:25:22 +02:00
|
|
|
git commit -F - <<-EOF
|
2016-11-19 01:58:15 +01:00
|
|
|
trailers: this commit message has trailers
|
|
|
|
|
|
|
|
Some message contents
|
|
|
|
|
|
|
|
$(cat trailers)
|
|
|
|
EOF
|
2017-10-02 07:25:22 +02:00
|
|
|
'
|
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
test_trailer_option () {
|
|
|
|
title=$1 option=$2
|
|
|
|
cat >expect
|
|
|
|
test_expect_success "$title" '
|
|
|
|
git for-each-ref --format="%($option)" refs/heads/main >actual &&
|
|
|
|
test_cmp expect actual &&
|
|
|
|
git for-each-ref --format="%(contents:$option)" refs/heads/main >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
}
|
2017-10-02 07:25:23 +02:00
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
test_trailer_option '%(trailers:unfold) unfolds trailers' \
|
|
|
|
'trailers:unfold' <<-EOF
|
|
|
|
$(unfold <trailers)
|
2017-10-02 07:25:23 +02:00
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
EOF
|
2017-10-02 07:25:24 +02:00
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
|
|
|
|
'trailers:only' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
2021-02-13 02:52:43 +01:00
|
|
|
test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
|
|
|
|
'trailers:only=no,only=true' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
|
|
|
|
'trailers:only=yes' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:only=no) shows all trailers' \
|
|
|
|
'trailers:only=no' <<-EOF
|
|
|
|
$(cat trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
test_trailer_option '%(trailers:only) and %(trailers:unfold) work together' \
|
|
|
|
'trailers:only,unfold' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers | unfold)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:unfold) and %(trailers:only) work together' \
|
|
|
|
'trailers:unfold,only' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers | unfold)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
2021-02-13 02:52:43 +01:00
|
|
|
test_trailer_option '%(trailers:key=foo) shows that trailer' \
|
|
|
|
'trailers:key=Signed-off-by' <<-EOF
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo) is case insensitive' \
|
|
|
|
'trailers:key=SiGned-oFf-bY' <<-EOF
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
|
|
|
|
'trailers:key=Signed-off-by:' <<-EOF
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo) multiple keys' \
|
|
|
|
'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
|
|
|
|
Reviewed-by: A U Thor <author@example.com>
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
|
|
|
|
'trailers:key=Shined-off-by:' <<-EOF
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
|
|
|
|
'trailers:key=Acked-by' <<-EOF
|
|
|
|
$(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
|
|
|
|
'trailers:key=Signed-Off-by,unfold' <<-EOF
|
|
|
|
$(unfold <trailers | grep Signed-off-by)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
|
|
|
|
'trailers:key=Signed-off-by,only=no' <<-EOF
|
|
|
|
Signed-off-by: A U Thor <author@example.com>
|
|
|
|
$(grep patch.description <trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
|
|
|
|
'trailers:key=Signed-off-by,valueonly' <<-EOF
|
|
|
|
A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:separator) changes separator' \
|
|
|
|
'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
|
|
|
|
Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
|
|
|
|
'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
|
|
|
|
Reviewed-by,A U Thor <author@example.com>
|
|
|
|
Signed-off-by,A U Thor <author@example.com>
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
|
|
|
|
'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
|
|
|
|
Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
|
|
|
|
EOF
|
|
|
|
|
2021-02-13 02:52:40 +01:00
|
|
|
test_failing_trailer_option () {
|
|
|
|
title=$1 option=$2
|
|
|
|
cat >expect
|
|
|
|
test_expect_success "$title" '
|
|
|
|
# error message cannot be checked under i18n
|
|
|
|
test_must_fail git for-each-ref --format="%($option)" refs/heads/main 2>actual &&
|
2021-04-13 14:19:51 +02:00
|
|
|
test_cmp expect actual &&
|
2021-02-13 02:52:40 +01:00
|
|
|
test_must_fail git for-each-ref --format="%(contents:$option)" refs/heads/main 2>actual &&
|
2021-04-13 14:19:51 +02:00
|
|
|
test_cmp expect actual
|
2021-02-13 02:52:40 +01:00
|
|
|
'
|
|
|
|
}
|
|
|
|
|
|
|
|
test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
|
|
|
|
'trailers:unsupported' <<-\EOF
|
2017-10-02 07:25:23 +02:00
|
|
|
fatal: unknown %(trailers) argument: unsupported
|
|
|
|
EOF
|
|
|
|
|
2021-02-13 02:52:43 +01:00
|
|
|
test_failing_trailer_option '%(trailers:key) without value is error' \
|
|
|
|
'trailers:key' <<-\EOF
|
|
|
|
fatal: expected %(trailers:key=<value>)
|
|
|
|
EOF
|
|
|
|
|
2020-08-21 23:06:14 +02:00
|
|
|
test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
|
2017-10-02 07:25:24 +02:00
|
|
|
cat >expect <<-EOF &&
|
2020-08-21 23:06:14 +02:00
|
|
|
fatal: unrecognized %(contents) argument: trailersonly
|
2017-10-02 07:25:24 +02:00
|
|
|
EOF
|
2020-08-21 23:06:14 +02:00
|
|
|
test_must_fail git for-each-ref --format="%(contents:trailersonly)" 2>actual &&
|
2021-04-13 14:19:51 +02:00
|
|
|
test_cmp expect actual
|
2017-10-02 07:25:24 +02:00
|
|
|
'
|
|
|
|
|
2017-10-02 07:25:22 +02:00
|
|
|
test_expect_success 'basic atom: head contents:trailers' '
|
2020-12-06 14:15:59 +01:00
|
|
|
git for-each-ref --format="%(contents:trailers)" refs/heads/main >actual &&
|
2016-11-19 01:58:15 +01:00
|
|
|
sanitize_pgp <actual >actual.clean &&
|
|
|
|
# git for-each-ref ends with a blank line
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
$(cat trailers)
|
|
|
|
|
|
|
|
EOF
|
|
|
|
test_cmp expect actual.clean
|
|
|
|
'
|
|
|
|
|
2021-07-26 05:26:50 +02:00
|
|
|
test_expect_success 'basic atom: rest must fail' '
|
|
|
|
test_must_fail git for-each-ref --format="%(rest)" refs/heads/main
|
|
|
|
'
|
|
|
|
|
2022-12-14 17:19:43 +01:00
|
|
|
test_expect_success 'HEAD atom does not take arguments' '
|
|
|
|
test_must_fail git for-each-ref --format="%(HEAD:foo)" 2>err &&
|
|
|
|
echo "fatal: %(HEAD) does not take arguments" >expect &&
|
|
|
|
test_cmp expect err
|
|
|
|
'
|
|
|
|
|
2022-12-14 17:20:19 +01:00
|
|
|
test_expect_success 'subject atom rejects unknown arguments' '
|
|
|
|
test_must_fail git for-each-ref --format="%(subject:foo)" 2>err &&
|
|
|
|
echo "fatal: unrecognized %(subject) argument: foo" >expect &&
|
|
|
|
test_cmp expect err
|
|
|
|
'
|
|
|
|
|
ref-filter: truncate atom names in error messages
If you pass a bogus argument to %(refname), you may end up with a
message like this:
$ git for-each-ref --format='%(refname:foo)'
fatal: unrecognized %(refname:foo) argument: foo
which is confusing. It should just say:
fatal: unrecognized %(refname) argument: foo
which is clearer, and is consistent with most other atom parsers. Those
other parsers do not have the same problem because they pass the atom
name from a string literal in the parser function. But because the
parser for %(refname) also handles %(upstream) and %(push), it instead
uses atom->name, which includes the arguments. The oid atom parser which
handles %(tree), %(parent), etc suffers from the same problem.
It seems like the cleanest fix would be for atom->name to be _just_ the
name, since there's already a separate "args" field. But since that
field is also used for other things, we can't change it easily (e.g.,
it's how we find things in the used_atoms array, and clearly %(refname)
and %(refname:short) are not the same thing).
Instead, we'll teach our error_bad_arg() function to stop at the first
":". This is a little hacky, as we're effectively re-parsing the name,
but the format is simple enough to do this as a one-liner, and this
localizes the change to the error-reporting code.
We'll give the same treatment to err_no_arg(). None of its callers use
this atom->name trick, but it's worth future-proofing it while we're
here.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-14 17:23:53 +01:00
|
|
|
test_expect_success 'refname atom rejects unknown arguments' '
|
|
|
|
test_must_fail git for-each-ref --format="%(refname:foo)" 2>err &&
|
|
|
|
echo "fatal: unrecognized %(refname) argument: foo" >expect &&
|
|
|
|
test_cmp expect err
|
|
|
|
'
|
|
|
|
|
2018-08-23 02:50:17 +02:00
|
|
|
test_expect_success 'trailer parsing not fooled by --- line' '
|
|
|
|
git commit --allow-empty -F - <<-\EOF &&
|
|
|
|
this is the subject
|
|
|
|
|
|
|
|
This is the body. The message has a "---" line which would confuse a
|
|
|
|
message+patch parser. But here we know we have only a commit message,
|
|
|
|
so we get it right.
|
|
|
|
|
|
|
|
trailer: wrong
|
|
|
|
---
|
|
|
|
This is more body.
|
|
|
|
|
|
|
|
trailer: right
|
|
|
|
EOF
|
|
|
|
|
|
|
|
{
|
|
|
|
echo "trailer: right" &&
|
|
|
|
echo
|
|
|
|
} >expect &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git for-each-ref --format="%(trailers)" refs/heads/main >actual &&
|
2018-08-23 02:50:17 +02:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2017-01-10 09:49:42 +01:00
|
|
|
test_expect_success 'Add symbolic ref for the following tests' '
|
2020-12-06 14:15:59 +01:00
|
|
|
git symbolic-ref refs/heads/sym refs/heads/main
|
2017-01-10 09:49:42 +01:00
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
refs/heads/main
|
2017-01-10 09:49:42 +01:00
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Verify usage of %(symref) atom' '
|
|
|
|
git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
heads/main
|
2017-01-10 09:49:42 +01:00
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Verify usage of %(symref:short) atom' '
|
|
|
|
git for-each-ref --format="%(symref:short)" refs/heads/sym >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2017-01-10 09:49:44 +01:00
|
|
|
cat >expected <<EOF
|
2020-12-06 14:15:59 +01:00
|
|
|
main
|
|
|
|
heads/main
|
2017-01-10 09:49:44 +01:00
|
|
|
EOF
|
|
|
|
|
2017-01-10 09:49:46 +01:00
|
|
|
test_expect_success 'Verify usage of %(symref:lstrip) atom' '
|
|
|
|
git for-each-ref --format="%(symref:lstrip=2)" refs/heads/sym > actual &&
|
2017-01-10 09:49:48 +01:00
|
|
|
git for-each-ref --format="%(symref:lstrip=-2)" refs/heads/sym >> actual &&
|
2017-02-07 20:50:34 +01:00
|
|
|
test_cmp expected actual &&
|
|
|
|
|
|
|
|
git for-each-ref --format="%(symref:strip=2)" refs/heads/sym > actual &&
|
|
|
|
git for-each-ref --format="%(symref:strip=-2)" refs/heads/sym >> actual &&
|
2017-01-10 09:49:44 +01:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2017-01-10 09:49:49 +01:00
|
|
|
cat >expected <<EOF
|
|
|
|
refs
|
|
|
|
refs/heads
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'Verify usage of %(symref:rstrip) atom' '
|
|
|
|
git for-each-ref --format="%(symref:rstrip=2)" refs/heads/sym > actual &&
|
|
|
|
git for-each-ref --format="%(symref:rstrip=-2)" refs/heads/sym >> actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2017-11-07 17:31:14 +01:00
|
|
|
test_expect_success ':remotename and :remoteref' '
|
|
|
|
git init remote-tests &&
|
|
|
|
(
|
|
|
|
cd remote-tests &&
|
|
|
|
test_commit initial &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git branch -M main &&
|
2017-11-07 17:31:14 +01:00
|
|
|
git remote add from fifth.coffee:blub &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git config branch.main.remote from &&
|
|
|
|
git config branch.main.merge refs/heads/stable &&
|
2017-11-07 17:31:14 +01:00
|
|
|
git remote add to southridge.audio:repo &&
|
|
|
|
git config remote.to.push "refs/heads/*:refs/heads/pushed/*" &&
|
2020-12-06 14:15:59 +01:00
|
|
|
git config branch.main.pushRemote to &&
|
2017-11-07 17:31:14 +01:00
|
|
|
for pair in "%(upstream)=refs/remotes/from/stable" \
|
|
|
|
"%(upstream:remotename)=from" \
|
|
|
|
"%(upstream:remoteref)=refs/heads/stable" \
|
2020-12-06 14:15:59 +01:00
|
|
|
"%(push)=refs/remotes/to/pushed/main" \
|
2017-11-07 17:31:14 +01:00
|
|
|
"%(push:remotename)=to" \
|
2020-12-06 14:15:59 +01:00
|
|
|
"%(push:remoteref)=refs/heads/pushed/main"
|
2017-11-07 17:31:14 +01:00
|
|
|
do
|
|
|
|
echo "${pair#*=}" >expect &&
|
|
|
|
git for-each-ref --format="${pair%=*}" \
|
2020-12-06 14:15:59 +01:00
|
|
|
refs/heads/main >actual &&
|
2021-12-09 06:11:15 +01:00
|
|
|
test_cmp expect actual || exit 1
|
2017-11-07 17:31:14 +01:00
|
|
|
done &&
|
|
|
|
git branch push-simple &&
|
|
|
|
git config branch.push-simple.pushRemote from &&
|
|
|
|
actual="$(git for-each-ref \
|
|
|
|
--format="%(push:remotename),%(push:remoteref)" \
|
|
|
|
refs/heads/push-simple)" &&
|
|
|
|
test from, = "$actual"
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2018-07-02 23:12:42 +02:00
|
|
|
test_expect_success 'for-each-ref --ignore-case ignores case' '
|
2020-12-06 14:15:59 +01:00
|
|
|
git for-each-ref --format="%(refname)" refs/heads/MAIN >actual &&
|
2018-07-27 19:48:11 +02:00
|
|
|
test_must_be_empty actual &&
|
2018-07-02 23:11:23 +02:00
|
|
|
|
2020-12-06 14:15:59 +01:00
|
|
|
echo refs/heads/main >expect &&
|
2018-07-02 23:11:23 +02:00
|
|
|
git for-each-ref --format="%(refname)" --ignore-case \
|
2020-12-06 14:15:59 +01:00
|
|
|
refs/heads/MAIN >actual &&
|
2018-07-02 23:11:23 +02:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
ref-filter: apply --ignore-case to all sorting keys
All of the ref-filter users (for-each-ref, branch, and tag) take an
--ignore-case option which makes filtering and sorting case-insensitive.
However, this option was applied only to the first element of the
ref_sorting list. So:
git for-each-ref --ignore-case --sort=refname
would do what you expect, but:
git for-each-ref --ignore-case --sort=refname --sort=taggername
would sort the primary key (taggername) case-insensitively, but sort the
refname case-sensitively. We have two options here:
- teach callers to set ignore_case on the whole list
- replace the ref_sorting list with a struct that contains both the
list of sorting keys, as well as options that apply to _all_
keys
I went with the first one here, as it gives more flexibility if we later
want to let the users set the flag per-key (presumably through some
special syntax when defining the key; for now it's all or nothing
through --ignore-case).
The new test covers this by sorting on both tagger and subject
case-insensitively, which should compare "a" and "A" identically, but
still sort them before "b" and "B". We'll break ties by sorting on the
refname to give ourselves a stable output (this is actually supposed to
be done automatically, but there's another bug which will be fixed in
the next commit).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-05-03 11:11:57 +02:00
|
|
|
test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
|
|
|
|
# name refs numerically to avoid case-insensitive filesystem conflicts
|
|
|
|
nr=0 &&
|
|
|
|
for email in a A b B
|
|
|
|
do
|
|
|
|
for subject in a A b B
|
|
|
|
do
|
|
|
|
GIT_COMMITTER_EMAIL="$email@example.com" \
|
|
|
|
git tag -m "tag $subject" icase-$(printf %02d $nr) &&
|
|
|
|
nr=$((nr+1))||
|
|
|
|
return 1
|
|
|
|
done
|
|
|
|
done &&
|
|
|
|
git for-each-ref --ignore-case \
|
|
|
|
--format="%(taggeremail) %(subject) %(refname)" \
|
|
|
|
--sort=refname \
|
|
|
|
--sort=subject \
|
|
|
|
--sort=taggeremail \
|
|
|
|
refs/tags/icase-* >actual &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
<a@example.com> tag a refs/tags/icase-00
|
|
|
|
<a@example.com> tag A refs/tags/icase-01
|
|
|
|
<A@example.com> tag a refs/tags/icase-04
|
|
|
|
<A@example.com> tag A refs/tags/icase-05
|
|
|
|
<a@example.com> tag b refs/tags/icase-02
|
|
|
|
<a@example.com> tag B refs/tags/icase-03
|
|
|
|
<A@example.com> tag b refs/tags/icase-06
|
|
|
|
<A@example.com> tag B refs/tags/icase-07
|
|
|
|
<b@example.com> tag a refs/tags/icase-08
|
|
|
|
<b@example.com> tag A refs/tags/icase-09
|
|
|
|
<B@example.com> tag a refs/tags/icase-12
|
|
|
|
<B@example.com> tag A refs/tags/icase-13
|
|
|
|
<b@example.com> tag b refs/tags/icase-10
|
|
|
|
<b@example.com> tag B refs/tags/icase-11
|
|
|
|
<B@example.com> tag b refs/tags/icase-14
|
|
|
|
<B@example.com> tag B refs/tags/icase-15
|
|
|
|
EOF
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2021-04-01 10:32:24 +02:00
|
|
|
test_expect_success 'for-each-ref reports broken tags' '
|
|
|
|
git tag -m "good tag" broken-tag-good HEAD &&
|
|
|
|
git cat-file tag broken-tag-good >good &&
|
|
|
|
sed s/commit/blob/ <good >bad &&
|
|
|
|
bad=$(git hash-object -w -t tag bad) &&
|
|
|
|
git update-ref refs/tags/broken-tag-bad $bad &&
|
|
|
|
test_must_fail git for-each-ref --format="%(*objectname)" \
|
|
|
|
refs/tags/broken-tag-*
|
|
|
|
'
|
|
|
|
|
ref-filter: fix parsing of signatures without blank lines
When ref-filter is asked to show %(content:subject), etc, we end up in
find_subpos() to parse out the three major parts: the subject, the body,
and the signature (if any).
When searching for the blank line between the subject and body, if we
don't find anything, we try to treat the whole message as the subject,
with no body. But our idea of "the whole message" needs to take into
account the signature, too. Since 9f75ce3d8f (ref-filter: handle CRLF at
end-of-line more gracefully, 2020-10-29), the code instead goes all the
way to the end of the buffer, which produces confusing output.
Here's an example. If we have a tag message like this:
this is the subject
-----BEGIN SSH SIGNATURE-----
...some stuff...
-----END SSH SIGNATURE-----
then the current parser will put the start of the body at the end of the
whole buffer. This produces two buggy outcomes:
- since the subject length is computed as (body - subject), showing
%(contents:subject) will print both the subject and the signature,
rather than just the single line
- since the body length is computed as (sig - body), and the body now
starts _after_ the signature, we end up with a negative length!
Fortunately we never access out-of-bounds memory, because the
negative length is fed to xmemdupz(), which casts it to a size_t,
and xmalloc() bails trying to allocate an absurdly large value.
In theory it would be possible for somebody making a malicious tag
to wrap it around to a more reasonable value, but it would require a
tag on the order of 2^63 bytes. And even if they did, all they get
is an out of bounds string read. So the security implications are
probably not interesting.
We can fix both by correctly putting the start of the body at the same
index as the start of the signature (effectively making the body empty).
Note that this is a real issue with signatures generated with gpg.format
set to "ssh", which would look like the example above. In the new tests
here I use a hard-coded tag message, for a few reasons:
- regardless of what the ssh-signing code produces now or in the
future, we should be testing this particular case
- skipping the actual signature makes the tests simpler to write (and
allows them to run on more systems)
- t6300 has helpers for working with gpg signatures; for the purposes
of this bug, "BEGIN PGP" is just as good a demonstration, and this
simplifies the tests
Curiously, the same issue doesn't happen with real gpg signatures (and
there are even existing tests in t6300 with cover this). Those have a
blank line between the header and the content, like:
this is the subject
-----BEGIN PGP SIGNATURE-----
...some stuff...
-----END PGP SIGNATURE-----
Because we search for the subject/body separator line with a strstr(),
we find the blank line in the signature, even though it's outside of
what we'd consider the body. But that puts us unto a separate code path,
which realizes that we're now in the signature and adjusts the line back
to "sigstart". So this patch is basically just making the "no line found
at all" case match that. And note that "sigstart" is always defined (if
there is no signature, it points to the end of the buffer as you'd
expect).
Reported-by: Martin Englund <martin@englund.nu>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-02 08:42:07 +01:00
|
|
|
test_expect_success 'set up tag with signature and no blank lines' '
|
|
|
|
git tag -F - fake-sig-no-blanks <<-\EOF
|
|
|
|
this is the subject
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
|
|
not a real signature, but we just care about the
|
|
|
|
subject/body parsing. It is important here that
|
|
|
|
there are no blank lines in the signature.
|
|
|
|
-----END PGP SIGNATURE-----
|
|
|
|
EOF
|
|
|
|
'
|
|
|
|
|
|
|
|
test_atom refs/tags/fake-sig-no-blanks contents:subject 'this is the subject'
|
|
|
|
test_atom refs/tags/fake-sig-no-blanks contents:body ''
|
|
|
|
test_atom refs/tags/fake-sig-no-blanks contents:signature "$sig"
|
|
|
|
|
ref-filter: fix parsing of signatures with CRLF and no body
This commit fixes a bug when parsing tags that have CRLF line endings, a
signature, and no body, like this (the "^M" are marking the CRs):
this is the subject^M
-----BEGIN PGP SIGNATURE-----^M
^M
...some stuff...^M
-----END PGP SIGNATURE-----^M
When trying to find the start of the body, we look for a blank line
separating the subject and body. In this case, there isn't one. But we
search for it using strstr(), which will find the blank line in the
signature.
In the non-CRLF code path, we check whether the line we found is past
the start of the signature, and if so, put the body pointer at the start
of the signature (effectively making the body empty). But the CRLF code
path doesn't catch the same case, and we end up with the body pointer in
the middle of the signature field. This has two visible problems:
- printing %(contents:subject) will show part of the signature, too,
since the subject length is computed as (body - subject)
- the length of the body is (sig - body), which makes it negative.
Asking for %(contents:body) causes us to cast this to a very large
size_t when we feed it to xmemdupz(), which then complains about
trying to allocate too much memory.
These are essentially the same bugs fixed in the previous commit, except
that they happen when there is a CRLF blank line in the signature,
rather than no blank line at all. Both are caused by the refactoring in
9f75ce3d8f (ref-filter: handle CRLF at end-of-line more gracefully,
2020-10-29).
We can fix this by doing the same "sigstart" check that we do in the
non-CRLF case. And rather than repeat ourselves, we can just use
short-circuiting OR to collapse both cases into a single conditional.
I.e., rather than:
if (strstr("\n\n"))
...found blank, check if it's in signature...
else if (strstr("\r\n\r\n"))
...found blank, check if it's in signature...
else
...no blank line found...
we can collapse this to:
if (strstr("\n\n")) ||
strstr("\r\n\r\n")))
...found blank, check if it's in signature...
else
...no blank line found...
The tests show the problem and the fix. Though it wasn't broken, I
included contents:signature here to make sure it still behaves as
expected, but note the shell hackery needed to make it work. A
less-clever option would be to skip using test_atom and just "append_cr
>expected" ourselves.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
2022-11-02 08:44:00 +01:00
|
|
|
test_expect_success 'set up tag with CRLF signature' '
|
|
|
|
append_cr <<-\EOF |
|
|
|
|
this is the subject
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
|
|
|
|
|
|
not a real signature, but we just care about
|
|
|
|
the subject/body parsing. It is important here
|
|
|
|
that there is a blank line separating this
|
|
|
|
from the signature header.
|
|
|
|
-----END PGP SIGNATURE-----
|
|
|
|
EOF
|
|
|
|
git tag -F - --cleanup=verbatim fake-sig-crlf
|
|
|
|
'
|
|
|
|
|
|
|
|
test_atom refs/tags/fake-sig-crlf contents:subject 'this is the subject'
|
|
|
|
test_atom refs/tags/fake-sig-crlf contents:body ''
|
|
|
|
|
|
|
|
# CRLF is retained in the signature, so we have to pass our expected value
|
|
|
|
# through append_cr. But test_atom requires a shell string, which means command
|
|
|
|
# substitution, and the shell will strip trailing newlines from the output of
|
|
|
|
# the substitution. Hack around it by adding and then removing a dummy line.
|
|
|
|
sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)"
|
|
|
|
sig_crlf=${sig_crlf%dummy}
|
|
|
|
test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf"
|
|
|
|
|
2007-10-02 13:02:57 +02:00
|
|
|
test_done
|