#!/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 \n"; exit 1; } open(FILE, $ARGV[0]) or error("Couldn't open $ARGV[0]"); while () { 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 () { 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 ' . $host . '::' . $collection . '|') or error("Couldn't open pipe to rsync"); while () { 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 --log-format "%o %n" ' . $host . "::$collection $destination|") or error("Couldn't open pipe to rsync"); while () { 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