chiark / gitweb /
Subprocess error handling: Initialise $? to -1
[dgit.git] / Debian / Dgit.pm
index fa85374150288cc53a1ef363042262315b76ab52..aa0c5a3d675cbf1d7418c222a2e5a9f7a6819182 100644 (file)
@@ -8,6 +8,7 @@ use warnings;
 use POSIX;
 use IO::Handle;
 use Config;
+use Digest::SHA;
 
 BEGIN {
     use Exporter   ();
@@ -18,6 +19,7 @@ BEGIN {
     @EXPORT      = qw(setup_sigwarn
                       debiantag server_branch server_ref
                       stat_exists link_ltarget
+                     hashfile
                       fail ensuredir executable_on_path
                       waitstatusmsg failedcmd
                       cmdoutput cmdoutput_errok
@@ -184,8 +186,19 @@ sub waitstatusmsg () {
 }
 
 sub failedcmd {
+    # Expects $!,$? as set by close - see below.
+    # To use with system(), set $?=-1 first.
+    #
+    # Actual behaviour of perl operations:
+    #   success              $!==0       $?==0       close of piped open
+    #   program failed       $!==0       $? >0       close of piped open
+    #   syscall failure      $! >0       $?=-1       close of piped open
+    #   failure              $! >0       unchanged   close of something else
+    #   success              trashed     $?==0       system
+    #   program failed       trashed     $? >0       system
+    #   syscall failure      $! >0       unchanged   system
     { local ($!); printcmd \*STDERR, _us().": failed command:", @_ or die $!; };
-    if ($!) {
+    if ($? < 0) {
        fail "failed to fork/exec: $!";
     } elsif ($?) {
        fail "subprocess ".waitstatusmsg();
@@ -229,6 +242,13 @@ sub link_ltarget ($$) {
     link $old, $new or die "link $old $new: $!";
 }
 
+sub hashfile ($) {
+    my ($fn) = @_;
+    my $h = Digest::SHA->new(256);
+    $h->addfile($fn);
+    return $h->hexdigest();
+}
+
 sub git_rev_parse ($) {
     return cmdoutput qw(git rev-parse), "$_[0]~0";
 }