X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=Debian%2FDgit.pm;h=2ef32f32a8179f9dc590bfdbcf27419470a62f21;hb=4615f2d1c695caf9b04719f51d57dfae539bb712;hp=19ea85b6ebe887c36ead2c44a6d409a17e5bfee6;hpb=89906fd58100567b415f9c13d83121b988dfa325;p=dgit.git diff --git a/Debian/Dgit.pm b/Debian/Dgit.pm index 19ea85b6..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,19 +446,40 @@ sub rename_link_xf ($$$) { $@ = "$!"; return 0; } - $!=0; $?=0; - my @cmd = (qw(cp --), $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) { - $@ = f_ "finally install file after cp: %S", $!; + my @src_stat = (stat _)[0..1]; + + my @dst_stat; + if (stat $dst) { + @dst_stat = (stat _)[0..1]; + } elsif ($! == ENOENT) { + } else { + $@ = 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", $!; @@ -477,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)