Adapt to mock-1.4.1-1.fc25
[Fedora-Rebuild.git] / bin / rebuildedit
blob7be30d4d1ea009b3a77d5e77f7a034a51f675c50
1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4 use Carp;
5 use Config::Tiny;
6 use Getopt::Long;
7 use Fedora::Rebuild::Set::Package;
8 use Fedora::Rebuild::Package;
9 use Fedora::Rebuild::Package::Config;
10 use Fedora::Rebuild::Scheduler;
11 use Fedora::Rebuild::Package::ListLog;
12 use Fcntl;
13 use File::Spec;
14 use File::Temp;
16 =encoding utf8
18 =head1 NAME
20 rebuildedit - Mass edit source repositories
22 =head1 SYNOPIS
24 rebuildedit [--config FILE]
26 =head1 DESCRIPTION
28 This tool clones source repositories for all packages sepcified in I<all>
29 list, executes an I<editor> command there and if the repository is changed,
30 commits and pushed the changes back to the server.
32 Packages without changes or successfully changed ones will be logged into
33 I<done> list. Packages that encountered an error will be logged into <failed>
34 list.
36 The I<editor> is a list consisting of command name folloed by optional
37 positional arguments. When executing the editor command, a spec file will be
38 appended as a last argument. The editor will be executed in the git repository
39 directory.
41 =cut
43 my $cfgfile = File::Spec->catfile($ENV{HOME}, '.rebuildperlrc');
44 my %config = (
45 all => undef,
46 done => undef,
47 failed => undef,
48 workdir => undef,
49 repodir => undef,
50 pyrpkg => 'fedpkg',
51 mode => 'koji',
52 anonymous => 0,
53 dist => undef,
54 loadthreads => 1,
55 target => '',
56 message => '',
57 editor => undef,
60 =head1 OPTIONS
62 =head2 --config I<FILE>
64 Read configuration from I<FILE>, or F<~/.rebuildperlrc> if not specified.
66 =head1 FILES
68 =head2 F<~/.rebuildperlrc>
70 Configuration is in L<Config::Tiny> format. Following options are needed:
72 done = done
73 failed = failed
74 workdir = workdir
75 dist = rawhide
76 editor = [ 'program', 'argument' ]
77 message = A commit mesage
79 Additional possible options:
81 mode => koji
82 anonymous => 0
83 loadthreads = 1
85 =cut
88 GetOptions(
89 'config=s' => \$cfgfile,
90 ) or die "Could not parse program options\n";
92 # Load configuration
93 if (-f $cfgfile) {
94 my $cfg = Config::Tiny->new->read($cfgfile);
95 if (! defined $cfg) {
96 print STDERR "Could not parse `" . $cfgfile .
97 "' configuration file: " . $Config::Tiny::errstr . "\n";
98 exit 1;
100 foreach (keys %{$cfg->{_}}) {
101 $config{$_} = $cfg->{_}->{$_};
102 $config{$_} = eval $config{$_} if $_ eq 'editor';
106 # Load list of packages
107 sub load_list {
108 my ($file_name) = @_;
109 my $packages = Fedora::Rebuild::Set::Package->new();
110 my $file;
112 if (not -e $file_name) {
113 return $packages;
116 open($file, '<', $file_name) or
117 croak "Could not open `" . $file_name . "': $!";
118 while (local $_ = <$file>) {
119 chomp;
120 if (m/^\s*$/) { next; }
121 if ($packages->contains($_)) {
122 warn "Duplicate name `$_'.\n";
123 next;
126 my $package = Fedora::Rebuild::Package->new(name => $_,
127 workdir => $config{workdir}, dist => $config{dist},
128 pkgdist => $config{pkgdist}, target => $config{target},
129 message => $config{message});
130 $packages->insert($package);
132 if ($!) {
133 croak "Could not read list of package names from file `" .
134 $file_name . "': $!";
136 close $file;
138 return $packages;
141 # Build config
143 my $build_config = Fedora::Rebuild::Package::Config->new(
144 mode => $config{mode},
145 pyrpkg => $config{pyrpkg},
146 koji => 'koji',
147 repositories => [],
148 architecture => 'x86_64',
149 mock_install_packages => '',
153 # Load package lists
154 print "Loading list of all package names...\n";
155 my $packages = load_list($config{all});
156 print "Number of all packages: " . $packages->size() . "\n";
158 print "Loading list of done package names...\n";
159 my $done = load_list($config{done});
160 print "Number of done packages: " . $done->size() . "\n";
162 print "Loading list of failed package names...\n";
163 my $failed = load_list($config{failed});
164 print "Number of failed packages: " . $failed->size() . "\n";
166 # Strip done and failed packages
167 for ($done->packages, $failed->packages) {
168 $packages->delete($_);
171 # Process packages
172 my $scheduler = Fedora::Rebuild::Scheduler->new(
173 limit => $config{loadthreads},
174 name => 'Editing repository',
175 total => $packages->size
177 my %jobs = ();
178 my $i = 0;
180 for my $package ($packages->packages) {
181 my $job = $scheduler->schedule($package->can('cloneeditpush'), $package,
182 $build_config, $config{anonymous}, $config{editor});
183 if (! defined $job) {
184 next;
186 $jobs{$job} = $package;
187 my %finished = $scheduler->finish(++$i < $packages->size);
189 while (my ($job, $status) = each %finished) {
190 my $package = $jobs{$job};
192 if (!$$status[0]) {
193 print "Could not edit repository for package `",
194 $package->name, "'.\n";
195 Fedora::Rebuild::Package::ListLog->new(
196 file => $config{failed})->log($package);
197 } else {
198 Fedora::Rebuild::Package::ListLog->new(
199 file => $config{done})->log($package);
204 print "Done.\n";
205 exit 0;