chiark / gitweb /
Dgit.pm: Provide rename_link_xf
[dgit.git] / Debian / Dgit.pm
index 5a13e0a14275030e7f0a8296faa1af4ec8d83b3f..b8a1b8c969ffe47d8a5b7b12153bf14871684747 100644 (file)
@@ -48,7 +48,7 @@ BEGIN {
                      upstreamversion
                      stripepoch source_file_leafname is_orig_file_of_p_v
                      server_branch server_ref
-                      stat_exists link_ltarget
+                      stat_exists link_ltarget rename_link_xf
                      hashfile
                       fail failmsg ensuredir must_getcwd executable_on_path
                       waitstatusmsg failedcmd_waitstatus
@@ -425,6 +425,42 @@ sub link_ltarget ($$) {
     $r or fail "(sym)link $old $new: $!\n";
 }
 
+sub rename_link_xf ($$$) {
+    # renames/moves or links/copies $src to $dst,
+    # even if $dst is on a different fs
+    # (May use the filename "$dst.tmp".);
+    # On success, returns true.
+    # On failure, returns false and sets
+    #    $@ to a reason message
+    #    $! to an errno value, or -1 if not known
+    # having possibly printed something about mv to stderr.
+    my ($keeporig,$src,$dst) = @_;
+    if ($keeporig
+       ? link   $src, $dst
+       : rename $src, $dst) {
+       return 1;
+    } elsif ($! != EXDEV) {
+       $@ = "$!";
+       return 0;
+    }
+    $!=0; $?=0;
+    my @cmd = ($keeporig ? qw(cp) : qw(mv));
+    push @cmd, (qw(--), $src, "$dst.tmp");
+    debugcmd '+',@cmd;
+    if (system @cmd) {
+       failedcmd_report_cmd undef, @cmd;
+       $@ = failedcmd_waitstatus();
+       $! = -1;
+       return 0;
+    }
+    if (rename "$dst.tmp", $dst) {
+       return 1;
+    } else {
+       $@ = f_ "finally install file after mv: %S", $!;
+       return 0;
+    }
+}
+
 sub hashfile ($) {
     my ($fn) = @_;
     my $h = Digest::SHA->new(256);
@@ -457,7 +493,7 @@ sub git_cat_file ($;$) {
        debugcmd "GCF|", @cmd;
        $gcf_pid = open2 $gcf_o, $gcf_i, @cmd or confess $!;
     }
-    printdebug "GCF>| ", $objname, "\n";
+    printdebug "GCF>| $objname\n";
     print $gcf_i $objname, "\n" or confess $!;
     my $x = <$gcf_o>;
     printdebug "GCF<| ", $x;
@@ -541,8 +577,8 @@ sub git_check_unmodified () {
        if ($?==256) {
            fail
                $cached
-               ? "git index contains changes (does not match HEAD)"
-               : "working tree is dirty (does not match HEAD)";
+               ? __ "git index contains changes (does not match HEAD)"
+               : __ "working tree is dirty (does not match HEAD)";
        } else {
            failedcmd @cmd;
        }
@@ -613,8 +649,8 @@ sub gdr_ffq_prev_branchinfo ($) {
     #    branch         message is undef
     #    weird-symref   } no $symref,
     #    notbranch      }  no $ffq_prev
-    return ('detached', 'detached HEAD') unless defined $symref;
-    return ('weird-symref', 'HEAD symref is not to refs/')
+    return ('detached', __ 'detached HEAD') unless defined $symref;
+    return ('weird-symref', __ 'HEAD symref is not to refs/')
        unless $symref =~ m{^refs/};
     my $ffq_prev = "refs/$ffq_refprefix/$'";
     my $gdrlast = "refs/$gdrlast_refprefix/$'";
@@ -630,7 +666,7 @@ sub parsecontrolfh ($$;$) {
        my %opts = ('name' => $desc);
        $opts{allow_pgp}= $allowsigned || !$dpkgcontrolhash_noissigned;
        $c = Dpkg::Control::Hash->new(%opts);
-       $c->parse($fh,$desc) or fail "parsing of $desc failed";
+       $c->parse($fh,$desc) or fail f_ "parsing of %s failed", $desc;
        last if $allowsigned;
        last if $dpkgcontrolhash_noissigned;
        my $issigned= $c->get_option('is_pgp_signed');
@@ -638,9 +674,11 @@ sub parsecontrolfh ($$;$) {
            $dpkgcontrolhash_noissigned= 1;
            seek $fh, 0,0 or confess "seek $desc: $!";
        } elsif ($issigned) {
-           fail "control file $desc is (already) PGP-signed. ".
+           fail f_
+               "control file %s is (already) PGP-signed. ".
                " Note that dgit push needs to modify the .dsc and then".
-               " do the signature itself";
+               " do the signature itself",
+               $desc;
        } else {
            last;
        }
@@ -651,7 +689,7 @@ sub parsecontrolfh ($$;$) {
 sub parsecontrol {
     my ($file, $desc, $allowsigned) = @_;
     my $fh = new IO::Handle;
-    open $fh, '<', $file or fail "open $file ($desc): $!";
+    open $fh, '<', $file or fail f_ "open %s (%s): %s", $file, $desc, $!;
     my $c = parsecontrolfh($fh,$desc,$allowsigned);
     $fh->error and confess $!;
     close $fh;
@@ -737,7 +775,7 @@ sub reflog_cache_insert ($$$) {
        # git update-ref doesn't always update, in this case.  *sigh*
        my $authline = (ucfirst _us()).
            ' <'._us().'@example.com> 1000000000 +0000';
-       my $dummy = make_commit_text <<ENDU.<<END;
+       my $dummy = make_commit_text <<ENDU.(__ <<END);
 tree $tree
 parent $value
 author $authline
@@ -765,7 +803,7 @@ sub reflog_cache_lookup ($$) {
            printdebug ">(no reflog)\n";
            finish 0;
        }
-       exec @cmd; confess $!;
+       exec @cmd; die f_ "exec %s: %s\n", $cmd[0], $!;
     }
     while (<GC>) {
        chomp;
@@ -833,7 +871,7 @@ sub record_maindir () {
     if (!defined $maindir) {
        $maindir = must_getcwd();
        if (!stat "$maindir/.git") {
-           fail "cannot stat $maindir/.git: $!";
+           fail f_ "cannot stat %s/.git: %s", $maindir, $!;
        }
        if (-d _) {
            # we fall back to this in case we have a pre-worktree
@@ -855,15 +893,16 @@ sub ensure_a_playground_parent ($) {
     record_maindir();
     $spc = "$maindir_gitdir/$spc";
     my $parent = dirname $spc;
-    mkdir $parent or $!==EEXIST
-       or fail "failed to mkdir playground parent $parent: $!";
+    mkdir $parent or $!==EEXIST or fail f_
+       "failed to mkdir playground parent %s: %s", $parent, $!;
     return $spc;
 }    
 
 sub ensure_a_playground ($) {
     my ($spc) = @_;
     $spc = ensure_a_playground_parent $spc;
-    mkdir $spc or $!==EEXIST or fail "failed to mkdir a playground $spc: $!";
+    mkdir $spc or $!==EEXIST or fail f_
+       "failed to mkdir a playground %s: %s", $spc, $!;
     return $spc;
 }    
 
@@ -871,7 +910,8 @@ sub fresh_playground ($) {
     my ($spc) = @_;
     $spc = ensure_a_playground_parent $spc;
     rmtree $spc;
-    mkdir $spc or fail "failed to mkdir the playground $spc: $!";
+    mkdir $spc or fail f_
+       "failed to mkdir the playground %s: %s", $spc, $!;
     return $spc;
 }