2007-04-22 06:09:02 +04:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='blob conversion via gitattributes'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
2010-01-02 01:14:06 +03:00
|
|
|
cat <<EOF >rot13.sh
|
|
|
|
#!$SHELL_PATH
|
2008-03-11 20:40:45 +03:00
|
|
|
tr \
|
|
|
|
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
|
|
|
|
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
|
2007-04-21 14:14:13 +04:00
|
|
|
EOF
|
|
|
|
chmod +x rot13.sh
|
|
|
|
|
2007-04-22 06:09:02 +04:00
|
|
|
test_expect_success setup '
|
2007-04-21 14:14:13 +04:00
|
|
|
git config filter.rot13.smudge ./rot13.sh &&
|
|
|
|
git config filter.rot13.clean ./rot13.sh &&
|
|
|
|
|
2007-04-22 06:09:02 +04:00
|
|
|
{
|
2007-04-21 14:14:13 +04:00
|
|
|
echo "*.t filter=rot13"
|
2007-04-22 06:09:02 +04:00
|
|
|
echo "*.i ident"
|
|
|
|
} >.gitattributes &&
|
|
|
|
|
|
|
|
{
|
|
|
|
echo a b c d e f g h i j k l m
|
|
|
|
echo n o p q r s t u v w x y z
|
2007-05-14 17:37:25 +04:00
|
|
|
echo '\''$Id$'\''
|
2007-04-22 06:09:02 +04:00
|
|
|
} >test &&
|
|
|
|
cat test >test.t &&
|
|
|
|
cat test >test.o &&
|
|
|
|
cat test >test.i &&
|
|
|
|
git add test test.t test.i &&
|
|
|
|
rm -f test test.t test.i &&
|
|
|
|
git checkout -- test test.t test.i
|
|
|
|
'
|
|
|
|
|
2007-05-14 17:37:25 +04:00
|
|
|
script='s/^\$Id: \([0-9a-f]*\) \$/\1/p'
|
2007-04-22 06:09:02 +04:00
|
|
|
|
|
|
|
test_expect_success check '
|
|
|
|
|
|
|
|
cmp test.o test &&
|
|
|
|
cmp test.o test.t &&
|
|
|
|
|
|
|
|
# ident should be stripped in the repository
|
|
|
|
git diff --raw --exit-code :test :test.i &&
|
|
|
|
id=$(git rev-parse --verify :test) &&
|
|
|
|
embedded=$(sed -ne "$script" test.i) &&
|
2007-10-19 23:48:04 +04:00
|
|
|
test "z$id" = "z$embedded" &&
|
|
|
|
|
|
|
|
git cat-file blob :test.t > test.r &&
|
|
|
|
|
|
|
|
./rot13.sh < test.o > test.t &&
|
|
|
|
cmp test.r test.t
|
2007-04-22 06:09:02 +04:00
|
|
|
'
|
|
|
|
|
2007-05-27 14:52:11 +04:00
|
|
|
# If an expanded ident ever gets into the repository, we want to make sure that
|
|
|
|
# it is collapsed before being expanded again on checkout
|
|
|
|
test_expect_success expanded_in_repo '
|
|
|
|
{
|
|
|
|
echo "File with expanded keywords"
|
|
|
|
echo "\$Id\$"
|
|
|
|
echo "\$Id:\$"
|
|
|
|
echo "\$Id: 0000000000000000000000000000000000000000 \$"
|
|
|
|
echo "\$Id: NoSpaceAtEnd\$"
|
|
|
|
echo "\$Id:NoSpaceAtFront \$"
|
|
|
|
echo "\$Id:NoSpaceAtEitherEnd\$"
|
|
|
|
echo "\$Id: NoTerminatingSymbol"
|
2010-04-06 16:46:37 +04:00
|
|
|
echo "\$Id: Foreign Commit With Spaces \$"
|
2011-05-25 05:02:48 +04:00
|
|
|
} >expanded-keywords.0 &&
|
2007-05-27 14:52:11 +04:00
|
|
|
|
2011-05-25 05:02:48 +04:00
|
|
|
{
|
|
|
|
cat expanded-keywords.0 &&
|
|
|
|
printf "\$Id: NoTerminatingSymbolAtEOF"
|
|
|
|
} >expanded-keywords &&
|
|
|
|
cat expanded-keywords >expanded-keywords-crlf &&
|
|
|
|
git add expanded-keywords expanded-keywords-crlf &&
|
2011-05-22 01:25:06 +04:00
|
|
|
git commit -m "File with keywords expanded" &&
|
|
|
|
id=$(git rev-parse --verify :expanded-keywords) &&
|
|
|
|
|
2007-05-27 14:52:11 +04:00
|
|
|
{
|
|
|
|
echo "File with expanded keywords"
|
2011-05-22 01:25:06 +04:00
|
|
|
echo "\$Id: $id \$"
|
|
|
|
echo "\$Id: $id \$"
|
|
|
|
echo "\$Id: $id \$"
|
|
|
|
echo "\$Id: $id \$"
|
|
|
|
echo "\$Id: $id \$"
|
|
|
|
echo "\$Id: $id \$"
|
2007-05-27 14:52:11 +04:00
|
|
|
echo "\$Id: NoTerminatingSymbol"
|
2010-04-06 16:46:38 +04:00
|
|
|
echo "\$Id: Foreign Commit With Spaces \$"
|
2011-05-25 05:02:48 +04:00
|
|
|
} >expected-output.0 &&
|
|
|
|
{
|
|
|
|
cat expected-output.0 &&
|
2011-05-22 01:25:06 +04:00
|
|
|
printf "\$Id: NoTerminatingSymbolAtEOF"
|
2011-05-25 05:02:48 +04:00
|
|
|
} >expected-output &&
|
|
|
|
{
|
|
|
|
append_cr <expected-output.0 &&
|
|
|
|
printf "\$Id: NoTerminatingSymbolAtEOF"
|
|
|
|
} >expected-output-crlf &&
|
|
|
|
{
|
|
|
|
echo "expanded-keywords ident"
|
|
|
|
echo "expanded-keywords-crlf ident text eol=crlf"
|
|
|
|
} >>.gitattributes &&
|
2007-05-27 14:52:11 +04:00
|
|
|
|
2011-05-25 05:02:48 +04:00
|
|
|
rm -f expanded-keywords expanded-keywords-crlf &&
|
2007-05-27 14:52:11 +04:00
|
|
|
|
|
|
|
git checkout -- expanded-keywords &&
|
2011-05-25 05:02:48 +04:00
|
|
|
test_cmp expanded-keywords expected-output &&
|
|
|
|
|
|
|
|
git checkout -- expanded-keywords-crlf &&
|
|
|
|
test_cmp expanded-keywords-crlf expected-output-crlf
|
2007-05-27 14:52:11 +04:00
|
|
|
'
|
|
|
|
|
2010-12-22 17:40:13 +03:00
|
|
|
# The use of %f in a filter definition is expanded to the path to
|
|
|
|
# the filename being smudged or cleaned. It must be shell escaped.
|
|
|
|
# First, set up some interesting file names and pet them in
|
|
|
|
# .gitattributes.
|
|
|
|
test_expect_success 'filter shell-escaped filenames' '
|
|
|
|
cat >argc.sh <<-EOF &&
|
|
|
|
#!$SHELL_PATH
|
2010-12-23 02:18:47 +03:00
|
|
|
cat >/dev/null
|
2010-12-22 17:40:13 +03:00
|
|
|
echo argc: \$# "\$@"
|
|
|
|
EOF
|
|
|
|
normal=name-no-magic &&
|
|
|
|
special="name with '\''sq'\'' and \$x" &&
|
|
|
|
echo some test text >"$normal" &&
|
|
|
|
echo some test text >"$special" &&
|
|
|
|
git add "$normal" "$special" &&
|
|
|
|
git commit -q -m "add files" &&
|
|
|
|
echo "name* filter=argc" >.gitattributes &&
|
|
|
|
|
|
|
|
# delete the files and check them out again, using a smudge filter
|
|
|
|
# that will count the args and echo the command-line back to us
|
|
|
|
git config filter.argc.smudge "sh ./argc.sh %f" &&
|
|
|
|
rm "$normal" "$special" &&
|
|
|
|
git checkout -- "$normal" "$special" &&
|
|
|
|
|
|
|
|
# make sure argc.sh counted the right number of args
|
|
|
|
echo "argc: 1 $normal" >expect &&
|
|
|
|
test_cmp expect "$normal" &&
|
|
|
|
echo "argc: 1 $special" >expect &&
|
|
|
|
test_cmp expect "$special" &&
|
|
|
|
|
|
|
|
# do the same thing, but with more args in the filter expression
|
|
|
|
git config filter.argc.smudge "sh ./argc.sh %f --my-extra-arg" &&
|
|
|
|
rm "$normal" "$special" &&
|
|
|
|
git checkout -- "$normal" "$special" &&
|
|
|
|
|
|
|
|
# make sure argc.sh counted the right number of args
|
|
|
|
echo "argc: 2 $normal --my-extra-arg" >expect &&
|
|
|
|
test_cmp expect "$normal" &&
|
|
|
|
echo "argc: 2 $special --my-extra-arg" >expect &&
|
|
|
|
test_cmp expect "$special" &&
|
|
|
|
:
|
|
|
|
'
|
|
|
|
|
2014-08-26 19:23:25 +04:00
|
|
|
test_expect_success 'required filter should filter data' '
|
|
|
|
git config filter.required.smudge ./rot13.sh &&
|
|
|
|
git config filter.required.clean ./rot13.sh &&
|
Add a setting to require a filter to be successful
By default, a missing filter driver or a failure from the filter driver is
not an error, but merely makes the filter operation a no-op pass through.
This is useful to massage the content into a shape that is more convenient
for the platform, filesystem, and the user to use, and the content filter
mechanism is not used to turn something unusable into usable.
However, we could also use of the content filtering mechanism and store
the content that cannot be directly used in the repository (e.g. a UUID
that refers to the true content stored outside git, or an encrypted
content) and turn it into a usable form upon checkout (e.g. download the
external content, or decrypt the encrypted content). For such a use case,
the content cannot be used when filter driver fails, and we need a way to
tell Git to abort the whole operation for such a failing or missing filter
driver.
Add a new "filter.<driver>.required" configuration variable to mark the
second use case. When it is set, git will abort the operation when the
filter driver does not exist or exits with a non-zero status code.
Signed-off-by: Jehan Bing <jehan@orb.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-17 05:19:03 +04:00
|
|
|
git config filter.required.required true &&
|
|
|
|
|
|
|
|
echo "*.r filter=required" >.gitattributes &&
|
|
|
|
|
2014-08-26 19:23:25 +04:00
|
|
|
cat test.o >test.r &&
|
Add a setting to require a filter to be successful
By default, a missing filter driver or a failure from the filter driver is
not an error, but merely makes the filter operation a no-op pass through.
This is useful to massage the content into a shape that is more convenient
for the platform, filesystem, and the user to use, and the content filter
mechanism is not used to turn something unusable into usable.
However, we could also use of the content filtering mechanism and store
the content that cannot be directly used in the repository (e.g. a UUID
that refers to the true content stored outside git, or an encrypted
content) and turn it into a usable form upon checkout (e.g. download the
external content, or decrypt the encrypted content). For such a use case,
the content cannot be used when filter driver fails, and we need a way to
tell Git to abort the whole operation for such a failing or missing filter
driver.
Add a new "filter.<driver>.required" configuration variable to mark the
second use case. When it is set, git will abort the operation when the
filter driver does not exist or exits with a non-zero status code.
Signed-off-by: Jehan Bing <jehan@orb.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-17 05:19:03 +04:00
|
|
|
git add test.r &&
|
2014-08-26 19:23:25 +04:00
|
|
|
|
Add a setting to require a filter to be successful
By default, a missing filter driver or a failure from the filter driver is
not an error, but merely makes the filter operation a no-op pass through.
This is useful to massage the content into a shape that is more convenient
for the platform, filesystem, and the user to use, and the content filter
mechanism is not used to turn something unusable into usable.
However, we could also use of the content filtering mechanism and store
the content that cannot be directly used in the repository (e.g. a UUID
that refers to the true content stored outside git, or an encrypted
content) and turn it into a usable form upon checkout (e.g. download the
external content, or decrypt the encrypted content). For such a use case,
the content cannot be used when filter driver fails, and we need a way to
tell Git to abort the whole operation for such a failing or missing filter
driver.
Add a new "filter.<driver>.required" configuration variable to mark the
second use case. When it is set, git will abort the operation when the
filter driver does not exist or exits with a non-zero status code.
Signed-off-by: Jehan Bing <jehan@orb.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-17 05:19:03 +04:00
|
|
|
rm -f test.r &&
|
2014-08-26 19:23:25 +04:00
|
|
|
git checkout -- test.r &&
|
|
|
|
cmp test.o test.r &&
|
|
|
|
|
|
|
|
./rot13.sh <test.o >expected &&
|
|
|
|
git cat-file blob :test.r >actual &&
|
|
|
|
cmp expected actual
|
Add a setting to require a filter to be successful
By default, a missing filter driver or a failure from the filter driver is
not an error, but merely makes the filter operation a no-op pass through.
This is useful to massage the content into a shape that is more convenient
for the platform, filesystem, and the user to use, and the content filter
mechanism is not used to turn something unusable into usable.
However, we could also use of the content filtering mechanism and store
the content that cannot be directly used in the repository (e.g. a UUID
that refers to the true content stored outside git, or an encrypted
content) and turn it into a usable form upon checkout (e.g. download the
external content, or decrypt the encrypted content). For such a use case,
the content cannot be used when filter driver fails, and we need a way to
tell Git to abort the whole operation for such a failing or missing filter
driver.
Add a new "filter.<driver>.required" configuration variable to mark the
second use case. When it is set, git will abort the operation when the
filter driver does not exist or exits with a non-zero status code.
Signed-off-by: Jehan Bing <jehan@orb.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-17 05:19:03 +04:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'required filter smudge failure' '
|
|
|
|
git config filter.failsmudge.smudge false &&
|
|
|
|
git config filter.failsmudge.clean cat &&
|
|
|
|
git config filter.failsmudge.required true &&
|
|
|
|
|
|
|
|
echo "*.fs filter=failsmudge" >.gitattributes &&
|
|
|
|
|
|
|
|
echo test >test.fs &&
|
|
|
|
git add test.fs &&
|
|
|
|
rm -f test.fs &&
|
|
|
|
test_must_fail git checkout -- test.fs
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'required filter clean failure' '
|
|
|
|
git config filter.failclean.smudge cat &&
|
|
|
|
git config filter.failclean.clean false &&
|
|
|
|
git config filter.failclean.required true &&
|
|
|
|
|
|
|
|
echo "*.fc filter=failclean" >.gitattributes &&
|
|
|
|
|
|
|
|
echo test >test.fc &&
|
|
|
|
test_must_fail git add test.fc
|
|
|
|
'
|
|
|
|
|
2014-08-26 19:23:25 +04:00
|
|
|
test_expect_success 'filtering large input to small output should use little memory' '
|
|
|
|
git config filter.devnull.clean "cat >/dev/null" &&
|
|
|
|
git config filter.devnull.required true &&
|
|
|
|
for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB &&
|
|
|
|
echo "30MB filter=devnull" >.gitattributes &&
|
|
|
|
GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
|
|
|
|
'
|
|
|
|
|
2015-05-19 21:08:23 +03:00
|
|
|
test_expect_success 'filter that does not read is fine' '
|
|
|
|
test-genrandom foo $((128 * 1024 + 1)) >big &&
|
|
|
|
echo "big filter=epipe" >.gitattributes &&
|
|
|
|
git config filter.epipe.clean "echo xyzzy" &&
|
|
|
|
git add big &&
|
|
|
|
git cat-file blob :big >actual &&
|
|
|
|
echo xyzzy >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
xread, xwrite: limit size of IO to 8MB
Checking out 2GB or more through an external filter (see test) fails
on Mac OS X 10.8.4 (12E55) for a 64-bit executable with:
error: read from external filter cat failed
error: cannot feed the input to external filter cat
error: cat died of signal 13
error: external filter cat failed 141
error: external filter cat failed
The reason is that read() immediately returns with EINVAL when asked
to read more than 2GB. According to POSIX [1], if the value of
nbyte passed to read() is greater than SSIZE_MAX, the result is
implementation-defined. The write function has the same restriction
[2]. Since OS X still supports running 32-bit executables, the
32-bit limit (SSIZE_MAX = INT_MAX = 2GB - 1) seems to be also
imposed on 64-bit executables under certain conditions. For write,
the problem has been addressed earlier [6c642a].
Address the problem for read() and write() differently, by limiting
size of IO chunks unconditionally on all platforms in xread() and
xwrite(). Large chunks only cause problems, like causing latencies
when killing the process, even if OS X was not buggy. Doing IO in
reasonably sized smaller chunks should have no negative impact on
performance.
The compat wrapper clipped_write() introduced earlier [6c642a] is
not needed anymore. It will be reverted in a separate commit. The
new test catches read and write problems.
Note that 'git add' exits with 0 even if it prints filtering errors
to stderr. The test, therefore, checks stderr. 'git add' should
probably be changed (sometime in another commit) to exit with
nonzero if filtering fails. The test could then be changed to use
test_must_fail.
Thanks to the following people for suggestions and testing:
Johannes Sixt <j6t@kdbg.org>
John Keeping <john@keeping.me.uk>
Jonathan Nieder <jrnieder@gmail.com>
Kyle J. McKay <mackyle@gmail.com>
Linus Torvalds <torvalds@linux-foundation.org>
Torsten Bögershausen <tboegi@web.de>
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html
[2] http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html
[6c642a] commit 6c642a878688adf46b226903858b53e2d31ac5c3
compate/clipped-write.c: large write(2) fails on Mac OS X/XNU
Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-08-20 10:43:54 +04:00
|
|
|
test_expect_success EXPENSIVE 'filter large file' '
|
|
|
|
git config filter.largefile.smudge cat &&
|
|
|
|
git config filter.largefile.clean cat &&
|
|
|
|
for i in $(test_seq 1 2048); do printf "%1048576d" 1; done >2GB &&
|
|
|
|
echo "2GB filter=largefile" >.gitattributes &&
|
|
|
|
git add 2GB 2>err &&
|
|
|
|
! test -s err &&
|
|
|
|
rm -f 2GB &&
|
|
|
|
git checkout -- 2GB 2>err &&
|
|
|
|
! test -s err
|
|
|
|
'
|
|
|
|
|
sha1_file: pass empty buffer to index empty file
`git add` of an empty file with a filter pops complaints from
`copy_fd` about a bad file descriptor.
This traces back to these lines in sha1_file.c:index_core:
if (!size) {
ret = index_mem(sha1, NULL, size, type, path, flags);
The problem here is that content to be added to the index can be
supplied from an fd, or from a memory buffer, or from a pathname. This
call is supplying a NULL buffer pointer and a zero size.
Downstream logic takes the complete absence of a buffer to mean the
data is to be found elsewhere -- for instance, these, from convert.c:
if (params->src) {
write_err = (write_in_full(child_process.in, params->src, params->size) < 0);
} else {
write_err = copy_fd(params->fd, child_process.in);
}
~If there's a buffer, write from that, otherwise the data must be coming
from an open fd.~
Perfectly reasonable logic in a routine that's going to write from
either a buffer or an fd.
So change `index_core` to supply an empty buffer when indexing an empty
file.
There's a patch out there that instead changes the logic quoted above to
take a `-1` fd to mean "use the buffer", but it seems to me that the
distinction between a missing buffer and an empty one carries intrinsic
semantics, where the logic change is adapting the code to handle
incorrect arguments.
Signed-off-by: Jim Hill <gjthill@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-18 03:41:45 +03:00
|
|
|
test_expect_success "filter: clean empty file" '
|
|
|
|
git config filter.in-repo-header.clean "echo cleaned && cat" &&
|
|
|
|
git config filter.in-repo-header.smudge "sed 1d" &&
|
|
|
|
|
|
|
|
echo "empty-in-worktree filter=in-repo-header" >>.gitattributes &&
|
|
|
|
>empty-in-worktree &&
|
|
|
|
|
|
|
|
echo cleaned >expected &&
|
|
|
|
git add empty-in-worktree &&
|
|
|
|
git show :empty-in-worktree >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "filter: smudge empty file" '
|
|
|
|
git config filter.empty-in-repo.clean "cat >/dev/null" &&
|
|
|
|
git config filter.empty-in-repo.smudge "echo smudged && cat" &&
|
|
|
|
|
|
|
|
echo "empty-in-repo filter=empty-in-repo" >>.gitattributes &&
|
|
|
|
echo dead data walking >empty-in-repo &&
|
|
|
|
git add empty-in-repo &&
|
|
|
|
|
|
|
|
echo smudged >expected &&
|
|
|
|
git checkout-index --prefix=filtered- empty-in-repo &&
|
|
|
|
test_cmp expected filtered-empty-in-repo
|
|
|
|
'
|
|
|
|
|
2016-01-29 11:21:37 +03:00
|
|
|
test_expect_success 'disable filter with empty override' '
|
|
|
|
test_config_global filter.disable.smudge false &&
|
|
|
|
test_config_global filter.disable.clean false &&
|
|
|
|
test_config filter.disable.smudge false &&
|
|
|
|
test_config filter.disable.clean false &&
|
|
|
|
|
|
|
|
echo "*.disable filter=disable" >.gitattributes &&
|
|
|
|
|
|
|
|
echo test >test.disable &&
|
|
|
|
git -c filter.disable.clean= add test.disable 2>err &&
|
|
|
|
test_must_be_empty err &&
|
|
|
|
rm -f test.disable &&
|
|
|
|
git -c filter.disable.smudge= checkout -- test.disable 2>err &&
|
|
|
|
test_must_be_empty err
|
|
|
|
'
|
|
|
|
|
2007-04-22 06:09:02 +04:00
|
|
|
test_done
|