core/rsync/rsync.driver

144 lines
3.0 KiB
Perl

#!/usr/bin/perl
#
# /etc/ports/drivers/rsync: rsync(1) driver script for ports(8)
#
use warnings;
use strict;
use File::Basename;
my $host = '';
my $collection = '';
my $destination = '';
my %new_checkouts;
my %old_checkouts;
sub error
{
my $message = shift;
print "Error: $message ($!)\nUpdating failed\n";
exit 1;
}
sub warning
{
my $message = shift;
print "Warning: $message ($!)\n";
}
if ($#ARGV < 0)
{
print "Usage: $0 <file>\n";
exit 1;
}
open(FILE, $ARGV[0]) or error("Couldn't open $ARGV[0]");
while (<FILE>)
{
chomp;
if (/^host=(.*)/) { $host = $1; }
elsif (/^collection=(.*)/) { $collection = $1; }
elsif (/^destination=(.*)/) { $destination = $1; }
}
close(FILE);
if ($host eq '') { error("Host field not set in $ARGV[0]"); }
if ($collection eq '') { error("Collection field not set in $ARGV[0]"); }
if ($destination eq '') { error("Destination field not set in $ARGV[0]"); }
if (-e "$destination/.checkouts")
{
# read the old .checkouts file into memory
open(FILE, "$destination/.checkouts") or error("Couldn't read checkouts from $destination/.checkouts");
while (<FILE>)
{
chomp;
$old_checkouts{$_} = 1;
}
close(FILE);
}
print "Updating file list from " . $host . "::$collection\n";
# get the remote file list (new .checkouts)
open(PIPE, 'rsync -crz --no-human-readable ' . $host . '::' . $collection . '|') or error("Couldn't open pipe to rsync");
while (<PIPE>)
{
chomp;
next if /^MOTD:/; # ignore MOTD lines
s/^(.{43})//; # ignore the first 43 characters (mode, date etc...)
next if /^.$/; # ignore the . directory
$new_checkouts{$_} = 1;
}
close(PIPE);
error("Running rsync failed") unless $? == 0;
print "Updating collection " . basename($destination) . "\n";
# now really run rsync
open(PIPE, 'rsync -crz --no-human-readable --log-format "%o %n" ' . $host . "::$collection $destination|") or error("Couldn't open pipe to rsync");
while (<PIPE>)
{
chomp;
if (/^recv (.*)/)
{
if ($old_checkouts{$1})
{
s/^recv/ Edit/;
}
else
{
s/^recv/ Checkout/;
}
}
print $_ . "\n";
}
close(PIPE);
error("Running rsync failed") unless $? == 0;
# save new checkouts into .checkouts
open(FILE, ">$destination/.checkouts") or error("Couldn't save checkouts to $destination/.checkouts");
foreach my $checkout (sort keys %new_checkouts)
{
print FILE "$checkout\n";
}
close(FILE);
# use chroot as an additional safety measure when removing files
chroot($destination) or error("Couldn't chroot into $destination");
chdir('/');
# iterate through old checkouts, remove obsolete files
foreach my $checkout (sort keys %old_checkouts)
{
if (!$new_checkouts{$checkout})
{
if (-f $checkout)
{
print " Delete $checkout\n";
unlink($checkout) or warning("Couldn't delete $checkout");
}
}
}
# iterate through old checkouts, remove obsolete directories
foreach my $checkout (sort keys %old_checkouts)
{
if (!$new_checkouts{$checkout})
{
if (-d $checkout)
{
print " Delete $checkout\n";
rmdir($checkout) or warning("Couldn't delete $checkout");
}
}
}
print "Finished successfully\n";
# End of file