7 use Fedora
::Rebuild
::Set
::Package
;
8 use Fedora
::Rebuild
::Package
;
9 use Fedora
::Rebuild
::Scheduler
;
10 use Fedora
::Rebuild
::Package
::ListLog
;
19 rebuildreset - Reset package for rebuild
23 rebuilreset [--config FILE] [--changed] < PACKAGE_LIST
27 This tool resets packages listed on standard input or in a file named in
28 positional arguments, so that next L<rebuildperl(1)> will consider the
29 packages as not yet rebuilt.
31 This is a helper for L<rebuildperl(1)> and it assumes the packages have
32 already been populated by rebuildperl. It will reset the local repository and
33 removes all stage locks except I<.clone>. It will also edit I<all>, I<done>,
34 and I<failed> package lists (see the configuration) accordingly. (It will
35 remove changed packaged from done and failed list.)
37 With other options, the set of packages to reset can be reduced more.
41 my $cfgfile = File
::Spec
->catfile($ENV{HOME
}, '.rebuildperlrc');
57 =head2 --config I<FILE>
59 Read configuration from I<FILE>, or F<~/.rebuildperlrc> if not specified.
63 Reset only packages whose remote repository has changed (e.g. there is a newer
64 version). It compares local copy of I<origin> GIT repository with repository
65 on the remote server and if it finds the HEADs are different it will reset the
66 package. Otherwise the package will not be reset.
68 If I<failedtemp> configuration option is defined and there is an error while
69 checking the remote repository, the faulting package will be logged into
70 the I<failedtemp> file. This is because talking to a GIT server can result
71 into intermittent network error that can disappear on next retry.
75 =head2 F<~/.rebuildperlrc>
77 Configuration is in L<Config::Tiny> format. Following options are needed:
81 failedtemp = failedtemp
88 # Copy file permissions and ownership from source file handle to target file
89 # handle. Croaks on error.
90 sub copy_file_attributes
{
91 my ($source_handle, $source_name, $target_handle, $target_name) = @_;
92 my @source_meta = stat($source_handle) or
93 croak
"Could not retrieve `$source_name' meta-data: $!";
94 if (defined $source_meta[2]) {
95 chmod($source_meta[2], $target_handle) or
96 croak
"Could not change `$target_name' permissions: $!";
98 if (defined $source_meta[4] and defined $source_meta[5]) {
99 chown($source_meta[4], $source_meta[5], $target_name) or
100 croak
"Could not change `$target_name' ownership: $!";
104 # Remove listed packages from file.
106 my ($file_name, $packages) = @_;
108 print "Strippig packages from file `$file_name'...\n";
111 # Write mode for exclusive lock
112 open($file, '+<', $file_name) or
113 croak
"Could not open `$file_name': $!";
114 flock($file, Fcntl
::LOCK_EX
) or
115 croak
"Could not lock `$file_name' file: $!";
118 my ($new_file, $new_file_name) =
119 File
::Temp
::tempfile
($file_name . 'XXXXXX', UNLINK
=> 0, EXLOCK
=> 1);
120 copy_file_attributes
($file, $file_name, $new_file, $new_file_name);
122 # Filter input file into output file
123 while (local $_ = <$file>) {
125 if (m/^\s*$/) { next; }
126 if ($packages->contains($_)) { next; }
127 print $new_file "$_\n" or
128 croak
"Could not write into temporary file `$new_file_name' :$!";
131 croak
"Could not read list of package names fromfile `$file_name' :$!";
134 # Finish writing and replace the the files
135 $new_file->flush && $new_file->sync or
136 croak
"Could not flush temporary file `$new_file_name': $!";
137 rename $new_file_name, $file_name or
138 croak
"Could not replace file `$file_name' with stripped " .
139 "`$new_file_name': $!";
141 croak
"Could not close `$file_name': $!";
143 # This unlocks input file.
146 print "Strippig packages from file `$file_name' finished successfully.\n";
151 'config=s' => \
$cfgfile,
152 'changed' => \
$changed_only
153 ) or die "Could not parse program options\n";
157 my $cfg = Config
::Tiny
->new->read($cfgfile);
158 if (! defined $cfg) {
159 print STDERR
"Could not parse `" . $cfgfile .
160 "' configuration file: " . $Config::Tiny
::errstr
. "\n";
163 foreach (keys %{$cfg->{_
}}) {
164 $config{$_} = $cfg->{_
}->{$_};
165 $config{$_} = eval $config{$_} if $_ eq 'buildrequiresfilter';
169 # Load list of packages to synchronize
170 my $packages = Fedora
::Rebuild
::Set
::Package
->new();
171 print "Loading list of package names...\n";
172 while (local $_ = <>) {
174 if (m/^\s*$/) { next; }
175 if ($packages->contains($_)) { next; }
176 my $package = Fedora
::Rebuild
::Package
->new(name
=> $_,
177 workdir
=> $config{workdir
}, dist
=> $config{dist
},
178 pkgdist
=> $config{pkgdist
}, target
=> $config{target
},
179 message
=> $config{message
});
180 $packages->insert($package);
183 croak
"Could not read list of package names: $!";
185 print "Number of packages: " . $packages->size() . "\n";
188 my $changed_packages = Fedora
::Rebuild
::Set
::Package
->new();
189 my $temporary_error = 0;
192 my $scheduler = Fedora
::Rebuild
::Scheduler
->new(
193 limit
=> $config{loadthreads
},
194 name
=> ($changed_only) ?
195 'Checking remote repository' : 'Reseting repository',
196 total
=> $packages->size
201 for my $package ($packages->packages) {
202 my $job = $scheduler->schedule($package->can(
203 ($changed_only) ?
'reset_remotly_updated' : 'reset'
205 if (! defined $job) {
208 $jobs{$job} = $package;
209 my %finished = $scheduler->finish(++$i < $packages->size);
211 while (my ($job, $status) = each %finished) {
212 my $package = $jobs{$job};
216 print "Could not check remote repository for package `",
217 $package->name, "'.\n";
219 if (defined $config{failedtemp
}) {
220 Fedora
::Rebuild
::Package
::ListLog
->new(
221 file
=> $config{failedtemp
})->log($package);
223 print "Waiting for finishing scheduled jobs...\n";
224 $scheduler->finish(1);
225 print "All jobs have finished.\n";
226 croak
"Could not check all packages for remote changes.\n";
228 } elsif (2 == $$status[0]) {
229 print "`", $package->name,
230 "' has been remotely changed and locally reset.\n";
231 $changed_packages->insert($package);
235 print "Could not reset package `", $package->name, "'.\n";
236 print "Waiting for finishing scheduled jobs...\n";
237 $scheduler->finish(1);
238 print "All jobs have finished.\n";
239 croak
"Could not reset all specified packages.\n";
241 $changed_packages->insert($package);
246 if ($changed_packages->size > 0) {
247 print "Following packages have been locally reset (",
248 $changed_packages->size, "): ", $changed_packages->string, "\n";
249 edit_file
($config{done
}, $changed_packages);
250 edit_file
($config{failed
}, $changed_packages);
252 print "None package has been reset.\n";
255 if ($temporary_error) {