diff options
author | Jeff King <peff@peff.net> | 2016-06-30 05:07:54 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-07-01 10:17:39 -0700 |
commit | 48860819e80260abae480407d0bd75dd58e70bb7 (patch) | |
tree | aa6d9940e317423ce6025f17320f7e091b29ebb4 /t/test-lib-functions.sh | |
parent | Git 2.9 (diff) | |
download | tgif-48860819e80260abae480407d0bd75dd58e70bb7.tar.xz |
t9300: factor out portable "head -c" replacement
It is sometimes useful to be able to read exactly N bytes from a
pipe. Doing this portably turns out to be surprisingly difficult
in shell scripts.
We want a solution that:
- is portable
- never reads more than N bytes due to buffering (which
would mean those bytes are not available to the next
program to read from the same pipe)
- handles partial reads by looping until N bytes are read
(or we see EOF)
- is resilient to stray signals giving us EINTR while
trying to read (even though we don't send them, things
like SIGWINCH could cause apparently-random failures)
Some possible solutions are:
- "head -c" is not portable, and implementations may
buffer (though GNU head does not)
- "read -N" is a bash-ism, and thus not portable
- "dd bs=$n count=1" does not handle partial reads. GNU dd
has iflags=fullblock, but that is not portable
- "dd bs=1 count=$n" fixes the partial read problem (all
reads are 1-byte, so there can be no partial response).
It does make a lot of write() calls, but for our tests
that's unlikely to matter. It's fairly portable. We
already use it in our tests, and it's unlikely that
implementations would screw up any of our criteria. The
most unknown one would be signal handling.
- perl can do a sysread() loop pretty easily. On my Linux
system, at least, it seems to restart the read() call
automatically. If that turns out not to be portable,
though, it would be easy for us to handle it.
That makes the perl solution the least bad (because we
conveniently omitted "length of code" as a criterion).
It's also what t9300 is currently using, so we can just pull
the implementation from there.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't/test-lib-functions.sh')
-rw-r--r-- | t/test-lib-functions.sh | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 48884d5208..90856d67e5 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -961,3 +961,17 @@ test_env () { done ) } + +# Read up to "$1" bytes (or to EOF) from stdin and write them to stdout. +test_copy_bytes () { + perl -e ' + my $len = $ARGV[1]; + while ($len > 0) { + my $s; + my $nread = sysread(STDIN, $s, $len); + die "cannot read: $!" unless defined($nread); + print $s; + $len -= $nread; + } + ' - "$1" +} |