[debhelper-devel] [debhelper] 01/02: Dh_Lib: Add restore_file_on_clean
Niels Thykier
nthykier at moszumanska.debian.org
Sun Jan 10 10:54:22 UTC 2016
This is an automated email from the git hooks/post-receive script.
nthykier pushed a commit to branch master
in repository debhelper.
commit 1566865e67d2712c45462794cc29d89f75c011d1
Author: Niels Thykier <niels at thykier.net>
Date: Sun Jan 10 10:19:29 2016 +0000
Dh_Lib: Add restore_file_on_clean
Signed-off-by: Niels Thykier <niels at thykier.net>
---
Debian/Debhelper/Dh_Lib.pm | 78 ++++++++++++++++++++++++++++++++++++++++++++++
dh_clean | 10 ++++--
doc/PROGRAMMING | 9 ++++++
3 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/Debian/Debhelper/Dh_Lib.pm b/Debian/Debhelper/Dh_Lib.pm
index 3d846b6..da20b76 100644
--- a/Debian/Debhelper/Dh_Lib.pm
+++ b/Debian/Debhelper/Dh_Lib.pm
@@ -35,6 +35,7 @@ use vars qw(@EXPORT %dh);
&install_file &install_prog &install_lib &install_dir
&get_source_date_epoch &is_cross_compiling
&generated_file &autotrigger &package_section
+ &restore_file_on_clean &restore_all_files
);
my $max_compat=10;
@@ -1322,6 +1323,83 @@ sub install_dh_config_file {
return 1;
}
+sub restore_file_on_clean {
+ my ($file) = @_;
+ my $bucket_index = 'debian/.debhelper/bucket/index';
+ my $bucket_dir = 'debian/.debhelper/bucket/files';
+ my $checksum;
+ if (not -d $bucket_dir) {
+ install_dir($bucket_dir);
+ }
+ if ($file =~ m{^/}) {
+ error("restore_file_on_clean requires a path relative to the package dir");
+ }
+ $file =~ s{^\./}{}g;
+ $file =~ s{//++}{}g;
+ if ($file =~ m{^\.} or $file =~ m{/CVS/} or $file =~ m{/\.svn/}) {
+ # We do not want to smash a Vcs repository by accident.
+ warning("Attempt to store $file, which looks like a VCS file or");
+ warning("a hidden package file (like quilt's \".pc\" directory");
+ error("This tool probably contains a bug.");
+ }
+ if (-l $file or not -f _) {
+ error("Cannot store $file, which is a non-file (incl. a symlink)");
+ }
+ require Digest::SHA;
+
+ $checksum = Digest::SHA->new('256')->addfile($file, 'b')->hexdigest;
+
+ if (not $dh{NO_ACT}) {
+ my ($in_index);
+ open(my $fd, '+>>', $bucket_index)
+ or error("open($bucket_index, a+) failed: $!");
+ seek($fd, 0, 0);
+ while (my $line = <$fd>) {
+ my ($cs, $stored_file);
+ chomp($line);
+ ($cs, $stored_file) = split(m/ /, $line, 2);
+ next if ($stored_file ne $file);
+ $in_index = 1;
+ }
+ if (not $in_index) {
+ # Copy and then rename so we always have the full copy of
+ # the file in the correct place (if any at all).
+ doit('cp', '-an', '--reflink=auto', $file, "${bucket_dir}/${checksum}.tmp");
+ doit('mv', '-f', "${bucket_dir}/${checksum}.tmp", "${bucket_dir}/${checksum}");
+ print {$fd} "${checksum} ${file}\n";
+ }
+ close($fd) or error("close($bucket_index) failed: $!");
+ }
+
+ return 1;
+}
+
+sub restore_all_files {
+ my $bucket_index = 'debian/.debhelper/bucket/index';
+ my $bucket_dir = 'debian/.debhelper/bucket/files';
+
+ return if not -f $bucket_index;
+ open(my $fd, '<', $bucket_index)
+ or error("open($bucket_index) failed: $!");
+
+ while (my $line = <$fd>) {
+ my ($cs, $stored_file, $bucket_file);
+ chomp($line);
+ ($cs, $stored_file) = split(m/ /, $line, 2);
+ $bucket_file = "${bucket_dir}/${cs}";
+ # Restore by copy and then rename. This ensures that:
+ # 1) If dh_clean is interrupted, we can always do a full restore again
+ # (otherwise, we would be missing some of the files and have to handle
+ # that with scary warnings)
+ # 2) The file is always fully restored or in its "pre-restore" state.
+ doit('cp', '-an', '--reflink=auto', $bucket_file, "${bucket_file}.tmp");
+ doit('mv', '-Tf', "${bucket_file}.tmp", $stored_file);
+ }
+ close($fd);
+ return;
+}
+
+
1
# Local Variables:
diff --git a/dh_clean b/dh_clean
index 666766d..f5fc8ad 100755
--- a/dh_clean
+++ b/dh_clean
@@ -113,8 +113,14 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
unless excludefile($tmp);
}
-# Remove internal state data
-doit('rm', '-rf', 'debian/.debhelper/') if not $dh{D_FLAG};
+
+if (not $dh{D_FLAG}) {
+ # Restore all files in our bucket (before we delete said bucket)
+ restore_all_files();
+
+ # Remove internal state data
+ doit('rm', '-rf', 'debian/.debhelper/');
+}
# Remove all debhelper logs.
diff --git a/doc/PROGRAMMING b/doc/PROGRAMMING
index e5b9a72..1f03bdf 100644
--- a/doc/PROGRAMMING
+++ b/doc/PROGRAMMING
@@ -290,6 +290,15 @@ load_log($package, $hashref)
write_log($cmd, $package ...)
Writes the log files for the specified package(s), adding
the cmd to the end.
+restore_file_on_clean($file)
+ Store a copy of $file, which will be restored by dh_clean.
+ The $file *must* be a relative path to the package root and
+ *must* be a real regular file. Dirs, devices and symlinks
+ (and everything else) *cannot* be restored by this.
+ If $file is passed multiple times (e.g. from different programs)
+ only the first version is stored.
+ CAVEAT: This *cannot* undo arbitrary "rm -fr"'ing. The dir,
+ which is/was in $file, must be present when dh_clean is called.
make_symlink($src, $dest, $tmp)
Creates a Policy compliant sytem link called $dest pointing to
$src. If $tmp is given, then $tmp will be prefixed to $dest when
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debhelper/debhelper.git
More information about the debhelper-devel
mailing list