line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Arepa::Builder::Sbuild; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
27
|
|
4
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
21
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
995
|
use English qw(-no_match_vars); |
|
1
|
|
|
|
|
4489
|
|
|
1
|
|
|
|
|
5
|
|
7
|
1
|
|
|
1
|
|
436
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
72
|
|
8
|
1
|
|
|
1
|
|
5
|
use Cwd; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
60
|
|
9
|
1
|
|
|
1
|
|
753
|
use File::chmod; |
|
1
|
|
|
|
|
3497
|
|
|
1
|
|
|
|
|
102
|
|
10
|
1
|
|
|
1
|
|
1273
|
use File::Temp; |
|
1
|
|
|
|
|
30409
|
|
|
1
|
|
|
|
|
90
|
|
11
|
1
|
|
|
1
|
|
10
|
use File::Basename; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
87
|
|
12
|
1
|
|
|
1
|
|
6
|
use File::Path; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
46
|
|
13
|
1
|
|
|
1
|
|
6
|
use File::Find; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
55
|
|
14
|
1
|
|
|
1
|
|
1094
|
use File::Copy; |
|
1
|
|
|
|
|
2890
|
|
|
1
|
|
|
|
|
57
|
|
15
|
1
|
|
|
1
|
|
820
|
use Config::Tiny; |
|
1
|
|
|
|
|
1119
|
|
|
1
|
|
|
|
|
33
|
|
16
|
1
|
|
|
1
|
|
652
|
use YAML::Syck; |
|
1
|
|
|
|
|
1942
|
|
|
1
|
|
|
|
|
61
|
|
17
|
|
|
|
|
|
|
|
18
|
1
|
|
|
1
|
|
527
|
use Arepa; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
29
|
|
19
|
|
|
|
|
|
|
|
20
|
1
|
|
|
1
|
|
5
|
use base qw(Arepa::Builder); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
551
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $schroot_config = undef; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub _get_schroot_conf { |
25
|
0
|
|
|
0
|
|
0
|
my ($self) = @_; |
26
|
|
|
|
|
|
|
|
27
|
0
|
0
|
|
|
|
0
|
if (!defined $schroot_config) { |
28
|
0
|
|
|
|
|
0
|
my $content = ""; |
29
|
0
|
|
|
|
|
0
|
for my $path ('/etc/schroot/schroot.conf', glob('/etc/schroot/chroot.d/*')) { |
30
|
0
|
0
|
|
|
|
0
|
if (open F, $path) { |
31
|
0
|
|
|
|
|
0
|
$content .= join("", ) . "\n"; |
32
|
0
|
|
|
|
|
0
|
close F; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
else { |
35
|
0
|
|
|
|
|
0
|
print STDERR "Ignoring file '$path': couldn't read\n"; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
} |
38
|
0
|
|
|
|
|
0
|
$schroot_config = Config::Tiny->read_string($content); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
0
|
return $schroot_config; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub ensure_file_exists { |
45
|
0
|
|
|
0
|
0
|
0
|
my ($self, $path) = @_; |
46
|
|
|
|
|
|
|
|
47
|
0
|
0
|
|
|
|
0
|
unless (-e $path) { |
48
|
0
|
0
|
|
|
|
0
|
open F, ">$path" or croak "Couldn't create file '$path'\n"; |
49
|
0
|
|
|
|
|
0
|
close F; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub builder_exists { |
54
|
0
|
|
|
0
|
0
|
0
|
my ($self, $builder_name) = @_; |
55
|
|
|
|
|
|
|
|
56
|
0
|
|
|
|
|
0
|
return (defined $self->_get_schroot_conf->{$builder_name}); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub get_builder_directory { |
60
|
0
|
|
|
0
|
0
|
0
|
my ($self, $builder_name) = @_; |
61
|
|
|
|
|
|
|
|
62
|
0
|
0
|
|
|
|
0
|
if ($self->builder_exists($builder_name)) { |
63
|
0
|
|
|
|
|
0
|
return $self->_get_schroot_conf->{$builder_name}->{directory}; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
else { |
66
|
0
|
|
|
|
|
0
|
croak "Can't find schroot information for builder '$builder_name'\n"; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub do_init { |
71
|
0
|
|
|
0
|
0
|
0
|
my ($self, $builder) = @_; |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
|
|
0
|
my $builder_dir = $self->get_builder_directory($builder); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# Bind some important files to the 'host' |
76
|
0
|
|
|
|
|
0
|
foreach my $etc_file (qw(resolv.conf passwd shadow group gshadow)) { |
77
|
0
|
|
|
|
|
0
|
my $full_path = "$builder_dir/etc/$etc_file"; |
78
|
0
|
0
|
|
|
|
0
|
unless (-e $full_path) { |
79
|
0
|
|
|
|
|
0
|
$self->ensure_file_exists($full_path); |
80
|
|
|
|
|
|
|
} |
81
|
0
|
|
|
|
|
0
|
my $mount_cmd = qq(mount --bind "/etc/$etc_file" "$full_path"); |
82
|
0
|
|
|
|
|
0
|
my $remount_cmd = qq(mount --bind -oremount,ro) . |
83
|
|
|
|
|
|
|
qq( "/etc/$etc_file" "$full_path"); |
84
|
0
|
|
|
|
|
0
|
$self->ui_module->print_title("Binding /etc/$etc_file to $full_path"); |
85
|
0
|
|
|
|
|
0
|
system($mount_cmd); |
86
|
0
|
|
|
|
|
0
|
system($remount_cmd); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub do_uninit { |
91
|
0
|
|
|
0
|
0
|
0
|
my ($self, $builder) = @_; |
92
|
|
|
|
|
|
|
|
93
|
0
|
|
|
|
|
0
|
my $builder_dir = $self->get_builder_directory($builder); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Bind some important files to the 'host' |
96
|
0
|
|
|
|
|
0
|
my $ok = 1; |
97
|
0
|
|
|
|
|
0
|
foreach my $etc_file (qw(resolv.conf passwd shadow group gshadow)) { |
98
|
0
|
|
|
|
|
0
|
my $full_path = "$builder_dir/etc/$etc_file"; |
99
|
0
|
|
|
|
|
0
|
$self->ui_module->print_title("Unbinding $full_path from /etc/$etc_file"); |
100
|
0
|
|
|
|
|
0
|
my $r = system(qq(umount "$full_path" 2>/dev/null)); |
101
|
0
|
0
|
|
|
|
0
|
if ($r != 0) { |
102
|
0
|
|
|
|
|
0
|
$ok = 0; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
0
|
return $ok; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub _call_sbuild { |
109
|
0
|
|
|
0
|
|
0
|
my ($self, $package_spec, $params, $output_dir) = @_; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# 1) Create a temporary directory, change to it |
112
|
0
|
|
|
|
|
0
|
my $tmp_dir = File::Temp::tempdir(); |
113
|
0
|
|
|
|
|
0
|
my $initial_dir = Cwd::cwd; |
114
|
0
|
|
|
|
|
0
|
chdir $tmp_dir; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# 2) Execute sbuild there and save output in last_build_log |
117
|
0
|
|
|
|
|
0
|
$self->{last_build_log} = qx/sbuild -v $params $package_spec 2>&1/; |
118
|
0
|
|
|
|
|
0
|
my $r = $CHILD_ERROR; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# 3) Move result to the result directory |
121
|
0
|
|
|
|
|
0
|
chdir $initial_dir; |
122
|
0
|
0
|
|
|
|
0
|
if ($output_dir !~ qr,^/,) { |
123
|
0
|
|
|
|
|
0
|
$output_dir = File::Spec->catfile($initial_dir, $output_dir); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
find({ wanted => sub { |
126
|
0
|
0
|
|
0
|
|
0
|
if ($File::Find::name =~ /\.deb$/) { |
127
|
0
|
|
|
|
|
0
|
my $move_r = move($File::Find::name, $output_dir); |
128
|
0
|
0
|
|
|
|
0
|
if (!$move_r) { |
129
|
0
|
|
|
|
|
0
|
print STDERR "Couldn't move $File::Find::name to $output_dir.\nCan't write to $output_dir maybe?\n"; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
}, |
133
|
0
|
|
|
|
|
0
|
follow => 0 }, |
134
|
|
|
|
|
|
|
$tmp_dir); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# 4) Remove temporary directory |
137
|
0
|
|
|
|
|
0
|
rmtree($tmp_dir); |
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
0
|
return $r; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub _compile_package_from_spec { |
143
|
2
|
|
|
2
|
|
5
|
my ($self, $package_spec, %user_opts) = @_; |
144
|
2
|
|
|
|
|
9
|
my %opts = (output_dir => '.', bin_nmu => 0, %user_opts); |
145
|
|
|
|
|
|
|
|
146
|
2
|
|
|
|
|
4
|
my $extra_opts = ""; |
147
|
2
|
50
|
|
|
|
6
|
if ($opts{bin_nmu}) { |
148
|
0
|
|
|
|
|
0
|
$extra_opts .= " --make-binNMU='Recompiled by Arepa' " . |
149
|
|
|
|
|
|
|
"--binNMU='$opts{bin_nmu}' " . |
150
|
|
|
|
|
|
|
"--maintainer='Arepa '"; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
2
|
|
|
|
|
9
|
my $builder_name = $self->name; |
154
|
2
|
|
|
|
|
16
|
my $build_params = "--chroot $builder_name -d unstable --apt-update --nolog -A $extra_opts"; |
155
|
2
|
|
|
|
|
13
|
my $r = $self->_call_sbuild($package_spec, |
156
|
|
|
|
|
|
|
$build_params, |
157
|
|
|
|
|
|
|
$opts{output_dir}); |
158
|
|
|
|
|
|
|
|
159
|
2
|
|
|
|
|
16
|
return ($r == 0); |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub do_compile_package_from_dsc { |
163
|
2
|
|
|
2
|
0
|
7
|
my ($self, $dsc_file, %user_opts) = @_; |
164
|
2
|
|
|
|
|
6
|
my %opts = (output_dir => '.', %user_opts); |
165
|
2
|
|
|
|
|
17
|
return $self->_compile_package_from_spec($dsc_file, |
166
|
|
|
|
|
|
|
%opts); |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub do_compile_package_from_repository { |
170
|
0
|
|
|
0
|
0
|
|
my ($self, $pkg_name, $pkg_version, %user_opts) = @_; |
171
|
0
|
|
|
|
|
|
my %opts = (output_dir => '.', %user_opts); |
172
|
0
|
|
|
|
|
|
my $package_spec = $pkg_name . '_' . $pkg_version; |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
return $self->_compile_package_from_spec($package_spec, |
175
|
|
|
|
|
|
|
%opts); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub do_create { |
179
|
0
|
|
|
0
|
0
|
|
my ($self, $builder_dir, $mirror, $distribution, %opts) = @_; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# Strip trailing slash from the builder directory. If present, it |
182
|
|
|
|
|
|
|
# triggers *very* weird errors when building any package with that |
183
|
|
|
|
|
|
|
# builder (you'll see "cd: 1: can't cd to ..." in the log output) |
184
|
0
|
|
|
|
|
|
$builder_dir =~ s,/$,,; |
185
|
0
|
|
|
|
|
|
my $builder_name = basename($builder_dir); |
186
|
|
|
|
|
|
|
|
187
|
0
|
|
|
|
|
|
my $chrootd_dir = "/etc/schroot/chroot.d"; |
188
|
0
|
|
|
|
|
|
my $schroot_file = "$chrootd_dir/$builder_name"; |
189
|
0
|
0
|
|
|
|
|
if (-e $schroot_file) { |
190
|
0
|
|
|
|
|
|
print STDERR "Builder $builder_name already exists ($schroot_file)\n"; |
191
|
0
|
|
|
|
|
|
exit 1; |
192
|
|
|
|
|
|
|
} |
193
|
0
|
|
|
|
|
|
mkpath $chrootd_dir; |
194
|
0
|
|
|
|
|
|
my $schroot_content = <
|
195
|
|
|
|
|
|
|
[$builder_name] |
196
|
|
|
|
|
|
|
description=Arepa autobuilder $builder_name |
197
|
|
|
|
|
|
|
directory=$builder_dir |
198
|
|
|
|
|
|
|
root-groups=sbuild |
199
|
|
|
|
|
|
|
# groups=sbuild-security |
200
|
|
|
|
|
|
|
groups=sbuild |
201
|
|
|
|
|
|
|
#aliases=testing |
202
|
|
|
|
|
|
|
#personality=linux32 |
203
|
|
|
|
|
|
|
EOCONTENT |
204
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Creating schroot file ($schroot_file)"); |
205
|
0
|
0
|
|
|
|
|
if (open F, ">$schroot_file") { |
206
|
0
|
|
|
|
|
|
print F $schroot_content; |
207
|
0
|
|
|
|
|
|
close F; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
else { |
210
|
0
|
|
|
|
|
|
print STDERR "Couldn't write to file $schroot_file. Check permissions\n"; |
211
|
0
|
|
|
|
|
|
exit 1; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Creating base chroot"); |
215
|
0
|
|
|
|
|
|
my $extra_opts = ""; |
216
|
0
|
0
|
|
|
|
|
if (defined $opts{arch}) { |
217
|
0
|
|
|
|
|
|
$extra_opts .= " --arch $opts{arch}"; |
218
|
|
|
|
|
|
|
} |
219
|
0
|
|
|
|
|
|
my $debootstrap_cmd = "debootstrap --variant=buildd $extra_opts " . |
220
|
|
|
|
|
|
|
"$distribution '$builder_dir' $mirror"; |
221
|
0
|
|
|
|
|
|
my $r = system($debootstrap_cmd); |
222
|
0
|
0
|
|
|
|
|
if ($r != 0) { |
223
|
0
|
|
|
|
|
|
print STDERR "Error executing debootstrap: error code $r\n"; |
224
|
0
|
|
|
|
|
|
print STDERR $debootstrap_cmd, "\n"; |
225
|
0
|
|
|
|
|
|
unlink $schroot_file; |
226
|
0
|
|
|
|
|
|
exit 1; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Create appropriate /etc/apt/sources.list |
230
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Creating default sources.list"); |
231
|
|
|
|
|
|
|
open SOURCESLIST, ">$builder_dir/etc/apt/sources.list" or |
232
|
0
|
0
|
|
|
|
|
do { |
233
|
0
|
|
|
|
|
|
print STDERR "Couldn't write to /etc/apt/sources.list"; |
234
|
0
|
|
|
|
|
|
exit 1; |
235
|
|
|
|
|
|
|
}; |
236
|
0
|
|
|
|
|
|
print SOURCESLIST <
|
237
|
|
|
|
|
|
|
deb $mirror $distribution main |
238
|
|
|
|
|
|
|
deb http://localhost/arepa/repository $distribution main |
239
|
|
|
|
|
|
|
deb-src http://localhost/arepa/repository $distribution main |
240
|
|
|
|
|
|
|
EOSOURCES |
241
|
0
|
|
|
|
|
|
close SOURCESLIST; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# Making sure /etc/hosts includes localhost |
244
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Checking /etc/hosts"); |
245
|
0
|
|
|
|
|
|
my $full_etc_hosts_path = "$builder_dir/etc/hosts"; |
246
|
0
|
|
|
|
|
|
$self->ensure_file_exists($full_etc_hosts_path); |
247
|
0
|
0
|
|
|
|
|
if (open F, $full_etc_hosts_path) { |
248
|
0
|
|
|
|
|
|
my $contents = join("", ); |
249
|
0
|
|
|
|
|
|
close F; |
250
|
0
|
0
|
|
|
|
|
if (! grep /localhost/, $contents) { |
251
|
0
|
0
|
|
|
|
|
if (open F, ">$full_etc_hosts_path") { |
252
|
0
|
|
|
|
|
|
print F $contents, "\n"; |
253
|
0
|
|
|
|
|
|
print F "127.0.0.1\tlocalhost\n"; |
254
|
0
|
|
|
|
|
|
close F; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
else { |
257
|
0
|
|
|
|
|
|
print STDERR "Couldn't update $full_etc_hosts_path\n"; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
else { |
262
|
0
|
|
|
|
|
|
print STDERR "Couldn't check for a 'localhost' alias in $full_etc_hosts_path\n"; |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Make sure certain directories exist and are writable by the 'sbuild' |
266
|
|
|
|
|
|
|
# group |
267
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Creating build directories"); |
268
|
0
|
|
|
|
|
|
my ($login, $pass, $uid, $gid) = getpwnam($Arepa::AREPA_MASTER_USER); |
269
|
0
|
0
|
|
|
|
|
if (!defined $login) { |
270
|
0
|
|
|
|
|
|
croak "'" . $Arepa::AREPA_MASTER_USER . "' user doesn't exist!"; |
271
|
|
|
|
|
|
|
} |
272
|
0
|
|
|
|
|
|
foreach my $dir (qw(build var/lib/sbuild var/lib/sbuild/srcdep-lock)) { |
273
|
0
|
|
|
|
|
|
my $full_path = "$builder_dir/$dir"; |
274
|
0
|
0
|
|
|
|
|
unless (-d $full_path) { |
275
|
0
|
|
|
|
|
|
mkpath $full_path; |
276
|
|
|
|
|
|
|
find({ wanted => sub { |
277
|
0
|
|
|
0
|
|
|
chmod("g+w", $File::Find::name); |
278
|
0
|
|
|
|
|
|
chown $uid, $gid, $File::Find::name; |
279
|
|
|
|
|
|
|
}, |
280
|
0
|
|
|
|
|
|
follow => 0 }, |
281
|
|
|
|
|
|
|
$full_path); |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Binding files"); |
286
|
0
|
|
|
|
|
|
Arepa::Builder::Sbuild->init($builder_name); |
287
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Updating package list"); |
289
|
0
|
|
|
|
|
|
my $update_cmd = "chroot '$builder_dir' apt-get update"; |
290
|
0
|
|
|
|
|
|
system($update_cmd); |
291
|
|
|
|
|
|
|
|
292
|
0
|
|
|
|
|
|
$self->ui_module->print_title("Installing build-essential and fakeroot"); |
293
|
0
|
|
|
|
|
|
my $install_cmd = "chroot '$builder_dir' apt-get -y --force-yes install " . |
294
|
|
|
|
|
|
|
"build-essential fakeroot"; |
295
|
0
|
|
|
|
|
|
return system($install_cmd); |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
1; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
__END__ |