Brackup
view release on metacpan or search on metacpan
lib/Brackup/Backup.pm view on Meta::CPAN
$pc->forget_chunkref;
}
}
warn "kb need to upload = $n_kb_up_need\n";
$stats->timestamp('Calc Needed');
}
my $chunk_iterator = Brackup::ChunkIterator->new(@files);
undef @files;
$stats->timestamp('Chunk Iterator');
my $gpg_iter;
my $gpg_pm; # gpg ProcessManager
if (@gpg_rcpts) {
($chunk_iterator, $gpg_iter) = $chunk_iterator->mux_into(2);
$gpg_pm = Brackup::GPGProcManager->new($gpg_iter, $target);
}
# begin temp backup_file
my ($metafh, $meta_filename);
unless ($self->{dryrun}) {
($metafh, $meta_filename) = tempfile(
'.' . basename($backup_file) . 'XXXXX',
DIR => dirname($backup_file),
);
if (! @gpg_rcpts) {
if (eval { require IO::Compress::Gzip }) {
close $metafh;
$metafh = IO::Compress::Gzip->new($meta_filename)
or die "Cannot open tempfile with IO::Compress::Gzip: $IO::Compress::Gzip::GzipError";
}
}
print $metafh $self->backup_header;
}
my $cur_file; # current (last seen) file
my @stored_chunks;
my $file_has_shown_status = 0;
my $merge_under = $root->merge_files_under;
my $comp_chunk = undef;
my $end_file = sub {
return unless $cur_file;
if ($merge_under && $comp_chunk) {
# defer recording to backup_file until CompositeChunk finalization
$self->add_unflushed_file($cur_file, [ @stored_chunks ]);
}
else {
print $metafh $cur_file->as_rfc822([ @stored_chunks ], $self) if $metafh;
}
$self->add_saved_file($cur_file, [ @stored_chunks ]) if $self->{savefiles};
$n_files_done++;
$n_kb_done += $cur_file->size / 1024;
$cur_file = undef;
};
my $show_status = sub {
# use either size of files in normal case, or if we pre-calculated
# the size-to-upload (by looking in inventory, then we'll show the
# more accurate percentage)
my $percdone = 100 * ($n_kb_up_need ?
($n_kb_up / $n_kb_up_need) :
($n_kb_done / $n_kb));
my $mb_remain = ($n_kb_up_need ?
($n_kb_up_need - $n_kb_up) :
($n_kb - $n_kb_done)) / 1024;
$self->debug(sprintf("* %-60s %d/%d (%0.02f%%; remain: %0.01f MB)",
$cur_file->path, $n_files_done, $n_files, $percdone,
$mb_remain));
$self->report_progress($percdone);
};
my $start_file = sub {
$end_file->();
$cur_file = shift;
@stored_chunks = ();
$show_status->() if $cur_file->is_dir;
if ($gpg_iter) {
# catch our gpg iterator up. we want it to be ahead of us,
# nothing iteresting is behind us.
$gpg_iter->next while $gpg_iter->behind_by > 1;
}
$file_has_shown_status = 0;
};
# records are either Brackup::File (for symlinks, directories, etc), or
# PositionedChunks, in which case the file can asked of the chunk
while (my $rec = $chunk_iterator->next) {
if ($rec->isa("Brackup::File")) {
$start_file->($rec);
next;
}
my $pchunk = $rec;
if ($pchunk->file != $cur_file) {
$start_file->($pchunk->file);
}
# have we already stored this chunk before? (iterative backup)
my $schunk;
if ($schunk = $target->stored_chunk_from_inventory($pchunk)) {
$pchunk->forget_chunkref;
push @stored_chunks, $schunk;
next;
}
# weird case... have we stored this same pchunk digest in the
# current comp_chunk we're building? these aren't caught by
# the above inventory check, because chunks in a composite
# chunk aren't added to the inventory until after the the composite
# chunk has fully grown (because it's not until it's fully grown
# that we know the handle for it, its digest)
if ($comp_chunk && ($schunk = $comp_chunk->stored_chunk_from_dup_internal_raw($pchunk))) {
$pchunk->forget_chunkref;
push @stored_chunks, $schunk;
next;
}
unless ($file_has_shown_status++) {
$show_status->();
lib/Brackup/Backup.pm view on Meta::CPAN
die "Bogus header value from driver" if $val =~ /[\r\n]/;
$ret .= "Driver-$k: $val\n";
}
}
$ret .= "RootName: " . $self->{root}->name . "\n";
$ret .= "RootPath: " . $self->{root}->path . "\n";
$ret .= "TargetName: " . $self->{target}->name . "\n";
$ret .= "DefaultFileMode: " . $self->default_file_mode . "\n";
$ret .= "DefaultDirMode: " . $self->default_directory_mode . "\n";
$ret .= "DefaultUID: " . $self->default_uid . "\n";
$ret .= "DefaultGID: " . $self->default_gid . "\n";
$ret .= "UIDMap: " . $self->uid_map . "\n";
$ret .= "GIDMap: " . $self->gid_map . "\n";
$ret .= "GPG-Recipient: $_\n" for $self->{root}->gpg_rcpts;
$ret .= "\n";
return $ret;
}
sub record_mode_ids {
my ($self, $file) = @_;
$self->{modecounts}{$file->type}{$file->mode}++;
$self->{idcounts}{u}{$file->uid}++;
$self->{idcounts}{g}{$file->gid}++;
}
sub add_unflushed_file {
my ($self, $file, $handlelist) = @_;
push @{ $self->{unflushed_files} }, [ $file, $handlelist ];
}
sub flush_files {
my ($self, $fh) = @_;
while (my $rec = shift @{ $self->{unflushed_files} }) {
next unless $fh;
my ($file, $stored_chunks) = @$rec;
print $fh $file->as_rfc822($stored_chunks, $self);
}
}
sub add_saved_file {
my ($self, $file, $handlelist) = @_;
push @{ $self->{saved_files} }, [ $file, $handlelist ];
}
sub foreach_saved_file {
my ($self, $cb) = @_;
foreach my $rec (@{ $self->{saved_files} }) {
$cb->(@$rec); # Brackup::File, arrayref of Brackup::StoredChunk
}
}
sub debug {
my ($self, @m) = @_;
return unless $self->{verbose};
my $line = join("", @m);
chomp $line;
print $line, "\n";
}
sub report_progress {
my ($self, $percent, $message) = @_;
if ($self->{zenityprogress}) {
if (defined($message) && length($message) > 100) {
$message = substr($message, 0, 100)."...";
}
print STDOUT "#", $message, "\n" if defined $message;
print STDOUT $percent, "\n" if defined $percent;
}
}
1;
( run in 2.180 seconds using v1.01-cache-2.11-cpan-5735350b133 )