Bump buildbot version to latest stable release 3.8.0
[buildbot.git] / scripts / sha2rsync.pl
1 #!/usr/bin/perl -w
2
3 # ./sha2rsync.pl <rlist> <llist> <torsync>
4
5 # <rlist> is the filename of sha256sums fetched from server
6 # <llist> is the filename of sha256sums generated locally
7 # <torsync> is the filename of the list of files to upload
8
9 # <rlist> and <llist> are files formatted as follows:
10 #checksum *pathtofile
11
12 # both files must be sorted based on pathtofile: the script performs
13 # in-place merge (O(n+m)) of both lists based on that assumption.
14 # <rlist> and <llist> are parsed only once.
15
16 # the script cannot currently handle any other type of input
17
18 # the script will generate <torsync>, a list of files suitable for
19 # using with "rsync --files-from=<torsync>"
20
21 # if <rlist> doesn't exist, all files in <llist> are added to the
22 # upload list.
23 # if <rlist> exists, the <llist> files are added if:
24 # - they're not present in <rlist>
25 # - they're present in <rlist> AND their checksums differ
26
27 # the script will clobber <torsync>
28
29 use strict;
30 use warnings;
31 use integer;
32
33 die ("wrong number of arguments!") if ($#ARGV+1 != 3);
34
35 my $shapat = qr/^(\w+) \*(.+)$/;
36
37 my $rlist = $ARGV[0];
38 my $llist = $ARGV[1];
39 my $torsync = $ARGV[2];
40
41 my $rlist_fh = undef;
42 my $llist_fh = undef;
43 my $torsync_fh = undef;
44
45 open($torsync_fh, ">", $torsync) or die("can't create output file!");
46 open($llist_fh, "<", $llist) or die("can't read local list!");
47 open($rlist_fh, "<", $rlist) or $rlist_fh = undef;
48
49 my $lline = readline($llist_fh);
50 my $rline = defined($rlist_fh) ? readline($rlist_fh) : undef;
51
52
53 MAINLOOP: while () {
54 # run this loop as long as we have content from both rlist and llist
55 last (MAINLOOP) unless (defined($lline) && defined($rline));
56
57 chomp($lline);
58 my ($lcsum, $lfname) = $lline =~ $shapat;
59
60 chomp($rline);
61 my ($rcsum, $rfname) = $rline =~ $shapat;
62
63 # compare current remote and local filenames
64 my $rtlcmp = ($rfname cmp $lfname);
65
66 while ($rtlcmp < 0) { # remote fname is before current local fname: remote file doesn't exist localy
67 $rline = readline($rlist_fh);
68 next (MAINLOOP);
69 }
70
71 while ($rtlcmp > 0) { # remote fname is after current local fname: local file doesn't exist remotely
72 add_file($lfname); # add lfname to upload list
73 $lline = readline($llist_fh);
74 next (MAINLOOP);
75 }
76
77 # if we end here, rtlcmp == 0: fnames matched, the file exist localy and remotely
78
79 # fetch next line of both streams for the next iteration
80 $lline = readline($llist_fh);
81 $rline = readline($rlist_fh);
82
83 # and skip if csums match
84 next (MAINLOOP) if ($lcsum eq $rcsum);
85
86 # otherwise add the file as it's different
87 add_file($lfname);
88 }
89
90 # deal with remainder of llist if any
91 while (defined($lline)) {
92 chomp($lline);
93 my ($lcsum, $lfname) = $lline =~ $shapat;
94 add_file($lfname);
95 $lline = readline($llist_fh);
96 }
97
98 # unconditionally add some mandatory files to rsynclist
99 # add them last so they're transferred last: if everything else transferred correctly
100 my @additional_files = qw(
101 packages/Packages.asc
102 packages/Packages.sig
103 sha256sums.asc
104 sha256sums.sig
105 sha256sums
106 );
107
108 (my $basedir = $llist) =~ s!/[^/]+$!!;
109
110 foreach my $file (@additional_files) {
111 if (-f "$basedir/$file") {
112 add_file($file);
113 }
114 }
115
116 exit (0);
117
118 sub add_file {
119 my $fname = shift;
120 print $torsync_fh "$fname\n";
121 }