Browse Source
upload-pack spawns two processes, rev-list and pack-objects, and carefully monitors their status so that it can report failure to the remote end. This change removes the complicated procedures on the grounds of the following observations: - If everything is OK, rev-list closes its output pipe end, upon which pack-objects (which reads from the pipe) sees EOF and terminates itself, closing its output (and error) pipes. upload-pack reads from both until it sees EOF in both. It collects the exit codes of the child processes (which indicate success) and terminates successfully. - If rev-list sees an error, it closes its output and terminates with failure. pack-objects sees EOF in its input and terminates successfully. Again upload-pack reads its inputs until EOF. When it now collects the exit codes of its child processes, it notices the failure of rev-list and signals failure to the remote end. - If pack-objects sees an error, it terminates with failure. Since this breaks the pipe to rev-list, rev-list is killed with SIGPIPE. upload-pack reads its input until EOF, then collects the exit codes of the child processes, notices their failures, and signals failure to the remote end. - If upload-pack itself dies unexpectedly, pack-objects is killed with SIGPIPE, and subsequently also rev-list. The upshot of this is that precise monitoring of child processes is not required because both terminate if either one of them dies unexpectedly. This allows us to use finish_command() and finish_async() instead of an explicit waitpid(2) call. The change is smaller than it looks because most of it only reduces the indentation of a large part of the inner loop. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
Johannes Sixt
17 years ago
committed by
Junio C Hamano
2 changed files with 152 additions and 115 deletions
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
#!/bin/sh |
||||
|
||||
test_description='errors in upload-pack' |
||||
|
||||
. ./test-lib.sh |
||||
|
||||
D=`pwd` |
||||
|
||||
corrupt_repo () { |
||||
object_sha1=$(git rev-parse "$1") && |
||||
ob=$(expr "$object_sha1" : "\(..\)") && |
||||
ject=$(expr "$object_sha1" : "..\(..*\)") && |
||||
rm -f ".git/objects/$ob/$ject" |
||||
} |
||||
|
||||
test_expect_success 'setup and corrupt repository' ' |
||||
|
||||
echo file >file && |
||||
git add file && |
||||
git rev-parse :file && |
||||
git commit -a -m original && |
||||
test_tick && |
||||
echo changed >file && |
||||
git commit -a -m changed && |
||||
corrupt_repo HEAD:file |
||||
|
||||
' |
||||
|
||||
test_expect_failure 'fsck fails' ' |
||||
|
||||
git fsck |
||||
' |
||||
|
||||
test_expect_success 'upload-pack fails due to error in pack-objects' ' |
||||
|
||||
! echo "0032want $(git rev-parse HEAD) |
||||
00000009done |
||||
0000" | git-upload-pack . > /dev/null 2> output.err && |
||||
grep "pack-objects died" output.err |
||||
' |
||||
|
||||
test_expect_success 'corrupt repo differently' ' |
||||
|
||||
git hash-object -w file && |
||||
corrupt_repo HEAD^^{tree} |
||||
|
||||
' |
||||
|
||||
test_expect_failure 'fsck fails' ' |
||||
|
||||
git fsck |
||||
' |
||||
test_expect_success 'upload-pack fails due to error in rev-list' ' |
||||
|
||||
! echo "0032want $(git rev-parse HEAD) |
||||
00000009done |
||||
0000" | git-upload-pack . > /dev/null 2> output.err && |
||||
grep "waitpid (async) failed" output.err |
||||
' |
||||
|
||||
test_expect_success 'create empty repository' ' |
||||
|
||||
mkdir foo && |
||||
cd foo && |
||||
git init |
||||
|
||||
' |
||||
|
||||
test_expect_failure 'fetch fails' ' |
||||
|
||||
git fetch .. master |
||||
|
||||
' |
||||
|
||||
test_done |
Loading…
Reference in new issue