X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=Debian%2FDgit.pm;h=2ef32f32a8179f9dc590bfdbcf27419470a62f21;hb=e19ffd361e29885a06765c65bd988b09c85b908b;hp=08a5b6c29a9ae21fc414d49f0eb18b02ae40931f;hpb=c826365c57b445c06ba4d5c5c90be24556eaa97b;p=dgit.git diff --git a/Debian/Dgit.pm b/Debian/Dgit.pm index 08a5b6c2..2ef32f32 100644 --- a/Debian/Dgit.pm +++ b/Debian/Dgit.pm @@ -54,7 +54,7 @@ BEGIN { waitstatusmsg failedcmd_waitstatus failedcmd_report_cmd failedcmd runcmd shell_cmd cmdoutput cmdoutput_errok - git_rev_parse git_cat_file + git_rev_parse changedir_git_toplevel git_cat_file git_get_ref git_get_symref git_for_each_ref git_for_each_tag_referring is_fast_fwd git_check_unmodified @@ -98,7 +98,7 @@ our $distro_re = $component_re; our $versiontag_re = qr{[-+.\%_0-9a-zA-Z/]+}; our $branchprefix = 'dgit'; our $series_filename_re = qr{(?:^|\.)series(?!\n)$}s; -our $extra_orig_namepart_re = qr{[-0-9a-z]+}; +our $extra_orig_namepart_re = qr{[-0-9a-zA-Z]+}; our $orig_f_comp_re = qr{orig(?:-$extra_orig_namepart_re)?}; our $orig_f_sig_re = '\\.(?:asc|gpg|pgp)'; our $orig_f_tail_re = "$orig_f_comp_re\\.tar(?:\\.\\w+)?(?:$orig_f_sig_re)?"; @@ -434,6 +434,8 @@ sub rename_link_xf ($$$) { # $@ to a reason message # $! to an errno value, or -1 if not known # having possibly printed something about mv to stderr. + # Not safe to use without $keeporig if $dst might be a symlink + # to $src, as it might delete $src leaving $dst invalid. my ($keeporig,$src,$dst) = @_; if ($keeporig ? link $src, $dst @@ -444,22 +446,47 @@ sub rename_link_xf ($$$) { $@ = "$!"; 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; + if (!stat $src) { + $@ = f_ "stat source file: %S", $!; return 0; } - if (rename "$dst.tmp", $dst) { - return 1; + my @src_stat = (stat _)[0..1]; + + my @dst_stat; + if (stat $dst) { + @dst_stat = (stat _)[0..1]; + } elsif ($! == ENOENT) { } else { - $@ = f_ "finally install file after mv: %S", $!; + $@ = f_ "stat destination file: %S", $!; return 0; } + + if ("@src_stat" eq "@dst_stat") { + # (Symlinks to) the same file. No need for a copy but + # we may need to delete the original. + printdebug "rename_link_xf $keeporig $src $dst EXDEV but same\n"; + } else { + $!=0; $?=0; + my @cmd = (qw(cp --), $src, "$dst.tmp"); + debugcmd '+',@cmd; + if (system @cmd) { + failedcmd_report_cmd undef, @cmd; + $@ = failedcmd_waitstatus(); + $! = -1; + return 0; + } + if (!rename "$dst.tmp", $dst) { + $@ = f_ "finally install file after cp: %S", $!; + return 0; + } + } + if (!$keeporig) { + if (!unlink $src) { + $@ = f_ "delete old file after cp: %S", $!; + return 0; + } + } + return 1; } sub hashfile ($) { @@ -473,6 +500,15 @@ sub git_rev_parse ($) { return cmdoutput qw(git rev-parse), "$_[0]~0"; } +sub changedir_git_toplevel () { + my $toplevel = cmdoutput qw(git rev-parse --show-toplevel); + length $toplevel or fail __ < ($type, $data) or ('missing', undef)