Dev-Util

 view release on metacpan or  search on metacpan

lib/Dev/Util/Backup.pm  view on Meta::CPAN

package Dev::Util::Backup;

use Dev::Util::Syntax;
use Exporter qw(import);

use File::Copy;
use File::Spec;
use File::Basename;
use File::Find;
use IO::File;
use Archive::Tar;

our $VERSION = version->declare("v2.19.42");

our @EXPORT_OK = qw(
    backup
);

our %EXPORT_TAGS = ( all => \@EXPORT_OK );

#where to save backup files
our $BACKUPDIR = '';

#should we preserve atime, mtime, and mode of the original
#file in all backups ?
our $PRESERVE_FILE_ATTRS = 1;

# Backup file or directory
sub backup {
    return -f $_[0] ? _backupfile(@_) : _backupdir(@_);
}

# Backup file -- takes file name and returns new file name
# This sub can DIE -- so use eval
sub _backupfile {
    my $filename = shift;

    croak "$filename is not a file\n" unless ( -e $filename );

    #backup file will have _yyyymmdd extention added to it
    my $newfile = _backup($filename);

    #preserve mode, atime, and utime of old file
    if ($PRESERVE_FILE_ATTRS) {
        my @stat = stat $filename;

        utime( $stat[8], $stat[9], $newfile );
        chmod $stat[2], $newfile;

        #preserve ownership if possible
        chown $stat[4], $stat[5], $newfile
            if ( $REAL_USER_ID == 0 || $REAL_USER_ID == $stat[4] );
    }

    return $newfile;
}

# Backup directory -- takes file name, optional compression level (2-9) and
#                     returns new archive file name
# This sub can DIE -- so use eval
sub _backupdir {
    my ( $dir, $level ) = @_;

    $level = 5 if ( !defined($level) || $level < 2 || $level > 9 );

    croak "$dir is not a directory\n" unless ( -d $dir );

    my @files;
    my $tar = Archive::Tar->new();

    # "promote" warnings from File::Find to errors
    local $SIG{ __WARN__ } = sub { croak $_[0] };

    #recursivelly add files to tar
    find(
           {  wanted   => sub { push( @files, $_ ) },
              no_chdir => 1
           },
           $dir
        );

    #save archive

    my $tmpout = IO::File->new_tmpfile() || croak "Failed to create tmpfile\n";
    binmode($tmpout);

    $tar->add_files(@files);
    $tar->write( $tmpout, $level );

    #backup file will have _yyyymmdd extention added to it
    return _backup( $dir, $tmpout );
}

# Perform file backup if necessary
# Arguments: $filename -- file/dir to backup
# Returns backup file name
sub _backup {
    my ( $filename, $fh ) = @_;

    my $input = $fh ? $fh : $filename;

    $filename =~ s/\/$//;    #remove trailing slash from paths

    my $ext   = -d $filename ? ".tar.gz" : "";
    my $mtime = ( stat $filename )[9];
    my ( $mday, $mon, $year ) = ( localtime($mtime) )[ 3 .. 5 ];

    if ( $BACKUPDIR ne '' ) {

        #backup in BUDIR directory relative to dirname
        my ( $name, $path ) = fileparse($filename);



( run in 2.847 seconds using v1.01-cache-2.11-cpan-71847e10f99 )