summaryrefslogtreecommitdiffstats
path: root/base/rsync/rsync.driver
blob: 21fd54c453535ecbf4a2526d8d9e273b3833094d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/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 rsync://' . $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 --log-format "%o %n" rsync://' . $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