App-powerdiff
view release on metacpan or search on metacpan
script/powerdiff view on Meta::CPAN
my %seendir = (q{.} => 1);
for my $path (@REGULAR) {
while ($path =~ m{\A(.*\G[^/]+)/}xmsg) {
next if $seendir{$1}++;
mkdir "$dir4diff/old/$1" or die "mkdir: $!";
mkdir "$dir4diff/new/$1" or die "mkdir: $!";
}
if (-f "$dir1/$path" && ! -l "$dir1/$path") {
symlink "$dir1/$path", "$dir4diff/old/$path" or die "symlink: $!";
}
if (-f "$dir2/$path" && ! -l "$dir2/$path") {
symlink "$dir2/$path", "$dir4diff/new/$path" or die "symlink: $!";
}
}
my $patch = `cd \Q$dir4diff\E; LANG= diff -uNr old new`;
while ($patch =~ s/^([^d@\\ +-][^\n]*)\n//ms) {
my $msg = $1;
if ($msg =~ /\bFiles old\/[^\n]* and new(\/[^\n]*) differ\z/ims) {
push @TAR, $1;
}
else {
warn "WARNING: $msg\n";
}
}
for my $ext (qw( pre.sh post.sh patch tgz )) {
unlink "$output.$ext";
}
if (@SH_PRE) {
output("$output.pre.sh", join q{}, map {"$_\n"} '#!/bin/sh', @SH_PRE);
}
if (@SH_POST) {
output("$output.post.sh", join q{}, map {"$_\n"} '#!/bin/sh', @SH_POST);
}
if ($patch ne q{}) {
output("$output.patch", $patch);
}
if (@TAR) {
my $TAR = (grep {-x "$_/gtar"} split /:/ms, $ENV{PATH}) ? 'gtar' : 'tar';
system $TAR, 'czf', "$output.tgz", '-C', $dir2, map { substr $_, 1 } @TAR;
}
return;
}
sub output {
my ($file, $data) = @_;
open my $f, '>', $file or die "open $file: $!";
print {$f} $data;
close $f or die "close: $!";
return;
}
sub change_mode {
my ($dir, $name, $m1, $m2) = @_;
my $pathname = quote_path("$dir/$name");
if (($m1 & PERM_ALL) != ($m2 & PERM_ALL)) {
my $prev = sprintf '%04o', $m1 & PERM_ALL;
my $perms = sprintf '%04o', $m2 & PERM_ALL; # TODO use text form?
my $m = $m2 & ~PERM_ALL;
if ($m == MODE_DIR) {
push @SH_POST, "chmod $perms $pathname/ # was $prev";
}
elsif ($m == MODE_FIFO || $m == MODE_REG) {
push @SH_POST, "chmod $perms $pathname # was $prev";
}
}
return;
}
sub add {
my ($dir, $name, $n) = @_;
my $pathname = quote_path("$dir/$name");
my $m = $n->{mode} & ~PERM_ALL;
warn "add: $dir/$name mode=$m\n";
if ($m == MODE_DIR) {
push @SH_PRE, "mkdir $pathname/";
diff_dir("$dir/$name", {}, $n->{dir});
}
elsif ($m == MODE_FIFO) {
push @SH_PRE, "mkfifo $pathname";
}
elsif ($m == MODE_LINK) {
my $to = quote_path($n->{link});
push @SH_PRE, "ln -s $to $pathname";
}
elsif ($m == MODE_REG) {
if ($n->{size} == 0) {
push @SH_PRE, "touch $pathname";
}
else {
push @REGULAR, "$dir/$name";
}
}
# WARNING if different systems has different umask setting this may
# result in different permissions after applying patch
# WARNING change_mode() will be called even for ignored file types
change_mode($dir, $name, $m == MODE_DIR ? PERM_DIR : PERM_FILE, $n->{mode});
# ignored: MODE_BLK, MODE_CHR, MODE_SOCK
return;
}
sub del {
my ($dir, $name, $n) = @_;
my $pathname = quote_path("$dir/$name");
my $m = $n->{mode} & ~PERM_ALL;
if ($m == MODE_DIR) {
push @SH_PRE, "rm -rf $pathname/";
}
elsif ($m == MODE_LINK || $m == MODE_FIFO || $m == MODE_REG) {
push @SH_PRE, "rm -f $pathname";
}
# ignored: MODE_BLK, MODE_CHR, MODE_SOCK
return;
}
sub mod {
my ($dir, $name, $n1, $n2) = @_;
my $pathname = quote_path("$dir/$name");
my $m = $n1->{mode} & ~PERM_ALL;
if ($m == MODE_DIR) {
diff_dir("$dir/$name", $n1->{dir}, $n2->{dir});
}
elsif ($m == MODE_LINK) {
if ($n1->{link} ne $n2->{link}) {
( run in 0.528 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )