Skip to content

Commit 4886081

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 05219a1 commit 4886081

File tree

2 files changed

+17
-20
lines changed

2 files changed

+17
-20
lines changed

t/t9300-fast-import.sh

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,6 @@ test_description='test git fast-import utility'
77
. ./test-lib.sh
88
. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
99

10-
# Print $1 bytes from stdin to stdout.
11-
#
12-
# This could be written as "head -c $1", but IRIX "head" does not
13-
# support the -c option.
14-
head_c () {
15-
perl -e '
16-
my $len = $ARGV[1];
17-
while ($len > 0) {
18-
my $s;
19-
my $nread = sysread(STDIN, $s, $len);
20-
die "cannot read: $!" unless defined($nread);
21-
print $s;
22-
$len -= $nread;
23-
}
24-
' - "$1"
25-
}
26-
2710
verify_packs () {
2811
for p in .git/objects/pack/*.pack
2912
do
@@ -2480,7 +2463,7 @@ test_expect_success PIPE 'R: copy using cat-file' '
24802463
24812464
read blob_id type size <&3 &&
24822465
echo "$blob_id $type $size" >response &&
2483-
head_c $size >blob <&3 &&
2466+
test_copy_bytes $size >blob <&3 &&
24842467
read newline <&3 &&
24852468
24862469
cat <<-EOF &&
@@ -2523,7 +2506,7 @@ test_expect_success PIPE 'R: print blob mid-commit' '
25232506
EOF
25242507
25252508
read blob_id type size <&3 &&
2526-
head_c $size >actual <&3 &&
2509+
test_copy_bytes $size >actual <&3 &&
25272510
read newline <&3 &&
25282511
25292512
echo
@@ -2558,7 +2541,7 @@ test_expect_success PIPE 'R: print staged blob within commit' '
25582541
echo "cat-blob $to_get" &&
25592542
25602543
read blob_id type size <&3 &&
2561-
head_c $size >actual <&3 &&
2544+
test_copy_bytes $size >actual <&3 &&
25622545
read newline <&3 &&
25632546
25642547
echo deleteall

t/test-lib-functions.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,17 @@ test_env () {
961961
done
962962
)
963963
}
964+
965+
# Read up to "$1" bytes (or to EOF) from stdin and write them to stdout.
966+
test_copy_bytes () {
967+
perl -e '
968+
my $len = $ARGV[1];
969+
while ($len > 0) {
970+
my $s;
971+
my $nread = sysread(STDIN, $s, $len);
972+
die "cannot read: $!" unless defined($nread);
973+
print $s;
974+
$len -= $nread;
975+
}
976+
' - "$1"
977+
}

0 commit comments

Comments
 (0)