3
# sbuild: build packages, obeying source dependencies
4
# Copyright (C) 1998-2000 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License as
8
# published by the Free Software Foundation; either version 2 of the
9
# License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
# General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
# $Id: sbuild,v 1.170 2002/10/10 18:50:44 rnhodek Exp $
23
# Revision 1.170 2002/10/10 18:50:44 rnhodek
24
# Security/accepted autobuilding patch by Ryan.
26
# Revision 1.169 2002/03/11 09:49:55 rnhodek
27
# chroot_apt_options: don't just set Dir::Etc::sourcelist, but whole
28
# Dir::Etc, to avoid new preferences.
30
# Revision 1.168 2002/02/07 09:12:25 rnhodek
31
# Fixed sudo call for running scripts.
33
# Revision 1.167 2002/01/22 08:53:10 rnhodek
34
# Use capitalized "Noninteractive" das DEBIAN_FRONTENT.
36
# Revision 1.166 2001/11/08 09:32:10 rnhodek
37
# fetch_source_file: in case of apt, need to pass up a $dscfile with
40
# Revision 1.165 2001/11/07 18:04:31 rnhodek
41
# Argl.. I should learn perl first :)
43
# Revision 1.164 2001/11/07 09:25:59 rnhodek
44
# fetch_source_files: after apt-get, fix $dscfile not to contain epoch.
46
# Revision 1.163 2001/11/06 15:11:24 rnhodek
47
# fetch_source_files: don't touch symlinks generated by apt-get.
49
# Revision 1.162 2001/11/06 12:29:22 rnhodek
50
# New config var $use_FetchFile (default 0).
51
# Integrated patches for using apt-get to download sources; modified so
52
# that old code (using FetchFile.pm) still present.
53
# run_apt: Fix parsing error of apt-output (\s matched ^M printed by
56
# Revision 1.161 2001/10/29 12:20:41 rnhodek
57
# Added $fakeroot var.
59
# Revision 1.160 2001/10/29 08:27:53 rnhodek
60
# Fix typo in message.
62
# Revision 1.159 2001/06/18 09:57:55 rnhodek
63
# Use --database option when wanna_build_dbbase set in config.
65
# Revision 1.158 2001/06/01 09:54:36 rnhodek
68
# Revision 1.157 2001/05/31 08:08:08 rnhodek
69
# Fixed thinko in conflicts checking (tnx James)
71
# Revision 1.156 2001/05/30 08:20:05 rnhodek
72
# Use /var/lib/apt as Dir::State if exists (newer apt versions use that)
73
# (tnx to Ryan Murray).
75
# Revision 1.155 2001/05/30 08:17:01 rnhodek
76
# Print also architecture at start of log.
78
# Revision 1.154 2001/05/29 07:33:54 rnhodek
79
# Also handle versioned Build-Conflicts.
80
# (Tnx to David Schleef <ds@schleef.org>)
82
# Revision 1.153 2001/03/13 08:45:17 rnhodek
83
# Run chmod -R on source tree only after unpacking.
85
# Revision 1.152 2001/02/19 09:23:24 rnhodek
88
# Revision 1.151 2001/02/19 08:43:22 rnhodek
89
# Fix wrong arch logic.
91
# Revision 1.150 2001/01/22 12:56:16 rnhodek
92
# Fix handling of arch-restricted build-deps (tnx to Ryan Murray).
94
# Revision 1.149 2001/01/15 11:17:36 rnhodek
97
# Revision 1.148 2001/01/15 10:59:18 rnhodek
98
# Shortcut when looking for non-dsc files: first try to fetch from same
99
# dir as .dsc and FF_search only if that fails.
101
# Revision 1.147 2001/01/10 16:16:48 rnhodek
102
# Move all built files from chroot dir, not only *.deb.
104
# Revision 1.146 2000/10/23 10:39:24 rnhodek
105
# Before doing chmod on /etc/ld.so.conf, test if it exists at all.
107
# Revision 1.145 2000/10/19 09:08:35 rnhodek
108
# A couple of little fixes from Ben.
109
# Checks and assures that /etc/ld.so.conf is readable.
110
# Support for local overrides with $conf::srcdep_over.
112
# Revision 1.144 2000/06/27 12:34:00 rnhodek
113
# Implemented new 'prepre' and 'unpack' sections for special targets;
114
# the first is a script run before package installation, and the latter
115
# can list source packages that should be unpacked in the build dir.
117
# Revision 1.143 2000/06/20 14:39:59 rnhodek
118
# Call apt-get with some options for relocating various files instead of
119
# chrooting it; this avoids that the archive must be available in chroot
120
# environment; same is true for dpkg and apt-cache calls.
121
# If chrooted, call dpkg with the chroot dir as cwd to avoid "cannot get
122
# current directory" errors; same for apt option DPkg::Run-Directory.
124
# Revision 1.142 2000/06/19 14:09:00 rnhodek
127
# Revision 1.141 2000/06/19 14:05:38 rnhodek
128
# Call buildd-addpkg with --chroot=DIR options for each dist that is >=
129
# the one building for (to run apt-get update in the chroot
132
# Revision 1.140 2000/06/19 09:10:24 rnhodek
133
# Obey new config var @ignore_watches_no_build_deps, i.e. don't flag
134
# watches that are listed there if the package doesn't have build deps.
135
# In check_watches(), strip $chroot_dir instead of $chroot_build_dir
138
# Revision 1.139 2000/06/13 10:54:43 rnhodek
139
# Also execute special dependency scripts in chroot environment.
141
# Revision 1.138 2000/06/09 12:47:52 rnhodek
142
# File .dsc filename for rbuilder (with URL).
144
# Revision 1.137 2000/06/09 09:15:21 rnhodek
145
# Always install built package (if already) when building chroot; i.e.
146
# the $system_level test is not necessary when chrooted.
148
# Revision 1.136 2000/06/09 08:20:52 rnhodek
149
# Fixed su usage in sub build.
151
# Revision 1.135 2000/06/08 14:02:11 rnhodek
152
# After changing to chroot dir, change back to be the normal user again
153
# and start dpkg-buildpackage with -rsudo again; some packages require
154
# that the build target is executed as non-root.
156
# Revision 1.134 2000/06/08 13:01:54 rnhodek
157
# apt-cache calls need sudo, too, when using chroot.
159
# Revision 1.133 2000/06/08 09:13:31 rnhodek
160
# Implemented chroot builds; there are a few new global variables
161
# $main::chroot_*; major changes are in build, where the source tree is
162
# unpacked somewhere else, dpkg-buildpackage called under chroot and
163
# built packages are moved back again; also all apt-get and dpkg calls
164
# are chroot-ed and /var/lib/dpkg/status is accessed from the chroot
165
# environment; also watches are checked under the new root dir.
167
# Revision 1.132 2000/06/06 14:37:05 rnhodek
168
# New option --source (-s): Also build source package, i.e. don't pass
169
# -b or -B to dpkg-buildpackage.
171
# Revision 1.131 2000/05/30 15:41:34 rnhodek
172
# Call buildd-addpkg with --dist option.
173
# Install freshly built packages only if $conf::system_level >= $dist.
175
# Revision 1.130 2000/05/16 12:34:20 rnhodek
176
# Insert a chmod -R go+rX on the build tree to make files readable; it
177
# happens sometimes that files in a .orig.tar.gz have restrictive
178
# permissions and this can be inconvenient.
180
# Revision 1.129 2000/03/01 14:43:34 rnhodek
181
# Also match error message "dpkg: status database area is locked" from
182
# apt and retry call later.
184
# Revision 1.128 2000/02/16 15:21:33 rnhodek
185
# Fix a print message in merge_pkg_build_deps.
187
# Revision 1.127 2000/02/16 15:20:38 rnhodek
188
# Print version number of sbuild in package log.
190
# Revision 1.126 2000/02/16 15:15:15 rnhodek
191
# Fix regexp for finding !needs-no-XXX packages.
192
# Move !needs-no-XXX from central deps to $main::additional_deps so that
193
# they can be found by prepare_watches later.
195
# Revision 1.125 2000/02/15 14:40:35 rnhodek
196
# Remove forgotten debugging code.
198
# Revision 1.124 2000/02/15 11:12:43 rnhodek
199
# Expand virtual packages in package build dependencies for comparing
202
# Revision 1.123 2000/02/11 11:17:07 rnhodek
203
# Do not activate watches for packages XXX if a negative dependency
204
# needs-no-XXX exists (used to be just a comment, now really processed
206
# Also do not activate watches for dependencies of pkg build deps.
208
# Revision 1.122 2000/02/09 15:57:25 rnhodek
209
# In merge_pkg_build_deps, do not show warnings about missing
210
# !this-package-does-not-exist or !needs-no-xxx dependencies.
212
# Revision 1.121 2000/02/04 14:04:18 rnhodek
213
# Use --no-down-propagation.
215
# Revision 1.120 2000/02/01 12:05:56 rnhodek
216
# In binNMU mode, a '_' was missing in the job name.
218
# Revision 1.119 2000/01/28 14:54:43 rnhodek
219
# Accept abbrevs for distribution options (-ds, -df, -du) here, too.
220
# New option --make-binNMU=entry.
221
# New binNMU hack to modify debian/changelog; it will add a new entry
222
# for the NMU version.
223
# New helper function binNMU_version to generate a new version number.
225
# Revision 1.118 2000/01/13 14:32:30 rnhodek
226
# For compiling on slink systems, pass the --force-confold option to
227
# dpkg only for versions < 1.4.1.18 (that don't understand it yet).
229
# Revision 1.117 1999/12/17 13:49:50 rnhodek
230
# Improved output about missing central deps: build-essential (act.
231
# policy) and dependencies of pkg build deps are filtered out and
232
# printed separately.
233
# New functions cmp_dep_lists, read_build_essential,
234
# expand_dependencies, and get_dependencies for the above.
236
# Revision 1.116 1999/12/17 11:04:43 rnhodek
237
# When pkg build-deps were read from debian/sbuild-build-deps, a wrong
238
# package name was used.
240
# Revision 1.115 1999/12/09 09:54:42 rnhodek
241
# Again fixed a fatal typo...
243
# Revision 1.114 1999/12/08 12:33:16 rnhodek
244
# merge_pkg_build_deps: Fix printing of overrides.
246
# Revision 1.113 1999/12/08 12:25:34 rnhodek
247
# Special dependencies are implicitly overrides, i.e. are added to the
248
# package-provided build deps.
250
# Revision 1.112 1999/12/08 11:31:38 rnhodek
251
# get_dpkg_status: don't reset $res{$pkg}->{Installed} to 0 if $pkg is
254
# Revision 1.111 1999/12/08 10:37:33 rnhodek
255
# Change parsing of .dsc file so that multi-line build dependencies are
257
# Make warning about missing central deps a bit bigger.
259
# Revision 1.110 1999/12/06 15:00:33 rnhodek
260
# Fix comparison with old deps (must copy them, not only the reference).
262
# Revision 1.109 1999/12/06 08:35:53 rnhodek
265
# Revision 1.108 1999/12/03 09:58:16 rnhodek
266
# If a pkg has its own build deps, compare them with the central ones
267
# and report missing ones.
269
# Revision 1.107 1999/11/30 13:54:38 rnhodek
270
# Print a message if build deps from the .dsc are used (to avoid confusion).
271
# If a pkg has build deps, store them in debian/.sbuild-build-deps to
272
# have them available when rebuilding later (no .dsc anymore); also
273
# check for this file and read deps from it if building without a .dsc
274
# in unpacked source.
276
# Revision 1.106 1999/11/15 12:30:15 rnhodek
277
# merge_pkg_build_deps: added missing if $main::debug.
279
# Revision 1.105 1999/11/03 14:56:32 rnhodek
280
# When running apt, set env var DEBIAN_FRONTEND to noninteractive to
281
# stop debconf from asking questions or complaining that /dev/tty can't
284
# Revision 1.104 1999/11/02 16:43:51 rnhodek
285
# check_inst_packages: also upgrade dependencies of src-deps (if they're
286
# already installed); some -dev packages fail to correctly require an
287
# identical versioned shlib pkg, so in some cases only the -dev pkg was
290
# Revision 1.103 1999/11/02 15:45:43 rnhodek
291
# build: Use epoch-stripped version number for the .changes file.
292
# check_inst_packages: forgot a if $main::debug.
294
# Revision 1.102 1999/10/29 13:07:49 rnhodek
295
# New option --stats-dir=DIR; if used, a "1" is appended to
296
# DIR/give-back each time a package is given back.
298
# Revision 1.101 1999/10/29 12:32:24 rnhodek
299
# If using an already unpacked source tree, check (with
300
# dpkg-parsechangelog) if it's really the requested version.
301
# Make apt-get run dpkg with --force-confold, as the </dev/null trick
302
# doesn't work anymore with dpkg >= 1.4.1.18.
304
# Revision 1.100 1999/10/25 12:12:21 rnhodek
305
# check_inst_packages: Add packages to @deps_inst only if they're not
306
# already to be installed.
308
# Revision 1.99 1999/10/22 09:01:36 rnhodek
309
# Minor changes to output of check_inst_packages.
311
# Revision 1.98 1999/10/21 14:21:57 rnhodek
312
# Oops... call check_inst_packages only if build was successful.
314
# Revision 1.97 1999/10/21 11:46:50 rnhodek
315
# Deleted RCS logs for < 1.50.
316
# New option --store-built-packages.
317
# Fix package name parsing: \w also matches '_' which is unwanted;
319
# Read reverse sourcedeps of $main::store_built_packages.
320
# New sub check_inst_packages.
322
# Revision 1.96 1999/09/27 11:18:10 rnhodek
323
# Added a missing PLOG.
325
# Revision 1.95 1999/09/15 09:10:25 rnhodek
326
# Additionally print a warning if a special dep has a version relation.
328
# Revision 1.94 1999/09/15 09:08:12 rnhodek
329
# Changed parsing of dependencies a bit so that special deps can have
330
# arch restrictions, too.
332
# Revision 1.93 1999/08/30 09:44:35 rnhodek
333
# get_dpkg_status: don't exit too early if a pkg isn't in the arg list,
334
# as it might be provided only.
336
# Revision 1.92 1999/08/27 13:32:04 rnhodek
337
# --auto-give-back has a new optional argument, the user and hostname
338
# where to call wanna-build (like $conf::sshcmd); this is needed that
339
# sbuild can do give-backs when there's no local wanna-build.
341
# Revision 1.91 1999/08/23 12:53:02 rnhodek
342
# Support for alternatives.
343
# Support for [ARCH1 !ARCH2] arch restriction on dependencies.
344
# Parses only src-deps which are needed for packages to be built.
345
# Reads Build-{Depends,Conflicts}{,-Indep}: fields from .dsc if present;
346
# those override the central src-deps, except those marked as override
348
# Implemented abbrevs as kind of macros in src-deps.
349
# New option --add-depends (-a).
350
# New option --arch-all (-A).
352
# Revision 1.90 1999/08/11 15:28:11 rnhodek
353
# Insert missing wait call in run_script to get correct return value.
355
# Revision 1.89 1999/08/10 14:01:49 rnhodek
356
# Virtual packages as dependencies didn't work really yet -- the
357
# consistency check didn't see them (dpkg --status doesn't know them)
358
# and thus aborted the build; solution: get_dpkg_status now directly
359
# reads the status file (which should be a bit faster, too) and extracts
360
# Provides: fields of all installed packages and considers those virtual
361
# packages installed, too.
362
# Print "Source-dependencies not satisfied" message to package log, not
364
# Same in run_apt for virtual package handling.
365
# Fix stdout/stderr redirecting when running scripts.
367
# Revision 1.88 1999/07/13 07:23:55 rnhodek
368
# Use GDBM for time/space databases, as perl-5.004 seems not to contain
371
# Revision 1.87 1999/06/21 12:52:00 rnhodek
372
# Seems apt has a new error message if a cached Packages file isn't
373
# up-to-date anymore -- recognize this msg, too, and reun apt-get update.
375
# Revision 1.86 1999/06/09 15:05:38 rnhodek
376
# Fix loop in apply_patches.
377
# Don't fail due to failed patch if a global patch.
378
# Global patches are no syntax error when parsing src-deps...
380
# Revision 1.85 1999/06/04 09:47:02 rnhodek
381
# Add support for global patches, which will be tried on any package;
382
# their names in source-dependencies start with "**".
384
# Revision 1.84 1999/06/04 08:17:17 rnhodek
385
# When calling wanna-build --give-back, don't forget the --dist argument!
386
# Added support for virtual packages as source dependencies: apt-get tells us
387
# which alternatives are possible, and one of these is selected either by
388
# %conf::alternatives or by random.
390
# Revision 1.83 1999/06/02 09:07:47 rnhodek
391
# With --batch, write each finished job to SBUILD-FINISHED; buildd can pick up
392
# this file if sbuild crashes and needs not rebuild already done stuff. The file
393
# is removed on normal exit and if sbuild dumps to REDO during a shutdown.
395
# Revision 1.82 1999/06/02 08:47:39 rnhodek
396
# Remove as many die's as possible -- the bad exit status can cause
397
# buildd to retry all packages of an sbuild run; better let this one
399
# Make sure that after build() we're in the correct directory: some
400
# chdir()s were missing; also don't chdir("..") because this can be
401
# wrong if we followed a symlink, use $main::cwd instead.
402
# If the package directory already exists as a symlink, abort the build.
404
# Revision 1.81 1999/05/31 12:59:41 rnhodek
405
# Run du after build under sudo, to avoid error messages about
408
# Revision 1.80 1999/05/27 13:28:04 rnhodek
409
# Oops, missed an epoch fix (when constructing the .changes file name).
411
# Revision 1.79 1999/05/26 11:34:11 rnhodek
412
# Ignore epochs for fetching files.
414
# Revision 1.78 1999/05/26 09:48:23 rnhodek
415
# If dpkg-source fails, remove .tmp-nest dir.
417
# Revision 1.77 1999/05/05 07:56:51 rnhodek
418
# Need to empty %main::this_watches before filling it for a new package;
419
# otherwise we have some spurious reports :-)
421
# Revision 1.76 1999/05/04 14:51:40 rnhodek
422
# Some more minor stuff for avg-build-space: Reset global
423
# $main::this_space to 0 before each build to avoid using the figure of
424
# the previous package in case of errors; don't write a 0 value into the
427
# Revision 1.75 1999/05/04 14:43:01 rnhodek
428
# Fix parsing of a single dependency: package name never should contain
431
# Revision 1.74 1999/05/04 14:29:51 rnhodek
432
# Determine how much space is required for a build (final build dir +
433
# generated .debs) after dpkg-buildpackage is finished; display figure
434
# in package log and also store it in $conf::avg_space_db (analogous to
437
# Revision 1.73 1999/05/03 12:53:25 rnhodek
438
# After unpacking src dir, run "chmod -R g-s ." on it; some
439
# .orig.tar.gz's are packed with the setgid bit, which causes the debian
440
# dir and all subdirs to be created setgid, too, and later dpkg-deb
441
# --build complains about this.
443
# Revision 1.72 1999/04/22 14:16:25 rnhodek
444
# Don't kill tee process if verbose but --nolog set -- $pkg_tee_pid
447
# Revision 1.71 1999/04/21 14:54:10 rnhodek
448
# Implemented watches if certain binaries have been used during a build
449
# without a source dependency.
451
# Revision 1.70 1999/03/12 10:29:32 rnhodek
452
# New option --force-depends (-f) to override src-deps of a package.
456
($main::HOME = $ENV{'HOME'})
457
or die "HOME not defined in environment!\n";
458
push( @INC, "$main::HOME/lib" );
461
chomp( $main::HOSTNAME = `hostname` );
466
@dist_parts = qw(main contrib non-free);
467
$source_dependencies = "/etc/source-dependencies";
468
$mailprog = "/usr/sbin/sendmail";
469
$dpkg = "/usr/bin/dpkg";
470
$sudo = "/usr/bin/sudo";
472
$fakeroot = "/usr/bin/fakeroot";
473
$apt_get = "/usr/bin/apt-get";
474
$apt_cache = "/usr/bin/apt-cache";
475
$dpkg_source = "/usr/bin/dpkg-source";
476
$build_env_cmnd = "";
477
$pgp_options = "-us -uc";
478
$log_dir = "$main::HOME/logs";
480
$purge_build_directory = "successful";
481
@toolchain_regex = ( 'binutils$', 'gcc-[\d.]+$', 'g\+\+-[\d.]+$', 'libstdc\+\+', 'libc[\d.]+-dev$', 'linux-kernel-headers$', 'dpkg-dev$', 'make$' );
482
$stalled_pkg_timeout = 90; # minutes
483
$srcdep_lock_wait = 1; # minutes
484
%individual_stalled_pkg_timeout = ();
485
$path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin:/usr/games";
487
require "/etc/sbuild.conf" if -r "/etc/sbuild.conf";
488
require "$HOME/.sbuildrc" if -r "$HOME/.sbuildrc";
490
#die "mailprog binary $conf::mailprog does not exist or isn't executable\n"
491
# if !-x $conf::mailprog;
492
die "sudo binary $conf::sudo does not exist or isn't executable\n"
494
die "apt-get binary $conf::apt_get does not exist or isn't executable\n"
495
if !-x $conf::apt_get;
496
die "apt-cache binary $conf::apt_cache does not exist or isn't executable\n"
497
if !-x $conf::apt_cache;
498
die "dpkg-source binary $conf::dpkg_source does not exist or isn't executable\n"
499
if !-x $conf::dpkg_source;
500
#die "$conf::log_dir is not a directory\n" if ! -d $conf::log_dir;
501
die "$conf::srcdep_lock_dir is not a directory\n" if ! -d $conf::srcdep_lock_dir;
502
die "conf::mailto not set\n" if !$conf::mailto;
511
# avoid intermixing of stdout and stderr
514
# We should not ignore HUP for our children - it breaks test suites.
515
# in case the terminal disappears, the build should continue
516
#$SIG{'HUP'} = 'IGNORE';
518
$main::distribution = "";
519
$main::distribution = $conf::default_distribution if $conf::default_distribution;
521
chomp( $main::arch = `$conf::dpkg --print-architecture` );
522
$main::username = (getpwuid($<))[0] || $ENV{'LOGNAME'} || $ENV{'USER'};
525
$main::batchmode = 0;
526
$main::auto_giveback = 0;
528
$main::build_arch_all = 0;
529
$main::build_source = 0;
530
$main::jobs_file = cwd() . "/build-progress";
531
$main::max_lock_trys = 120;
532
$main::lock_interval = 5;
534
$main::ilock_file = "$conf::srcdep_lock_dir/install";
535
$main::srcdep_lock_cnt = 0;
536
$main::chroot_dir = "";
537
$main::chroot_build_dir = "";
538
$main::chroot_apt_options = "";
539
@main::toolchain_pkgs = ();
541
$main::nr_processors = $ENV{'NR_PROCESSORS'} if $ENV{'NR_PROCESSORS'};
546
check_dpkg_version();
548
while( @ARGV && $ARGV[0] =~ /^-/ ) {
550
if (/^-v$/ || /^--verbose$/) {
553
elsif (/^-D$/ || /^--debug$/) {
556
elsif (/^-b$/ || /^--batch$/) {
557
$main::batchmode = 1;
559
elsif (/^-n$/ || /^--nolog$/) {
562
elsif (/^-A$/ || /^--arch-all$/) {
563
$main::build_arch_all++;
565
elsif (/^-s$/ || /^--source$/) {
566
$main::build_source++;
567
$conf::purge_build_directory = "never";
569
elsif (/^--architecture=(.)/) {
572
elsif (/^--archive=(.)/) {
573
$main::archive=$1.$';
575
elsif (/^--comp=(.)/) {
576
$main::component=$1.$';
578
elsif (/^--purpose=(.)/) {
579
$main::purpose=$1.$';
581
elsif (/^--build-debug-symbols$/) {
582
$main::build_debug_symbols = 1;
584
elsif (/^-d/ || /^--dist/) {
585
if (/^-d(.)/ || /^--dist=(.)/) {
586
$main::distribution = $1.$';
589
die "$_ option missing argument\n";
592
$main::distribution = shift @ARGV;
594
$main::distribution = "stable" if $main::distribution eq "s";
595
$main::distribution = "testing" if $main::distribution eq "t";
596
$main::distribution = "unstable" if $main::distribution eq "u";
598
elsif (/^-p/ || /^--purge/) {
599
if (/^-p(.)/ || /^--purge=(.)/) {
600
$conf::purge_build_directory = $1.$';
603
die "$_ option missing argument\n";
606
$conf::purge_build_directory = shift @ARGV;
608
die "Bad purge mode\n"
609
if !isin($conf::purge_build_directory, qw(always successful never));
611
elsif (/^-m/ || /^--maintainer/) {
612
if (/^-m(.)/ || /^--maintainer=(.)/) {
613
$conf::maintainer_name = $1.$';
616
die "$_ option missing argument\n";
619
$conf::maintainer_name = shift @ARGV;
622
elsif (/^-f/ || /^--force-depends/) {
623
if (/^-f(.)/ || /^--force-depends=(.)/) {
624
push( @main::manual_srcdeps, "f".$1.$' );
627
die "$_ option missing argument\n";
630
push( @main::manual_srcdeps, "f".(shift @ARGV) );
633
elsif (/^-a/ || /^--add-depends/) {
634
if (/^-a(.)/ || /^--add-depends=(.)/) {
635
push( @main::manual_srcdeps, "a".$1.$' );
638
die "$_ option missing argument\n";
641
push( @main::manual_srcdeps, "a".(shift @ARGV) );
644
elsif (/^--auto-give-back(=(.*))?$/) {
645
$main::auto_giveback = 1;
647
my @parts = split( '@', $2 );
648
$main::auto_giveback_socket = "$main::HOME/build" if @parts > 3;
649
$main::auto_giveback_socket .= $parts[$#parts-3] if @parts > 3;
650
$main::auto_giveback_wb_user = $parts[$#parts-2] if @parts > 2;
651
$main::auto_giveback_user = $parts[$#parts-1] if @parts > 1;
652
$main::auto_giveback_host = $parts[$#parts];
655
elsif (/^--database=(.+)$/) {
656
$main::database = $1;
658
elsif (/^--stats-dir=(.+)$/) {
659
$main::stats_dir = $1;
661
elsif (/^--make-binNMU=(.+)$/) {
663
$main::binNMUver ||= 1;
665
elsif (/^--binNMU=(\d+)$/) {
666
$main::binNMUver = $1;
668
elsif (/^--use-snapshot$/) {
670
$main::ld_library_path = "/usr/lib/gcc-snapshot/lib";
671
$conf::path = "/usr/lib/gcc-snapshot/bin:$conf::path";
674
die "Unknown option: $_\n";
678
die "Need distribution\n" if $main::distribution eq "";
680
$conf::mailto = $conf::mailto{$main::distribution}
681
if $conf::mailto{$main::distribution};
683
$main::arch = $conf::arch if $conf::arch;
685
# variables for scripts:
687
$SIG{'INT'} = \&shutdown;
688
$SIG{'TERM'} = \&shutdown;
689
$SIG{'ALRM'} = \&shutdown;
690
$SIG{'PIPE'} = \&shutdown;
691
read_deps( map { m,(?:.*/)?([^_/]+)[^/]*, } @ARGV );
692
if (-d "chroot-autobuild") {
693
$main::chroot_dir = "chroot-autobuild";
694
$main::chroot_build_dir = "$main::chroot_dir/build/$main::username/";
695
$conf::srcdep_lock_dir = "$main::chroot_dir/var/debbuild/srcdep-lock";
696
$main::ilock_file = "$conf::srcdep_lock_dir/install";
697
my $absroot = "$main::cwd/$main::chroot_dir";
698
$main::chroot_apt_options =
699
"-o APT::Architecture=$main::arch ".
700
"-o Dir::State=$absroot/var/".
701
(-d "$absroot/var/lib/apt" ? "lib":"state")."/apt ".
702
"-o Dir::State::status=$absroot/var/lib/dpkg/status ".
703
"-o Dir::Cache=$absroot/var/cache/apt ".
704
"-o Dir::Etc=$absroot/etc/apt ".
705
"-o DPkg::Options::=--root=$absroot ".
706
"-o DPkg::Options::=--force-architecture ".
707
"-o DPkg::Run-Directory=$absroot";
708
$main::chroot_apt_op = '$CHROOT_OPTIONS';
713
foreach $pkgv (@ARGV) {
717
($urlbase, $pkgv) = ($1, $3) if $pkgv =~ m,^(\w+://(\S+/)?)([^/]+)$,;
719
next if !open_pkg_log( $pkgv );
720
(my $pkg = $pkgv) =~ s/_.*$//;
721
$main::pkg_start_time = time;
722
$main::this_space = 0;
723
$main::pkg_status = "failed"; # assume for now
724
$main::current_job = $main::binNMU_name || $pkgv;
725
$main::additional_deps = [];
726
write_jobs_file( "currently building" );
727
if (should_skip( $pkgv )) {
728
$main::pkg_status = "skipped";
731
my $dscfile = $pkgv.".dsc";
732
$main::pkg_fail_stage = "fetch-src";
733
my @files_to_rm = fetch_source_files( \$dscfile );
734
if (@files_to_rm && $files_to_rm[0] eq "ERROR") {
736
goto cleanup_symlinks;
739
$main::pkg_fail_stage = "install-deps";
740
if (!install_deps( $pkg )) {
741
print PLOG "Source-dependencies not satisfied; skipping $pkg\n";
742
goto cleanup_packages;
745
my $dscbase = basename( $dscfile );
746
$main::pkg_status = "successful" if build( $dscbase, $pkgv );
748
write_jobs_file( $main::pkg_status );
749
append_to_FINISHED( $main::current_job );
754
remove_srcdep_lock_file();
756
remove_files( @files_to_rm );
758
analyze_fail_stage( $pkgv );
759
if( $main::pkg_status eq 'failed' ) {
760
$main::pkg_status = 'failed ' . $main::pkg_fail_stage;
762
write_jobs_file( $main::pkg_status );
763
close_pkg_log( $pkgv );
764
$main::current_job = "";
765
if ( $main::batchmode and (-f "$main::HOME/EXIT-DAEMON-PLEASE") ) {
766
main::shutdown("NONE (flag file exit)");
772
#unlink( $main::jobs_file ) if $main::batchmode;
773
unlink( "SBUILD-FINISHED" ) if $main::batchmode;
776
sub fetch_source_files {
777
my $dscfile_ref = shift;
778
my $dscfile = $$dscfile_ref;
779
my ($dir, $dscbase, $files, @other_files, $dscarchs, @made);
780
my ($build_depends, $build_depends_indep, $build_conflicts,
781
$build_conflicts_indep);
784
$dscfile =~ m,^(.*)/([^/]+)$,;
785
($dir, $dscbase) = ($1, $2);
787
$urlbase = $1 if $dscfile =~ m,^(\w+://(\S+/)?)([^/]+)$,;
788
(my $pkgv = $dscfile) =~ s,^(.*/)?([^/]+)\.dsc$,$2,;
789
my ($pkg, $version) = split /_/, $pkgv;
790
@main::have_dsc_build_deps = ();
793
if (-f "$dscfile/debian/.sbuild-build-deps") {
794
open( F, "<$dscfile/debian/.sbuild-build-deps" );
797
/^Package:\s*(.*)\s*$/i and $pkg = $1;
798
/^Build-Depends:\s*(.*)\s*$/i and $build_depends = $1;
799
/^Build-Depends-Indep:\s*(.*)\s*$/i and $build_depends_indep = $1;
800
/^Build-Conflicts:\s*(.*)\s*$/i and $build_conflicts = $1;
801
/^Build-Conflicts-Indep:\s*(.*)\s*$/i and $build_conflicts_indep = $1;
804
if ($build_depends || $build_depends_indep || $build_conflicts ||
805
$build_conflicts_indep) {
806
merge_pkg_build_deps( $pkg, $build_depends,
807
$build_depends_indep, $build_conflicts,
808
$build_conflicts_indep );
816
if (-f "${pkgv}.dsc") {
817
print PLOG "${pkgv}.dsc exists in cwd\n";
824
print PLOG "Checking available source versions...\n";
825
if (!open( PIPE, "$conf::sudo /usr/sbin/chroot ".
826
"$main::chroot_dir $conf::apt_cache ".
827
"-q showsrc $pkg 2>&1 </dev/null |" )) {
828
print PLOG "Can't open pipe to apt-cache: $!\n";
833
my $ver = $1 if /^Version:\s+(\S+)\s*$/mi;
834
my $tfile = $1 if /^Files:\s*\n((\s+.*\s*\n)+)/mi;
835
@{$entries{$ver}} = map { (split( /\s+/, $_ ))[3] }
836
split( "\n", $tfile );
841
print PLOG "$conf::apt_cache failed\n";
845
if (!defined($entries{$version})) {
847
# try to update apt's cache if nothing found
848
system "$conf::sudo /usr/sbin/chroot ".
849
"$main::chroot_dir $conf::apt_get ".
854
print PLOG "Can't find source for $pkgv\n";
855
print PLOG "(only different version(s) ",
856
join( ", ", sort keys %entries), " found)\n"
861
print PLOG "Fetching source files...\n";
862
@made = @{$entries{$version}};
863
if (!open( PIPE, "$conf::apt_get $main::chroot_apt_options ".
864
"--only-source -q -d source $pkg=$version 2>&1 </dev/null |" )) {
865
print PLOG "Can't open pipe to $conf::apt_get: $!\n";
866
return ("ERROR", @made);
873
print PLOG "$conf::apt_get for sources failed\n";
874
return( "ERROR", @made );
876
# touch the downloaded files, otherwise buildd-watcher
877
# will complain that they're old :)
878
$$dscfile_ref = $dscfile = (grep { /\.dsc$/ } @made)[0];
883
if (!open( F, "<$dscfile" )) {
884
print PLOG "Can't open $dscfile: $!\n";
885
return( "ERROR", @made );
888
{ local($/); $dsctext = <F>; }
891
$dsctext =~ /^Build-Depends:\s*((.|\n\s+)*)\s*$/mi
892
and $build_depends = $1;
893
$dsctext =~ /^Build-Depends-Indep:\s*((.|\n\s+)*)\s*$/mi
894
and $build_depends_indep = $1;
895
$dsctext =~ /^Build-Conflicts:\s*((.|\n\s+)*)\s*$/mi
896
and $build_conflicts = $1;
897
$dsctext =~ /^Build-Conflicts-Indep:\s*((.|\n\s+)*)\s*$/mi
898
and $build_conflicts_indep = $1;
899
$build_depends =~ s/\n\s+/ /g if defined $build_depends;
900
$build_depends_indep =~ s/\n\s+/ /g if defined $build_depends_indep;
901
$build_conflicts =~ s/\n\s+/ /g if defined $build_conflicts;
902
$build_conflicts_indep =~ s/\n\s+/ /g if defined $build_conflicts_indep;
904
$dsctext =~ /^Architecture:\s*(.*)$/mi and $dscarchs = $1;
906
$dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
907
@other_files = map { (split( /\s+/, $_ ))[3] } split( "\n", $files );
910
print PLOG "$dscbase has no Architecture: field -- skipping arch check!\n";
914
for my $a (split(/\s+/, $dscarchs)) {
915
if (system("$conf::sudo", "/usr/sbin/chroot",
916
"$main::cwd/$main::chroot_dir",
917
"dpkg-architecture", "-a".$main::arch, "-i".$a) eq 0) {
922
if ($dscarchs ne "any" && !($valid_arch) &&
923
!($dscarchs eq "all" && $main::build_arch_all) ) {
924
my $msg = "$dscbase: $main::arch not in arch list or does not match any arch ";
925
$msg .= "wildcards: $dscarchs -- skipping\n";
927
$main::pkg_fail_stage = "arch-check";
928
return( "ERROR", @made );
931
print "Arch check ok ($main::arch included in $dscarchs)\n"
934
if ($build_depends || $build_depends_indep || $build_conflicts ||
935
$build_conflicts_indep) {
936
@main::have_dsc_build_deps = ($build_depends, $build_depends_indep,
937
$build_conflicts,$build_conflicts_indep);
938
merge_pkg_build_deps( $pkg, $build_depends, $build_depends_indep,
939
$build_conflicts, $build_conflicts_indep );
948
my( $dir, $rv, $changes );
949
my $do_apply_patches = 1;
950
local( *PIPE, *F, *F2 );
952
fixup_pkgv( \$pkgv );
953
print PLOG "-"x78, "\n";
954
# count build time from now, ignoring the installation of source deps
955
$main::pkg_start_time = time;
956
$main::this_space = 0;
957
$pkgv =~ /^([a-zA-Z\d.+-]+)_([a-zA-Z\d:.+~-]+)/;
958
my ($pkg, $version) = ($1,$2);
959
(my $sversion = $version) =~ s/^\d+://;
960
my $tmpunpackdir = $dsc;
961
$tmpunpackdir =~ s/-.*$/.orig.tmp-nest/;
962
$tmpunpackdir =~ s/_/-/;
963
$tmpunpackdir = "$main::chroot_build_dir$tmpunpackdir";
965
if (-d "$main::chroot_build_dir$dsc" && -l "$main::chroot_build_dir$dsc") {
966
# if the package dir already exists but is a symlink, complain
967
print PLOG "Cannot unpack source: a symlink to a directory with the\n",
968
"same name already exists.\n";
971
if (! -d "$main::chroot_build_dir$dsc") {
972
$main::pkg_fail_stage = "unpack";
973
# dpkg-source refuses to remove the remanants of an
974
# aborted dpkg-source extraction, so we will if necessary.
975
if (-d $tmpunpackdir) {
976
system ("rm -fr $tmpunpackdir");
978
$main::sub_pid = open( PIPE, "-|" );
979
if (!defined $main::sub_pid) {
980
print PLOG "Can't spawn dpkg-source: $!\n";
983
if ($main::sub_pid == 0) {
985
if ($main::chroot_build_dir && !chdir( $main::chroot_build_dir )) {
986
print PLOG "Couldn't cd to $main::chroot_build_dir: $!\n";
987
system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
992
push( @files, $dsc );
993
if (!open( F, "<$main::cwd/$dsc" )) {
994
print PLOG "Can't open $main::cwd/$dsc: $!\n";
998
{ local($/); $dsctext = <F>; }
1001
$dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
1002
push(@files, map { (split( /\s+/, $_ ))[3] } split( "\n", $files ));
1005
foreach $file (@files) {
1006
system ("cp", "$main::cwd/$file", "$file");
1008
exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
1009
"$conf::su", $main::username, "-s", "/bin/sh", "-c",
1010
"cd /build/$main::username && $conf::dpkg_source -sn -x $dsc 2>&1";
1013
$main::sub_task = "dpkg-source";
1017
$dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ in (\S+)/;
1018
$main::pkg_fail_stage = "unpack-check"
1019
if /^dpkg-source: error: file.*instead of expected/;
1022
undef $main::sub_pid;
1024
print PLOG "FAILED [dpkg-source died]\n";
1026
system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1030
print PLOG "Couldn't find directory of $dsc in dpkg-source output\n";
1031
system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1034
$dir = "$main::chroot_build_dir$dir";
1036
if (system( "chmod -R g-s,go+rX $dir" ) != 0) {
1037
print PLOG "chmod -R g-s,go+rX $dir failed.\n";
1041
if (@main::have_dsc_build_deps && !defined $main::build_source) {
1042
my ($d, $di, $c, $ci) = @main::have_dsc_build_deps;
1043
open( F, ">$dir/debian/.sbuild-build-deps" );
1044
print F "Package: $pkg\n";
1045
print F "Build-Depends: $d\n" if $d;
1046
print F "Build-Depends-Indep: $di\n" if $di;
1047
print F "Build-Conflicts: $c\n" if $c;
1048
print F "Build-Conflicts-Indep: $ci\n" if $ci;
1053
$dir = "$main::chroot_build_dir$dsc";
1054
$do_apply_patches = 0;
1056
$main::pkg_fail_stage = "check-unpacked-version";
1057
# check if the unpacked tree is really the version we need
1058
$main::sub_pid = open( PIPE, "-|" );
1059
if (!defined $main::sub_pid) {
1060
print PLOG "Can't spawn dpkg-parsechangelog: $!\n";
1063
if ($main::sub_pid == 0) {
1066
exec "dpkg-parsechangelog 2>&1";
1068
$main::sub_task = "dpkg-parsechangelog";
1075
undef $main::sub_pid;
1077
print PLOG "FAILED [dpkg-parsechangelog died]\n";
1080
if ($clog !~ /^Version:\s*(.+)\s*$/mi) {
1081
print PLOG "dpkg-parsechangelog didn't print Version:\n";
1084
my $tree_version = $1;
1085
my $cmp_version = ($main::binNMU && -f "$dir/debian/.sbuild-binNMU-done") ?
1086
binNMU_version($version) : $version;
1087
if ($tree_version ne $cmp_version) {
1088
print PLOG "The unpacked source tree $dir is version ".
1089
"$tree_version, not wanted $cmp_version!\n";
1094
if (!chdir( $dir )) {
1095
print PLOG "Couldn't cd to $dir: $!\n";
1096
system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir;
1100
$main::pkg_fail_stage = "check-space";
1101
my $current_usage = `/usr/bin/du -s .`;
1102
$current_usage =~ /^(\d+)/;
1103
$current_usage = $1;
1104
if ($current_usage) {
1105
my $free = df( "." );
1106
if ($free < 2*$current_usage) {
1107
print PLOG "Disk space is propably not enough for building.\n".
1108
"(Source needs $current_usage KB, free are $free KB.)\n";
1109
print PLOG "Purging $dir\n";
1110
chdir( $main::cwd );
1111
system "$conf::sudo rm -rf $dir";
1116
$main::pkg_fail_stage = "hack-binNMU";
1117
if ($main::binNMU && ! -f "debian/.sbuild-binNMU-done") {
1118
if (open( F, "<debian/changelog" )) {
1119
my($firstline, $text);
1120
$firstline = <F> while $firstline =~ /^$/;
1121
{ local($/); undef $/; $text = <F>; }
1123
$firstline =~ /^(\S+)\s+\((\S+)\)\s+([^;]+)\s*;\s*urgency=(\S+)\s*$/;
1124
my ($name, $version, $dists, $urgent) = ($1, $2, $3, $4);
1125
my $NMUversion = binNMU_version($version);
1126
chomp( my $date = `822-date` );
1127
if (!open( F, ">debian/changelog" )) {
1128
print PLOG "Can't open debian/changelog for binNMU hack: $!\n";
1129
chdir( $main::cwd );
1132
$dists = $main::distribution;
1133
print F "$name ($NMUversion) $dists; urgency=low\n\n";
1134
print F " * Binary-only non-maintainer upload for $main::arch; ",
1135
"no source changes.\n";
1136
print F " * ", join( " ", split( "\n", $main::binNMU )), "\n\n";
1137
print F " -- $conf::maintainer_name $date\n\n";
1139
print F $firstline, $text;
1141
system "touch debian/.sbuild-binNMU-done";
1142
print PLOG "*** Created changelog entry for bin-NMU version $NMUversion\n";
1145
print PLOG "Can't open debian/changelog -- no binNMU hack!\n";
1149
if ($do_apply_patches) {
1150
if (!apply_patches( $pkg )) {
1151
chdir( $main::cwd );
1156
if (-f "debian/files") {
1159
open( FILES, "<debian/files" );
1160
chomp( @lines = <FILES> );
1162
@lines = map { my $ind = 68-length($_);
1163
$ind = 0 if $ind < 0;
1164
"| $_".(" " x $ind)." |\n"; } @lines;
1168
+----------------------------------------------------------------------+
1171
| After unpacking, there exists a file debian/files with the contents: |
1177
| This should be reported as a bug. |
1178
| The file has been removed to avoid dpkg-genchanges errors. |
1179
+----------------------------------------------------------------------+
1182
unlink "debian/files";
1185
open CURRENT, ">$main::cwd/$main::chroot_dir/CurrentlyBuilding" or die "$main::cwd/$main::chroot_dir/CurrentlyBuilding open failed";
1186
# Package: must be first
1187
print CURRENT "Package: $pkg\nComponent: $main::component\n";
1188
print CURRENT "Suite: $main::distribution\n" if $main::distribution;
1189
print CURRENT "Purpose: $main::purpose\n" if $main::purpose;
1190
print CURRENT "Build-Debug-Symbols: yes\n" if $main::build_debug_symbols;
1193
$main::build_start_time = time;
1194
$main::pkg_fail_stage = "build";
1195
$main::sub_pid = open( PIPE, "-|" );
1196
if (!defined $main::sub_pid) {
1197
print PLOG "Can't spawn dpkg-buildpackage: $!\n";
1198
chdir( $main::cwd );
1201
if ($main::sub_pid == 0) {
1203
my $binopt = $main::build_source ? "" :
1204
$main::build_arch_all ? "-b" : "-B";
1205
my $env_cmnd = $conf::build_env_cmnd;
1206
$env_cmnd = $conf::build_env_cmnd{$pkg} if $conf::build_env_cmnd{$pkg};
1207
if ($main::chroot_dir) {
1209
$bdir =~ s/^\Q$main::chroot_dir\E//;
1210
if (-f "$main::chroot_dir/etc/ld.so.conf" &&
1211
! -r "$main::chroot_dir/etc/ld.so.conf") {
1212
system "$conf::sudo chmod a+r $main::chroot_dir/etc/ld.so.conf";
1213
print PLOG "ld.so.conf was not readable! Fixed.\n";
1215
exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
1216
"$conf::su", $main::username, "-s", "/bin/sh", "-c",
1217
"cd $bdir && PATH=$conf::path ".
1218
(defined($main::nr_processors) ?
1219
"DEB_BUILD_OPTIONS=\"parallel=".$main::nr_processors."\" " : "").
1220
(defined($main::ld_library_path) ?
1221
"LD_LIBRARY_PATH=".$main::ld_library_path." " : "").
1222
"exec $env_cmnd dpkg-buildpackage $conf::pgp_options ".
1223
"$binopt -m'$conf::maintainer_name' -r$conf::fakeroot 2>&1";
1226
if (-f "/etc/ld.so.conf" && ! -r "/etc/ld.so.conf") {
1227
system "$conf::sudo chmod a+r /etc/ld.so.conf";
1228
print PLOG "ld.so.conf was not readable! Fixed.\n";
1230
exec "$env_cmnd dpkg-buildpackage $conf::pgp_options $binopt ".
1231
"-m'$conf::maintainer_name' -r$conf::fakeroot 2>&1";
1234
$main::sub_task = "dpkg-buildpackage";
1236
# We must send the signal as root, because some subprocesses of
1237
# dpkg-buildpackage could run as root. So we have to use a shell
1238
# command to send the signal... but /bin/kill can't send to
1239
# process groups :-( So start another Perl :-)
1240
my $timeout = $conf::individual_stalled_pkg_timeout{$pkg} ||
1241
$conf::stalled_pkg_timeout;
1244
my(@timeout_times, @timeout_sigs, $last_time);
1245
$SIG{'ALRM'} = sub {
1246
my $signal = ($timed_out > 0) ? 9 : 15;
1247
system "$conf::sudo perl -e 'kill( -$signal, $main::sub_pid )'";
1248
$timeout_times[$timed_out] = time - $last_time;
1249
$timeout_sigs[$timed_out] = $signal;
1251
$timeout = 5*60; # only wait 5 minutes until next signal
1261
undef $main::sub_pid;
1266
for( $i = 0; $i < $timed_out; ++$i ) {
1267
print PLOG "Build killed with signal ", $timeout_sigs[$i],
1268
" after ", int($timeout_times[$i]/60),
1269
" minutes of inactivity\n";
1271
$main::pkg_end_time = time;
1272
my $date = `date +%Y%m%d-%H%M`;
1273
print PLOG "*"x78, "\n";
1274
print PLOG "Build finished at $date";
1275
chdir( $main::cwd );
1277
my @space_files = ("$dir");
1278
if (!$main::nolog and defined $conf::exit_hook and open TMP, '-|', "$conf::exit_hook <$main::pkg_logfile") {
1286
print PLOG "FAILED [dpkg-buildpackage died]\n";
1289
my $trans_oldfmt="$main::chroot_build_dir${pkg}_${version}_translations.tar.gz";
1290
my $trans_newfmt="$main::chroot_build_dir${pkg}_${version}_${main::arch}_translations.tar.gz";
1291
my $translations="";
1292
if (-r $trans_newfmt) {
1293
$translations = $trans_newfmt;
1294
} elsif (-r $trans_oldfmt) {
1295
$translations = $trans_oldfmt;
1297
if ($translations) {
1298
print PLOG "Publishing $translations for rosetta.\n";
1299
my $date = strftime '%Y%m%d',gmtime;
1300
my $target = "$main::HOME/public_html/translations/$date/";
1301
system "mkdir -p $target";
1302
if (system("cp",$translations,$target) != 0) {
1303
print PLOG "ERROR: Could not move $translations to $target\n";
1305
open TRANS, ">>$target/translations.txt";
1306
print TRANS "File: " . basename(${translations}) . "\n".
1307
"Distribution: ${main::archive}\n".
1308
"Release: ${main::distribution}\n".
1309
"Component: ${main::component}\n".
1311
"Version: ${version}\n\n";
1313
system("chmod -R go+rX $main::HOME/public_html/translations");
1318
my $ddebstring = "";
1319
if (-r glob("$main::chroot_build_dir/*.ddeb")) {
1320
my @ddeblist = glob("$main::chroot_build_dir/*.ddeb");
1321
$ddebtar="${pkg}_${version}_${main::arch}_ddebs.tar";
1323
$ddebstring .= basename(@ddeblist[0]) . " ";
1328
print PLOG "Publishing debug debs.\n";
1329
my $date = strftime '%Y%m%d',gmtime;
1330
my $target = "$main::HOME/public_html/ddebs/$date/";
1331
system "mkdir -p $target";
1332
if (system("tar -C $main::chroot_build_dir -chf $target/$ddebtar $ddebstring") != 0) {
1333
print PLOG "ERROR: Could not create $ddebtar in $target\n";
1335
open TRANS, ">>$target/ddebs.txt";
1336
print TRANS "File: " . basename(${ddebtar}) . "\n".
1337
"Distribution: ${main::archive}\n".
1338
"Release: ${main::distribution}\n".
1339
"Component: ${main::component}\n".
1341
"Version: ${version}\n\n";
1343
system("chmod -R go+rX $main::HOME/public_html/ddebs");
1347
if (-r "$dir/debian/files") {
1350
open( F, "<$dir/debian/files" );
1352
my $f = (split( /\s+/, $_ ))[0];
1353
push( @files, "$main::chroot_build_dir$f" );
1354
if ($main::build_arch_all) {
1355
next if ($f !~ /$main::arch\.[\w\d.-]*$/ && $f !~ /all\.[\w\d.-]*$/);
1357
next if ($f !~ /$main::arch\.[\w\d.-]*$/);
1359
push( @debs, "$main::chroot_build_dir$f" );
1360
push( @space_files, $f );
1365
print PLOG "\n$_:\n";
1366
if (!open( PIPE, "dpkg --info $_ 2>&1 |" )) {
1367
print PLOG "Can't spawn dpkg: $! -- can't dump infos\n";
1370
print PLOG $_ while( <PIPE> );
1375
print PLOG "\n$_:\n";
1376
if (!open( PIPE, "dpkg --contents $_ 2>&1 |" )) {
1377
print PLOG "Can't spawn dpkg: $! -- can't dump infos\n";
1380
print PLOG $_ while( <PIPE> );
1384
if ($main::chroot_build_dir) {
1386
system "mv", $_, "."
1387
and print PLOG "ERROR: Could not move $_ to .\n";
1392
if (-r $translations) {
1393
system("rm",$translations);
1396
$changes = "${pkg}_".
1397
($main::binNMU ? binNMU_version($sversion) : $sversion).
1398
"_$main::arch.changes";
1399
if (-r "$main::chroot_build_dir$changes") {
1400
my(@do_dists, @saved_dists);
1401
print PLOG "\n$changes:\n";
1402
open( F, "<$main::chroot_build_dir$changes" );
1403
if (open( F2, ">$changes.new" )) {
1405
if (/^Distribution:\s*(.*)\s*$/) {
1406
print PLOG "Distribution: $main::distribution\n";
1407
print F2 "Distribution: $main::distribution\n";
1411
while (length $_ > 989)
1413
my $index = rindex($_,' ',989);
1414
print PLOG substr ($_,0,$index) . "\n";
1415
$_ = ' ' . substr ($_,$index+1);
1421
rename( "$changes.new", "$changes" )
1422
or print PLOG "$changes.new could not be renamed ".
1423
"to $changes: $!\n";
1424
unlink( "$main::chroot_build_dir$changes" )
1425
if $main::chroot_build_dir;
1428
print PLOG "Cannot create $changes.new: $!\n";
1429
print PLOG "Distribution field may be wrong!!!\n";
1430
if ($main::chroot_build_dir) {
1431
system "mv", "$main::chroot_build_dir$changes", "."
1432
and print PLOG "ERROR: Could not move $_ to .\n";
1439
print PLOG "Can't find $changes -- can't dump infos\n";
1442
print PLOG "*"x78, "\n";
1443
print PLOG "Built successfully\n";
1447
check_space( @space_files );
1449
#if ($conf::purge_build_directory eq "always" ||
1450
# ($conf::purge_build_directory eq "successful" && $rv == 0)) {
1451
# print PLOG "Purging $dir\n";
1452
# system "$conf::sudo rm -rf $dir";
1455
#print PLOG "-"x78, "\n";
1456
return $rv == 0 ? 1 : 0;
1463
$main::pkg_fail_stage = "apply-patch";
1464
foreach $name ((map { $_->{'Package'} } @{$main::deps{$pkg}}),
1465
@main::global_patches) {
1466
if ($name =~ /^\*/ && exists $main::specials{$name}->{'patch'}) {
1467
if (exists $main::specials{$name}->{'patchcond'}) {
1468
print "Testing condition for $name patch:\n"
1470
if (run_script("+e",$main::specials{$name}->{'patchcond'})!=0){
1471
print PLOG "Condition for $name patch not true -- ",
1472
"not applying\n" if $name !~ /^\*\*/;
1475
print PLOG "Condition for $name patch ok\n";
1477
print PLOG "Applying $name patch\n";
1478
$main::sub_pid = open( PIPE, "|-" );
1479
if (!defined $main::sub_pid) {
1480
print PLOG "Can't spawn patch: $! -- can't patch\n";
1483
if ($main::sub_pid == 0) {
1485
open( STDOUT, ">&PLOG" );
1486
open( STDERR, ">&PLOG" );
1487
exec "patch --batch --quiet -p1 -E -N --no-backup-if-mismatch";
1489
$main::sub_task = "patch";
1491
print PIPE $main::specials{$name}->{'patch'};
1493
undef $main::sub_pid;
1494
if ($name !~ /^\*\*/ && $?) {
1495
print PLOG "FAILED [patch died]\n";
1503
sub analyze_fail_stage {
1506
return if $main::pkg_status ne "failed";
1507
return if !$main::auto_giveback;
1508
if (isin( $main::pkg_fail_stage,
1509
qw(find-dsc fetch-src unpack-check check-space install-deps-env))) {
1510
$main::pkg_status = "given-back";
1511
print PLOG "Giving back package $pkgv after failure in ".
1512
"$main::pkg_fail_stage stage.\n";
1513
chdir( $main::cwd );
1515
$cmd = "ssh -l$main::auto_giveback_user $main::auto_giveback_host "
1516
if $main::auto_giveback_host;
1517
$cmd .= "-S $main::auto_giveback_socket "
1518
if ($main::auto_giveback_socket and -S "$main::auto_giveback_socket");
1519
$cmd .= "wanna-build --give-back --no-down-propagation ".
1520
"--dist=$main::distribution";
1521
$cmd .= " --database=$main::database" if $main::database;
1522
$cmd .= " --user=$main::auto_giveback_wb_user "
1523
if $main::auto_giveback_wb_user;
1527
print PLOG "wanna-build failed with status $?\n";
1530
add_givenback( $pkgv, time );
1531
if ($main::stats_dir) {
1533
lock_file( "$main::stats_dir" );
1534
open( F, ">>$main::stats_dir/give-back" );
1537
unlock_file( "$main::stats_dir" );
1547
print "Removed $_\n" if $main::debug;
1554
my( @positive, @negative, @special, @instd, @rmvd );
1556
if (!exists $main::deps{$pkg}) {
1557
prepare_watches( [] );
1561
my $dep = $main::deps{$pkg};
1563
print "Source dependencies of $pkg: ", format_deps(@$dep), "\n";
1567
lock_file( "$main::ilock_file", 1 );
1569
print "Filtering dependencies\n" if $main::debug;
1570
if (!filter_dependencies( $dep, \@positive, \@negative, \@special )) {
1571
print PLOG "Package installation not possible\n";
1572
unlock_file( "$main::ilock_file" );
1576
print PLOG "Checking for source dependency conflicts...\n";
1577
if (!run_apt( "-s", \@instd, \@rmvd, @positive )) {
1578
print PLOG "Test what should be installed failed.\n";
1579
unlock_file( "$main::ilock_file" );
1582
# add negative deps as to be removed for checking srcdep conflicts
1583
push( @rmvd, @negative );
1585
if (@confl = check_srcdep_conflicts( \@instd, \@rmvd, \@special )) {
1586
print PLOG "Waiting for job(s) @confl to finish\n";
1588
unlock_file( "$main::ilock_file" );
1589
wait_for_srcdep_conflicts( @confl );
1593
write_srcdep_lock_file( $dep, \@special );
1595
foreach my $sp (@special) {
1596
next if $sp !~ /^\*/ || !exists $main::specials{$sp}->{'prepre'};
1597
print PLOG "Running prepre script for $sp\n";
1598
if (run_script( "-e", $main::specials{$sp}->{'prepre'} ) != 0) {
1599
print PLOG "prepre script of special dependency $sp failed\n";
1600
unlock_file( "$main::ilock_file" );
1605
print "Installing positive dependencies: @positive\n" if $main::debug;
1606
if (!run_apt( "-y", \@instd, \@rmvd, @positive )) {
1607
print PLOG "Package installation failed\n";
1608
# try to reinstall removed packages
1609
print PLOG "Trying to reinstall removed packages:\n";
1610
print "Reinstalling removed packages: @rmvd\n" if $main::debug;
1611
my (@instd2, @rmvd2);
1612
print PLOG "Failed to reinstall removed packages!\n"
1613
if !run_apt( "-y", \@instd2, \@rmvd2, @rmvd );
1614
print "Installed were: @instd2\n" if $main::debug;
1615
print "Removed were: @rmvd2\n" if $main::debug;
1616
# remove additional packages
1617
print PLOG "Trying to uninstall newly installed packages:\n";
1618
uninstall_debs( $main::chroot_dir ? "purge" : "remove", @instd );
1619
unlock_file( "$main::ilock_file" );
1622
set_installed( @instd );
1623
set_removed( @rmvd );
1625
print "Removing negative dependencies: @negative\n" if $main::debug;
1626
if (!uninstall_debs( $main::chroot_dir ? "purge" : "remove", @negative )) {
1627
print PLOG "Removal of packages failed\n";
1628
unlock_file( "$main::ilock_file" );
1631
set_removed( @negative );
1633
my $fail = check_dependencies( $dep );
1635
print PLOG "After installing, the following source dependencies are ".
1636
"still unsatisfied:\n$fail\n";
1637
unlock_file( "$main::ilock_file" );
1641
foreach my $sp (@special) {
1642
next if $sp !~ /^\*/ ||
1643
(!exists $main::specials{$sp}->{'pre'} &&
1644
!exists $main::specials{$sp}->{'post'} &&
1645
!exists $main::specials{$sp}->{'unpack'});
1646
if (exists $main::specials{$sp}->{'unpack'}) {
1647
my $s = $main::specials{$sp}->{'unpack'};
1650
my @s = split( /\s+/, $s );
1652
print PLOG "Unpacking special sources $sp: @s\n";
1653
if (!(@rem = unpack_special_source( @s ))) {
1654
print PLOG "unpacking of special dependency sources for $sp failed\n";
1655
unlock_file( "$main::ilock_file" );
1658
$main::changes->{'unpacked'}->{$sp} = \@rem;
1660
if (exists $main::specials{$sp}->{'pre'}) {
1661
print PLOG "Running pre script for $sp\n";
1662
$main::changes->{'specials'}->{$sp} = 1;
1663
if (run_script( "-e", $main::specials{$sp}->{'pre'} ) != 0) {
1664
print PLOG "pre script of special dependency $sp failed\n";
1665
unlock_file( "$main::ilock_file" );
1672
if (open( F, "| $conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::dpkg --set-selections")) {
1673
foreach my $tpkg (@instd) {
1674
print F $tpkg . " purge\n";
1678
print PLOG "$conf::dpkg --set-selections failed";
1682
unlock_file( "$main::ilock_file" );
1684
prepare_watches( $dep, @instd );
1688
sub unpack_special_source {
1693
foreach my $s (@s) {
1697
if (!open( PIPE, "$conf::apt_get $main::chroot_apt_options ".
1698
"--only-source -q -d source $s 2>&1 </dev/null |" )) {
1699
print PLOG "Can't open pipe to apt-get: $!\n";
1703
$dsc = "$1_$2.dsc" if /(\S+) (?:[^:]+:)?(\S+) \(dsc\)/;
1708
print PLOG "Apt-get of special unpack sources failed\n";
1711
push( @files, $dsc );
1712
if (!open( F, "<$dsc" )) {
1713
print PLOG "Can't open $dsc: $!\n";
1717
{ local($/); $dsctext = <F>; }
1720
$dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1;
1721
push(@files, map { (split( /\s+/, $_ ))[3] } split( "\n", $files ));
1724
my $pid = open( PIPE, "-|" );
1725
if (!defined $pid) {
1726
print PLOG "Can't spawn dpkg-source: $! -- special unpack failed\n";
1731
if ($main::chroot_build_dir && !chdir( $main::chroot_build_dir )) {
1732
print PLOG "Couldn't cd to $main::chroot_build_dir: $! -- special unpack failed\n";
1735
exec "$conf::dpkg_source -sn -x $main::cwd/$dsc 2>&1";
1740
$dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ in (\S+)/;
1744
print PLOG "dpkg-source failure -- special unpack failed\n";
1747
push( @dirs, "$main::chroot_build_dir$dir" );
1755
system( "rm", "-rf", @dirs );
1759
sub wait_for_srcdep_conflicts {
1763
sleep( $conf::srcdep_lock_wait*60 );
1768
if (-f "$conf::srcdep_lock_dir/$_") {
1769
if (kill( 0, $pid ) == 0 && $! == ESRCH) {
1770
print PLOG "Ignoring stale src-dep lock $_\n";
1771
unlink( "$conf::srcdep_lock_dir/$_" ) or
1772
print PLOG "Cannot remove $conf::srcdep_lock_dir/$_: $!\n";
1784
sub uninstall_deps {
1785
my( @pkgs, @instd, @rmvd );
1787
lock_file( "$main::ilock_file", 1 );
1789
@pkgs = keys %{$main::changes->{'removed'}};
1790
print "Reinstalling removed packages: @pkgs\n" if $main::debug;
1791
print PLOG "Failed to reinstall removed packages!\n"
1792
if !run_apt( "-y", \@instd, \@rmvd, @pkgs );
1793
print "Installed were: @instd\n" if $main::debug;
1794
print "Removed were: @rmvd\n" if $main::debug;
1795
unset_removed( @instd );
1796
unset_installed( @rmvd );
1798
@pkgs = keys %{$main::changes->{'installed'}};
1799
print "Removing installed packages: @pkgs\n" if $main::debug;
1800
print PLOG "Failed to remove installed packages!\n"
1801
if !uninstall_debs( "purge", @pkgs );
1802
unset_installed( @pkgs );
1804
unlock_file( "$main::ilock_file" );
1807
sub uninstall_debs {
1812
print "Uninstalling packages: @_\n" if $main::debug;
1813
print PLOG " $conf::sudo dpkg --$mode @_\n";
1816
if (!open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::dpkg --$mode @_ 2>&1 </dev/null |")) {
1817
print PLOG "Can't open pipe to dpkg: $!\n";
1826
if ($output =~ /status database area is locked/mi) {
1827
print PLOG "Another dpkg is running -- retrying later\n";
1832
print PLOG "dpkg run to remove packages (@_) failed!\n" if $?;
1839
print "Running post scripts of special dependencies:\n" if $main::debug;
1840
foreach $sp (keys %{$main::changes->{'specials'}}) {
1841
print PLOG "Running post script for $sp\n";
1842
if (run_script( "-e", $main::specials{$sp}->{'post'} ) != 0) {
1843
print PLOG "post script of special dependency $sp failed\n";
1845
delete $main::changes->{'specials'}->{$sp};
1847
foreach $sp (keys %{$main::changes->{'unpacked'}}) {
1848
my @dirs = @{$main::changes->{'unpacked'}->{$sp}};
1849
print PLOG "Removing special unpacked sources for $sp: @dirs\n";
1850
system "rm", "-rf", @dirs;
1851
delete $main::changes->{'unpacked'}->{$sp};
1858
my $inst_ret = shift;
1859
my $rem_ret = shift;
1860
my @to_install = @_;
1861
my( $msgs, $status, $pkgs, $rpkgs );
1863
local (%ENV) = %ENV; # make local environment
1864
# hardwire frontend for debconf to non-interactive
1865
$ENV{'DEBIAN_FRONTEND'} = "noninteractive";
1869
return 1 if !@to_install;
1871
print PLOG " $conf::sudo $conf::apt_get --purge $main::chroot_apt_op -q $mode install @to_install\n"
1874
# redirection of stdin from /dev/null so that conffile question are
1875
# treated as if RETURN was pressed.
1876
# dpkg since 1.4.1.18 issues an error on the conffile question if it reads
1877
# EOF -- hardwire the new --force-confold option to avoid the questions.
1878
if (!open( PIPE, "$conf::sudo /usr/sbin/chroot ".
1879
"$main::chroot_dir $conf::apt_get --purge ".
1880
($main::new_dpkg ? "-o DPkg::Options::=--force-confold " : "").
1881
"-q $mode install @to_install 2>&1 </dev/null |" )) {
1882
print PLOG "Can't open pipe to apt-get: $!\n";
1887
print PLOG $_ if $mode ne "-s" || $main::debug;
1892
if ($status != 0 && $msgs =~ /^E: Packages file \S+ (has changed|is out of sync)/mi) {
1893
print PLOG "$conf::sudo $conf::apt_get $main::chroot_apt_op -q update\n";
1894
if (!open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_get -q update 2>&1 |" )) {
1895
print PLOG "Can't open pipe to apt-get: $!\n";
1904
print PLOG "apt-get update failed\n" if $?;
1909
if ($status != 0 && $msgs =~ /^Package (\S+) is a virtual package provided by:\n((^\s.*\n)*)/mi) {
1910
my $to_replace = $1;
1912
foreach (split( "\n", $2 )) {
1914
push( @providers, (split( /\s+/, $_ ))[0] );
1916
print PLOG "$to_replace is a virtual package provided by: @providers\n";
1918
if (@providers == 1) {
1919
$selected = $providers[0];
1920
print PLOG "Using $selected (only possibility)\n";
1922
elsif (exists $conf::alternatives{$to_replace}) {
1923
$selected = $conf::alternatives{$to_replace};
1924
print PLOG "Using $selected (selected in sbuildrc)\n";
1927
$selected = $providers[0];
1928
print PLOG "Using $selected (no default, using first one)\n";
1931
@to_install = grep { $_ ne $to_replace } @to_install;
1932
push( @to_install, $selected );
1937
if ($status != 0 && ($msgs =~ /^E: Could( not get lock|n.t lock)/mi ||
1938
$msgs =~ /^dpkg: status database area is locked/mi)) {
1939
print PLOG "Another apt-get or dpkg is running -- retrying later\n";
1944
# check for errors that are probably caused by something broken in
1945
# the build environment, and give back the packages.
1946
if ($status != 0 && $mode ne "-s" &&
1947
(($msgs =~ /^E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem./mi) ||
1948
($msgs =~ /^dpkg: parse error, in file `\/.+\/var\/lib\/dpkg\/(?:available|status)' near line/mi) ||
1949
($msgs =~ /^E: Unmet dependencies. Try 'apt-get -f install' with no packages \(or specify a solution\)\./mi))) {
1950
print PLOG "Build environment unusable, giving back\n";
1951
$main::pkg_fail_stage = "install-deps-env";
1954
if ($status != 0 && $mode ne "-s" &&
1955
(($msgs =~ /^E: Unable to fetch some archives, maybe run apt-get update or try with/mi))) {
1956
print PLOG "Unable to fetch build-depends\n";
1957
$main::pkg_fail_stage = "install-deps-env";
1960
$pkgs = $rpkgs = "";
1961
if ($msgs =~ /NEW packages will be installed:\n((^[ ].*\n)*)/mi) {
1962
($pkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m;
1965
if ($msgs =~ /packages will be REMOVED:\n((^[ ].*\n)*)/mi) {
1966
($rpkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m;
1969
@$inst_ret = split( /\s+/, $pkgs );
1970
@$rem_ret = split( /\s+/, $rpkgs );
1972
print PLOG "apt-get failed.\n" if $status && $mode ne "-s";
1973
return $mode eq "-s" || $status == 0;
1976
sub filter_dependencies {
1977
my $dependencies = shift;
1978
my $pos_list = shift;
1979
my $neg_list = shift;
1980
my $special_list = shift;
1981
my($dep, $d, $name, %names);
1983
print PLOG "Checking for already installed source dependencies...\n";
1985
@$pos_list = @$neg_list = @$special_list = ();
1986
foreach $d (@$dependencies) {
1987
my $name = $d->{'Package'};
1988
$names{$name} = 1 if $name !~ /^\*/;
1989
foreach (@{$d->{'Alternatives'}}) {
1990
my $name = $_->{'Package'};
1991
$names{$name} = 1 if $name !~ /^\*/;
1994
my $status = get_dpkg_status( keys %names );
1996
foreach $dep (@$dependencies) {
1997
$name = $dep->{'Package'};
1999
if ($name =~ /^\*/) {
2001
if (exists $main::specials{$name}->{'condition'}) {
2002
print "Testing condition for special dependency $name:\n"
2004
if (run_script("+e",$main::specials{$name}->{'condition'})!=0){
2005
print "Condition false -> not running scripts\n"
2010
push( @$special_list, $name ) if $doit;
2013
my $stat = $status->{$name};
2014
if ($dep->{'Neg'}) {
2015
if ($stat->{'Installed'}) {
2016
my ($rel, $vers) = ($dep->{'Rel'}, $dep->{'Version'});
2017
my $ivers = $stat->{'Version'};
2018
if (!$rel || version_cmp( $ivers, $rel, $vers )){
2019
print "$name: neg dep, installed, not versioned or ",
2020
"version relation satisfied --> remove\n" if $main::debug;
2021
print PLOG "$name: installed (negative dependency)";
2022
print PLOG " (bad version $ivers $rel $vers)"
2025
push( @$neg_list, $name );
2028
print PLOG "$name: installed (negative dependency)",
2029
"(but version ok $ivers $rel $vers)\n";
2033
print "$name: neg dep, not installed\n" if $main::debug;
2034
print PLOG "$name: already deinstalled\n";
2039
my $is_satisfied = 0;
2040
my $installable = "";
2041
my $upgradeable = "";
2042
my $downgradeable = "";
2043
foreach $d ($dep, @{$dep->{'Alternatives'}}) {
2044
my ($name, $rel, $vers) =
2045
($d->{'Package'}, $d->{'Rel'}, $d->{'Version'});
2046
my $stat = $status->{$name};
2047
if (!$stat->{'Installed'}) {
2048
print "$name: pos dep, not installed\n" if $main::debug;
2049
print PLOG "$name: missing\n";
2050
my $exists = package_exists($name);
2051
print PLOG "$name: does not exist\n" if not $exists;
2052
$installable = $name if !$installable and $exists;
2055
my $ivers = $stat->{'Version'};
2056
if (!$rel || version_cmp( $ivers, $rel, $vers )) {
2057
print "$name: pos dep, installed, no versioned dep or ",
2058
"version ok\n" if $main::debug;
2059
print PLOG "$name: already installed ($ivers";
2060
print PLOG " $rel $vers is satisfied"
2066
print "$name: vers dep, installed $ivers ! $rel $vers\n"
2068
print PLOG "$name: non-matching version installed ",
2069
"($ivers ! $rel $vers)\n";
2071
($rel eq '=' && version_cmp($ivers, '>>', $vers))) {
2072
print "$name: would be a downgrade!\n" if $main::debug;
2073
print PLOG "$name: would have to downgrade!\n";
2074
$downgradeable = $name if !$downgradeable;
2077
$upgradeable = $name if !$upgradeable;
2080
if (!$is_satisfied) {
2082
print "using $upgradeable for upgrade\n" if $main::debug;
2083
push( @$pos_list, $upgradeable );
2085
elsif ($installable) {
2086
print "using $installable for install\n" if $main::debug;
2087
push( @$pos_list, $installable );
2089
elsif ($downgradeable) {
2090
print PLOG "To satisfy this dependency the package(s) would ",
2092
"to be downgraded; this is not implemented.\n";
2096
# None of the build-deps exist. Return the
2097
# first one so that we get a useful dep-wait.
2098
$installable = $dep->{'Package'};
2099
print "using $installable for install (does not exist)\n" if $main::debug;
2100
push( @$pos_list, $installable );
2108
sub check_dependencies {
2109
my $dependencies = shift;
2111
my($dep, $d, $name, %names);
2113
print PLOG "Checking correctness of source dependencies...\n";
2115
foreach $d (@$dependencies) {
2116
my $name = $d->{'Package'};
2117
$names{$name} = 1 if $name !~ /^\*/;
2118
foreach (@{$d->{'Alternatives'}}) {
2119
my $name = $_->{'Package'};
2120
$names{$name} = 1 if $name !~ /^\*/;
2123
foreach $name (@main::toolchain_pkgs) {
2126
my $status = get_dpkg_status( keys %names );
2128
foreach $dep (@$dependencies) {
2129
$name = $dep->{'Package'};
2130
next if $name =~ /^\*/;
2131
my $stat = $status->{$name};
2132
if ($dep->{'Neg'}) {
2133
if ($stat->{'Installed'}) {
2134
if (!$dep->{'Rel'}) {
2135
$fail .= "$name(still installed) ";
2137
elsif (version_cmp($stat->{'Version'}, $dep->{'Rel'},
2138
$dep->{'Version'})) {
2139
$fail .= "$name(inst $stat->{'Version'} $dep->{'Rel'} ".
2140
"conflicted $dep->{'Version'})\n";
2145
my $is_satisfied = 0;
2147
foreach $d ($dep, @{$dep->{'Alternatives'}}) {
2148
my $name = $d->{'Package'};
2149
my $stat = $status->{$name};
2150
if (!$stat->{'Installed'}) {
2151
$f =~ s/ $/\|/ if $f;
2152
$f .= "$name(missing) ";
2154
elsif ($d->{'Rel'} &&
2155
!version_cmp( $stat->{'Version'}, $d->{'Rel'},
2156
$d->{'Version'} )) {
2157
$f =~ s/ $/\|/ if $f;
2158
$f .= "$name(inst $stat->{'Version'} ! $d->{'Rel'} ".
2159
"wanted $d->{'Version'}) ";
2165
if (!$is_satisfied) {
2171
if (!$fail && @main::toolchain_pkgs) {
2172
print PLOG "Toolchain package versions:";
2173
foreach $name (@main::toolchain_pkgs) {
2174
print PLOG ' ' . $name . '_' . $status->{$name}->{'Version'};
2182
sub get_dpkg_status {
2188
print "Requesting dpkg status for packages: @interest\n"
2190
if (!open( STATUS, "<$main::chroot_dir/var/lib/dpkg/status" )) {
2191
print PLOG "Can't open $main::chroot_dir/var/lib/dpkg/status: $!\n";
2196
my( $pkg, $status, $version, $provides );
2197
/^Package:\s*(.*)\s*$/mi and $pkg = $1;
2198
/^Status:\s*(.*)\s*$/mi and $status = $1;
2199
/^Version:\s*(.*)\s*$/mi and $version = $1;
2200
/^Provides:\s*(.*)\s*$/mi and $provides = $1;
2202
print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2203
"no Package: field\n";
2206
print "$pkg ($version) status: $status\n" if $main::debug >= 2;
2208
print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2209
"no Status: field for package $pkg\n";
2212
if ($status !~ /\sinstalled$/) {
2213
$result{$pkg}->{'Installed'} = 0
2214
if !(exists($result{$pkg}) &&
2215
$result{$pkg}->{'Version'} eq '=*=PROVIDED=*=');
2219
print PLOG "sbuild: parse error in $main::chroot_dir/var/lib/dpkg/status: ",
2220
"no Version: field for package $pkg\n";
2223
$result{$pkg} = { Installed => 1, Version => $version }
2224
if isin( $pkg, @interest );
2226
foreach (split( /\s*,\s*/, $provides )) {
2227
$result{$_} = { Installed => 1, Version => '=*=PROVIDED=*=' }
2228
if (isin( $_, @interest ) &&
2229
$result{$_}->{'Installed'} != 1);
2241
if ($v1 eq "=*=PROVIDED=*=") {
2245
system "$conf::dpkg", "--compare-versions", $v1, $rel, $v2;
2254
if ($main::debug >= 2) {
2255
$x_mode = "set -x -v\n";
2257
elsif ($main::debug) {
2258
print "Running script:\n ",
2259
join( "\n ", split( "\n", "set $e_mode\n$script" )), "\n";
2262
if (!defined $pid) {
2263
print PLOG "Can't fork: $! -- can't execute script\n";
2268
open( STDOUT, ">&PLOG" );
2269
open( STDERR, ">&PLOG" );
2270
if ($main::chroot_dir) {
2271
exec "$conf::sudo", "/usr/sbin/chroot", "$main::cwd/$main::chroot_dir",
2272
"$conf::su", $main::username, "-s", "/bin/sh", "-c",
2273
"cd /build/$main::username\nset $e_mode\n$x_mode$script";
2276
exec "/bin/sh", "-c", "set $e_mode\n$x_mode$script";
2278
die "Can't exec /bin/sh: $!\n";
2281
print "Script return value: $?\n" if $main::debug;
2291
open( F, $fname = "<$conf::source_dependencies-$main::distribution" )
2292
or open( F, $fname = "<$conf::source_dependencies" )
2293
or die "Cannot open $conf::source_dependencies: $!\n";
2294
$fname = substr( $fname, 1 );
2295
print "Reading source dependencies from $fname\n"
2299
next if /^\s*$/ || /^\s*#/;
2305
if (/^(\*\*?[\w\d.+-]+):\s*$/) {
2306
# is a special definition
2308
get_special( $fname, $sp, \*F );
2311
if (/^abbrev\s+([\w\d.+-]+)\s*=\s*(.*)\s*$/) {
2312
my ($abbrev, $def) = ($1, $2);
2313
parse_one_srcdep( $abbrev, $def, \%main::abbrevs );
2316
if (!/^([a-zA-Z\d.+-]+):\s*(.*)\s*$/) {
2317
warn "Syntax error in line $. in $fname\n";
2320
my( $pkg, $deps ) = ($1, $2);
2321
if (exists $main::deps{$pkg}) {
2322
warn "Ignoring double entry for package $pkg at line $. ".
2326
next if !isin( $pkg, @for_pkgs );
2327
parse_one_srcdep( $pkg, $deps, \%main::deps );
2331
foreach (@main::manual_srcdeps) {
2332
if (!/^([fa])([a-zA-Z\d.+-]+):\s*(.*)\s*$/) {
2333
warn "Syntax error in manual source dependency: ",
2334
substr( $_, 1 ), "\n";
2337
my ($mode, $pkg, $deps) = ($1, $2, $3);
2338
next if !isin( $pkg, @for_pkgs );
2339
@{$main::deps{$pkg}} = () if $mode eq 'f';
2340
parse_one_srcdep( $pkg, $deps, \%main::deps );
2343
# substitute abbrevs and warn about undefined special deps
2344
my( $pkg, $i, %warned );
2345
foreach $pkg (keys %main::deps) {
2347
my $dl = $main::deps{$pkg};
2348
for( $i = 0; $i < @$dl; ++$i ) {
2349
my $dep = $dl->[$i];
2350
my $name = $dep->{'Package'};
2351
if ($name =~ /^\*/) {
2352
if (!$warned{$name} && !exists $main::specials{$name}) {
2353
warn "Warning: $pkg: No definition for special ",
2354
"dependency $name!\n";
2358
elsif (defined $main::abbrevs{$name}) {
2359
my @l = @{$main::abbrevs{$name}};
2360
if (defined $dep->{'Alternatives'}) {
2361
warn "Warning: $pkg: abbrev $name not allowed ",
2365
if ($dep->{'Neg'}) {
2366
warn "Warning: $pkg: Negation of abbrev $name ",
2370
if ($dep->{'Rel'}) {
2371
warn "Warning: $pkg: No relation with abbrev $name ",
2375
if (my $ov = $dep->{'Override'}) {
2376
@l = map { my $x = copy($_);
2377
$x->{'Override'} = $ov; $x } @l;
2379
splice @$dl, $i, 1, @l;
2382
elsif (defined $dep->{'Alternatives'}) {
2384
foreach $alt (@{$dep->{'Alternatives'}}) {
2385
if (defined $main::abbrevs{$alt->{'Package'}}) {
2386
warn "Warning: $pkg: abbrev $alt->{'Package'} not ",
2387
"allowed in alternative\n";
2400
if (ref($r) eq "HASH") {
2402
foreach (keys %$r) {
2403
$new->{$_} = copy($r->{$_});
2406
elsif (ref($r) eq "ARRAY") {
2409
for( $i = 0; $i < @$r; ++$i ) {
2410
$new->[$i] = copy($r->[$i]);
2417
die "unknown ref type in copy\n";
2423
sub merge_pkg_build_deps {
2425
my $depends = shift;
2426
my $dependsi = shift;
2427
my $conflicts = shift;
2428
my $conflictsi = shift;
2431
print PLOG "** Using build dependencies supplied by package:\n";
2432
print PLOG "Build-Depends: $depends\n" if $depends;
2433
print PLOG "Build-Depends-Indep: $dependsi\n" if $dependsi;
2434
print PLOG "Build-Conflicts: $conflicts\n" if $conflicts;
2435
print PLOG "Build-Conflicts-Indep: $conflictsi\n" if $conflictsi;
2437
my $old_deps = copy($main::deps{$pkg});
2438
# keep deps from the central file marked as overrides (& prefix)
2439
if ( $main::useSNAP ) {
2440
$dep->{'Package'} = "gcc-snapshot";
2441
$dep->{'Override'} = 1;
2442
push( @{$main::deps{$pkg}}, $dep );
2444
foreach $dep (@{$main::deps{$pkg}}) {
2445
if ($dep->{'Override'}) {
2446
print PLOG "Added override: ",
2447
(map { ($_->{'Neg'} ? "!" : "") .
2449
($_->{'Rel'} ? " ($_->{'Rel'} $_->{'Version'})":"") }
2450
scalar($dep), @{$dep->{'Alternatives'}}), "\n";
2455
$conflicts = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflicts ));
2456
$conflictsi = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflictsi ));
2458
my $deps = $depends . ", " . $conflicts;
2459
$deps .= ", " . $dependsi . ", " . $conflictsi if $main::build_arch_all;
2460
# For the moment, we treat multiarch-annotated build-dependencies as
2461
# the same as any others because we're not implementing a
2464
$deps =~ s/:native//g;
2466
@{$main::deps{$pkg}} = @l;
2467
print "Merging pkg deps: $deps\n" if $main::debug;
2468
parse_one_srcdep( $pkg, $deps, \%main::deps );
2470
my $missing = (cmp_dep_lists( $old_deps, $main::deps{$pkg} ))[1];
2472
# read list of build-essential packages (if not yet done) and expand their
2473
# dependencies (those are implicitly essential)
2474
if (!defined($main::deps{'ESSENTIAL'})) {
2475
my $ess = read_build_essential();
2476
parse_one_srcdep( 'ESSENTIAL', $ess, \%main::deps );
2478
my ($exp_essential, $exp_pkgdeps, $filt_essential, $filt_pkgdeps);
2479
$exp_essential = expand_dependencies( $main::deps{'ESSENTIAL'} );
2480
print "Dependency-expanded build essential packages:\n",
2481
format_deps(@$exp_essential), "\n" if $main::debug;
2483
# populate toolchain_pkgs from toolchain_regexes and essential packages.
2484
@main::toolchain_pkgs = ();
2485
foreach my $tpkg (@$exp_essential) {
2486
foreach my $regex (@conf::toolchain_regex) {
2487
push @main::toolchain_pkgs,$tpkg->{'Package'}
2488
if $tpkg->{'Package'} =~ m,^$regex,;
2491
return if !@$missing;
2493
# remove missing central deps that are essential
2494
($filt_essential, $missing) = cmp_dep_lists( $missing, $exp_essential );
2495
print PLOG "** Filtered missing central deps that are build-essential:\n",
2496
format_deps(@$filt_essential), "\n"
2497
if @$filt_essential;
2499
# if some build deps are virtual packages, replace them by an alternative
2500
# over all providing packages
2501
$exp_pkgdeps = expand_virtuals( $main::deps{$pkg} );
2502
print "Provided-expanded build deps:\n",
2503
format_deps(@$exp_pkgdeps), "\n" if $main::debug;
2505
# now expand dependencies of package build deps
2506
$exp_pkgdeps = expand_dependencies( $exp_pkgdeps );
2507
print "Dependency-expanded build deps:\n",
2508
format_deps(@$exp_pkgdeps), "\n" if $main::debug;
2509
$main::additional_deps = $exp_pkgdeps;
2511
# remove missing central deps that are dependencies of build deps
2512
($filt_pkgdeps, $missing) = cmp_dep_lists( $missing, $exp_pkgdeps );
2513
print PLOG "** Filtered missing central deps that are dependencies of ",
2514
"or provide build-deps:\n",
2515
format_deps(@$filt_pkgdeps), "\n"
2518
# remove comment package names
2519
push( @$main::additional_deps,
2520
grep { $_->{'Neg'} && $_->{'Package'} =~ /^needs-no-/ } @$missing );
2521
$missing = [ grep { !($_->{'Neg'} &&
2522
($_->{'Package'} =~ /^this-package-does-not-exist/ ||
2523
$_->{'Package'} =~ /^needs-no-/)) } @$missing ];
2525
print PLOG "**** Warning:\n",
2526
"**** The following central src deps are ",
2527
"(probably) missing:\n ", format_deps(@$missing), "\n"
2534
my ($dep, @common, @missing);
2536
foreach $dep (@$list1) {
2539
if ($dep->{'Neg'}) {
2541
if ($dep->{'Package'} eq $_->{'Package'} && $_->{'Neg'}) {
2548
my $al = get_altlist($dep);
2550
if (is_superset( get_altlist($_), $al )) {
2558
push( @common, $dep );
2561
push( @missing, $dep );
2564
return (\@common, \@missing);
2571
foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2572
$l{$_->{'Package'}} = 1 if !$_->{'Neg'};
2581
foreach (keys %$l2) {
2582
return 0 if !exists $l1->{$_};
2587
sub read_build_essential {
2591
if (open( F, "$main::chroot_dir/usr/share/doc/build-essential/essential-packages-list" )) {
2597
push( @essential, $_ ) if $_ !~ /^\s*$/;
2602
warn "Cannot open $main::chroot_dir/usr/share/doc/build-essential/essential-packages-list: $!\n";
2605
if (open( F, "$main::chroot_dir/usr/share/doc/build-essential/list" )) {
2607
last if $_ eq "BEGIN LIST OF PACKAGES\n";
2611
last if $_ eq "END LIST OF PACKAGES";
2612
next if /^\s/ || /^$/;
2613
push( @essential, $_ );
2618
warn "Cannot open $main::chroot_dir/usr/share/doc/build-essential/list: $!\n";
2621
return join( ", ", @essential );
2624
sub expand_dependencies {
2626
my (@to_check, @result, %seen, $check, $dep);
2628
foreach $dep (@$dlist) {
2629
next if $dep->{'Neg'} || $dep->{'Package'} =~ /^\*/;
2630
foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2631
my $name = $_->{'Package'};
2632
push( @to_check, $name );
2635
push( @result, copy($dep) );
2638
while( @to_check ) {
2639
my $deps = get_dependencies( @to_check );
2640
my @check = @to_check;
2642
foreach $check (@check) {
2643
foreach (split( /\s*,\s*/, $deps->{$check} )) {
2644
foreach (split( /\s*\|\s*/, $_ )) {
2645
my $pkg = (/^([^\s([]+)/)[0];
2647
push( @to_check, $pkg );
2648
push( @result, { Package => $pkg, Neg => 0 } );
2659
sub expand_virtuals {
2661
my ($dep, %names, @new_dlist);
2663
foreach $dep (@$dlist) {
2664
foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2665
$names{$_->{'Package'}} = 1;
2668
my $provided_by = get_virtuals( keys %names );
2670
foreach $dep (@$dlist) {
2672
foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
2673
my $name = $_->{'Package'};
2675
if (exists $provided_by->{$name}) {
2676
foreach( keys %{$provided_by->{$name}} ) {
2681
my @l = map { { Package => $_, Neg => 0 } } keys %seen;
2684
push( @{$l->{'Alternatives'}}, $_ );
2686
push( @new_dlist, $l );
2692
sub get_dependencies {
2696
open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_cache show @_ 2>&1 |" )
2697
or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2700
my ($name, $dep, $predep);
2701
/^Package:\s*(.*)\s*$/mi and $name = $1;
2702
next if !$name || $deps{$name};
2703
/^Depends:\s*(.*)\s*$/mi and $dep = $1;
2704
/^Pre-Depends:\s*(.*)\s*$/mi and $predep = $1;
2705
$dep .= ", " if $dep && $predep;
2707
$deps{$name} = $dep;
2710
die "$conf::apt_cache exit status $?\n" if $?;
2718
open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir $conf::apt_cache showpkg @_ 2>&1 |" )
2719
or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2724
if (/^Package:\s*(\S+)\s*$/) {
2727
elsif (/^Reverse Provides: $/) {
2730
elsif ($in_rprov && /^(\w+):\s/) {
2733
elsif ($in_rprov && /^(\S+)\s*\S+\s*$/) {
2734
$provided_by{$name}->{$1} = 1;
2738
die "$conf::apt_cache exit status $?\n" if $?;
2740
return \%provided_by;
2743
# Try to figure out if a package exists. We need to take account of virtual
2744
# packages, so showpkg is the best tool I can think of; but that shows
2745
# packages which only exist as (reverse) dependencies. As such, we make
2746
# sure that either Versions: or Reverse Provides: has some content.
2747
sub package_exists {
2750
open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir ".
2751
"$conf::apt_cache showpkg @_ 2>&1 |" )
2752
or die "Cannot start $conf::apt_cache $main::chroot_apt_op: $!\n";
2754
my $in_versions = 0;
2758
if (/^Package:\s*(\S+)\s*$/) {
2761
elsif (/^Versions: $/) {
2765
elsif (/^Reverse Provides: $/) {
2769
elsif (($in_versions || $in_rprov) && /^(\w.*):\s/) {
2773
elsif (($in_versions || $in_rprov) && /^\S/) {
2778
if (defined $name and $real) {
2785
sub parse_one_srcdep {
2790
$deps =~ s/^\s*(.*)\s*$/$1/;
2791
foreach (split( /\s*,\s*/, $deps )) {
2798
my @alts = split( /\s*\|\s*/, $_ );
2799
my $special_seen = 0;
2802
if (!/^([^\s([]+)\s*(\(\s*([<=>]+)\s*(\S+)\s*\))?(\s*\[([^]]+)\])?/) {
2803
warn "Warning: syntax error in dependency '$_' of $pkg\n";
2806
my( $dep, $rel, $relv, $archlist ) = ($1, $3, $4, $6);
2808
$archlist =~ s/^\s*(.*)\s*$/$1/;
2809
my @archs = split( /\s+/, $archlist );
2810
my ($use_it, $ignore_it, $include) = (0, 0, 0);
2812
# Use 'dpkg-architecture' to support architecture
2815
if (system("$conf::sudo", "/usr/sbin/chroot",
2816
"$main::cwd/$main::chroot_dir",
2817
"dpkg-architecture", "-a".$main::arch, "-i".substr($_, 1)) eq 0) {
2822
if (system("$conf::sudo", "/usr/sbin/chroot",
2823
"$main::cwd/$main::chroot_dir",
2824
"dpkg-architecture", "-a".$main::arch, "-i".$_) eq 0) {
2830
warn "Warning: inconsistent arch restriction on ",
2831
"$pkg: $dep depedency\n"
2832
if $ignore_it && $use_it;
2833
next if $ignore_it || ($include && !$use_it);
2835
if ($dep =~ /^\*/) {
2836
warn "Warning: $pkg: ignoring version relation on ".
2837
"special dependency $dep\n"
2839
push( @l, { Package => $dep, Override => 1 } );
2849
if ($conf::srcdep_over{$dep}) {
2850
if ($main::verbose) {
2851
print PLOG "Replacing source dep $dep";
2852
print PLOG " ($rel $relv)" if $relv;
2853
print PLOG " with $conf::srcdep_over{$dep}[0]";
2854
print PLOG " ($conf::srcdep_over{$dep}[1] $conf::srcdep_over{$dep}[2])"
2855
if $conf::srcdep_over{$dep}[1];
2858
$dep = $conf::srcdep_over{$dep}[0];
2859
$rel = $conf::srcdep_over{$dep}[1];
2860
$relv = $conf::srcdep_over{$dep}[2];
2862
my $h = { Package => $dep, Neg => $neg };
2863
if ($rel && $relv) {
2865
$h->{'Version'} = $relv;
2867
$h->{'Override'} = $override if $override;
2870
if (@alts > 1 && $special_seen) {
2871
warn "Warning: $pkg: alternatives with special dependencies ",
2872
"forbidden -- skipped\n";
2874
elsif (@alts > 1 && $neg_seen) {
2875
warn "Warning: $pkg: alternatives with negative dependencies ",
2876
"forbidden -- skipped\n";
2881
push( @{$l->{'Alternatives'}}, $_ );
2883
push( @{$hash->{$pkg}}, $l );
2895
if (/^\s*(\w+)\s*\{\s*$/) {
2897
warn "Syntax error in line $. in $fname:\n";
2898
warn " Start of special subsection inside ".
2903
$main::specials{$sp}->{$sub} = "";
2906
elsif (/^\s*\}\s*$/) {
2908
warn "Syntax error in line $. in $fname:\n";
2909
warn " } outside of special subsection\n";
2916
$main::specials{$sp}->{$sub} .= $_;
2919
warn "Syntax error in line $. in $fname:\n";
2920
warn " Subsection start expected\n";
2924
warn "Syntax error in line $. in $fname:\n";
2925
warn " Subsection not finished with }\n";
2928
push( @main::global_patches, $sp ) if $sp =~ /^\*\*/;
2933
my $date = `date +%Y%m%d-%H%M`;
2937
open( LOG, ">&STDOUT" );
2938
open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
2943
$main::main_logfile = "build-$date.log";
2945
if ($main::verbose) {
2947
($pid = open( LOG, "|-")) || exec "tee $main::main_logfile";
2948
if (!defined $pid) {
2949
warn "Cannot open pipe to 'tee $main::main_logfile': $!\n";
2952
$main::tee_pid = $pid;
2956
open( LOG, ">$main::main_logfile" )
2957
or warn "Cannot open log file $main::main_logfile: $!\n";
2959
select( (select( LOG ), $| = 1)[0] );
2960
open( STDOUT, ">&LOG" ) or warn "Can't redirect stdout\n";
2961
open( STDERR, ">&LOG" ) or warn "Can't redirect stderr\n";
2962
open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
2966
my $date = `date +%Y%m%d-%H%M`;
2969
kill( 15, $main::tee_pid ) if $main::verbose;
2971
if (!$main::nolog && !$main::verbose &&
2972
-s $main::main_logfile && $conf::mailto) {
2973
send_mail( $conf::mailto, "Log from sbuild $date",
2974
$main::main_logfile ) if $conf::mailto;
2976
elsif (!$main::nolog && !$main::verbose && ! -s $main::main_logfile) {
2977
unlink( $main::main_logfile );
2982
my $date = `date +%Y%m%d-%H%M`;
2986
open( PLOG, ">&STDOUT" );
2989
$pkg = basename( $pkg );
2990
if ($main::binNMU) {
2991
$pkg =~ /^([^_]+)_([^_]+)(.*)$/;
2992
$pkg = $1."_".binNMU_version($2);
2993
$main::binNMU_name = $pkg;
2996
$main::pkg_logfile = "$conf::log_dir/${pkg}_$date";
2997
if ($main::verbose) {
2999
($pid = open( PLOG, "|-")) || exec "tee $main::pkg_logfile";
3000
if (!defined $pid) {
3001
warn "Cannot open pipe to 'tee $main::pkg_logfile': $!\n";
3004
$main::pkg_tee_pid = $pid;
3008
if (!open( PLOG, ">$main::pkg_logfile" )) {
3009
warn "Can't open logfile $main::pkg_logfile: $!\n";
3014
select( (select( PLOG ), $| = 1)[0] );
3016
my $revision = '$Revision: 1.170.5 $';
3017
$revision =~ /([\d.]+)/;
3020
print PLOG "Automatic build of $pkg on $main::HOSTNAME by ".
3021
"sbuild/$main::arch $revision\n";
3022
print PLOG "Build started at $date";
3023
print PLOG "*"x78, "\n";
3028
my $date = `date +%Y%m%d-%H%M`;
3030
my $t = $main::pkg_end_time - $main::pkg_start_time;
3032
$pkg = basename( $pkg );
3034
#if ($main::pkg_status eq "successful") {
3035
# add_time_entry( $pkg, $t );
3036
# add_space_entry( $pkg, $main::this_space );
3038
print PLOG "*"x78, "\n";
3039
printf PLOG "Finished at ${date}Build needed %02d:%02d:%02d, %dk disk space\n",
3040
int($t/3600), int(($t%3600)/60), int($t%60), $main::this_space;
3041
kill( 15, $main::pkg_tee_pid ) if $main::verbose && !$main::nolog;
3043
open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n";
3044
send_mail( $conf::mailto,
3045
"Log for $main::pkg_status build of ".
3046
($main::binNMU_name || $pkg)." (dist=$main::distribution)",
3047
$main::pkg_logfile ) if !$main::nolog && $conf::mailto;
3050
sub add_time_entry {
3054
return if !$conf::avg_time_db;
3056
if (!tie %db, 'GDBM_File',$conf::avg_time_db,GDBM_WRCREAT,0664) {
3057
print "Can't open average time db $conf::avg_time_db\n";
3062
if (exists $db{$pkg}) {
3063
my @times = split( /\s+/, $db{$pkg} );
3066
foreach (@times[1..$#times]) { $sum += $_; }
3067
$times[0] = $sum / (@times-1);
3068
$db{$pkg} = join( ' ', @times );
3071
$db{$pkg} = "$t $t";
3080
if (!open( PIPE, "sudo /usr/bin/du -s @files 2>/dev/null |" )) {
3081
print PLOG "Cannot determine space needed (du failed): $!\n";
3090
$main::this_space = $sum;
3093
sub add_space_entry {
3099
return if !$conf::avg_space_db || $main::this_space == 0;
3101
if (!tie %db, 'GDBM_File',$conf::avg_space_db,GDBM_WRCREAT,0664) {
3102
print "Can't open average space db $conf::avg_space_db\n";
3107
if (exists $db{$pkg}) {
3108
my @values = split( /\s+/, $db{$pkg} );
3110
unshift( @values, $t );
3111
pop @values if @values > $keepvals;
3112
my ($sum, $n, $weight, $i) = (0, 0, scalar(@values));
3113
for( $i = 0; $i < @values; ++$i) {
3114
$sum += $values[$i] * $weight;
3117
unshift( @values, $sum/$n );
3118
$db{$pkg} = join( ' ', @values );
3121
$db{$pkg} = "$t $t";
3128
my @x = grep { /^\Q$name\E_/ } @_;
3132
sub write_jobs_file {
3137
$main::job_state{$main::current_job} = $news
3138
if $news && $main::current_job;
3140
return if !$main::batchmode;
3142
return if !open( F, ">$main::jobs_file" );
3143
foreach $job (@ARGV) {
3144
print F ($job eq $main::current_job) ? "" : " ",
3146
($main::job_state{$job} ? ": $main::job_state{$job}" : ""),
3152
sub append_to_FINISHED {
3156
return if !$main::batchmode;
3158
open( F, ">>SBUILD-FINISHED" );
3163
sub write_srcdep_lock_file {
3165
my $specials = shift;
3168
++$main::srcdep_lock_cnt;
3169
my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt";
3170
if (!open( F, ">$f" )) {
3171
print "Warning: cannot create srcdep lock file $f: $!";
3174
print "Writing srcdep lock file $f:\n" if $main::debug;
3176
chomp( my $user = `/usr/bin/whoami` );
3177
print F "$main::current_job $$ $user\n";
3178
print "Job $main::current_job pid $$ user $user\n" if $main::debug;
3180
my $name = $_->{'Package'};
3181
# add special deps only if they affect global state ("global" sub)
3182
next if $name =~ /^\*/ &&
3183
(!isin( $name, @$specials ) ||
3184
$main::specials{$name}->{'global'} !~ /yes/m);
3185
print F ($_->{'Neg'} ? "!" : ""), "$name\n";
3186
print " ", ($_->{'Neg'} ? "!" : ""), "$name\n" if $main::debug;
3191
sub check_srcdep_conflicts {
3192
my $to_inst = shift;
3193
my $to_remove = shift;
3194
my $special = shift;
3197
my %conflict_builds;
3199
if (!opendir( DIR, $conf::srcdep_lock_dir )) {
3200
print PLOG "Cannot opendir $conf::srcdep_lock_dir: $!\n";
3203
my @files = grep { !/^\.\.?$/ && !/^install\.lock/ && !/^$mypid-\d+$/ }
3208
foreach $file (@files) {
3209
if (!open( F, "<$conf::srcdep_lock_dir/$file" )) {
3210
print PLOG "Cannot open $conf::srcdep_lock_dir/$file: $!\n";
3213
<F> =~ /^(\S+)\s+(\S+)\s+(\S+)/;
3214
my ($job, $pid, $user) = ($1, $2, $3);
3216
# ignore (and remove) a lock file if associated process doesn't exist
3218
if (kill( 0, $pid ) == 0 && $! == ESRCH) {
3220
print PLOG "Found stale srcdep lock file $file -- removing it\n";
3221
print PLOG "Cannot remove: $!\n"
3222
if !unlink( "$conf::srcdep_lock_dir/$file" );
3226
print "Reading srclock file $file by job $job user $user\n"
3230
my ($neg, $pkg) = /^(!?)(\S+)/;
3231
print "Found ", ($neg ? "neg " : ""), "entry $pkg\n"
3234
if ($pkg =~ /^\*/) {
3235
print PLOG "Build of $job by $user (pid $pid) has ",
3236
"installed the global special dependency $pkg.\n";
3237
$conflict_builds{$file} = 1;
3240
if (isin( $pkg, @$to_inst, @$to_remove )) {
3241
print PLOG "Source dependency conflict with build of ",
3242
"$job by $user (pid $pid):\n";
3243
print PLOG " $job ", ($neg ? "conflicts with" : "needs"),
3245
print PLOG " $main::current_job wants to ",
3246
(isin( $pkg, @$to_inst ) ? "update" : "remove"),
3248
$conflict_builds{$file} = 1;
3255
foreach (@$special) {
3256
if ($main::specials{$_}->{'global'} =~ /yes/m) {
3257
print PLOG "$main::current_job wants to apply global ",
3258
"special dependency $_\n",
3259
"Must wait for other builds to finish\n";
3261
$conflict_builds{$_} = 1;
3266
my @conflict_builds = keys %conflict_builds;
3267
if (@conflict_builds) {
3268
print "Srcdep conflicts with: @conflict_builds\n" if $main::debug;
3271
print "No srcdep conflicts\n" if $main::debug;
3273
return @conflict_builds;
3276
sub remove_srcdep_lock_file {
3277
my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt";
3279
print "Removing srcdep lock file $f\n" if $main::debug;
3280
if (!unlink( $f )) {
3281
print "Warning: cannot remove srcdep lock file $f: $!\n"
3286
sub prepare_watches {
3287
my $dependencies = shift;
3289
my(@dep_on, $dep, $pkg, $prg);
3292
foreach $dep (@$dependencies, @$main::additional_deps) {
3293
if ($dep->{'Neg'} && $dep->{'Package'} =~ /^needs-no-(\S+)/) {
3294
push( @dep_on, $1 );
3296
elsif ($dep->{'Package'} !~ /^\*/ && !$dep->{'Neg'}) {
3297
foreach (scalar($dep), @{$dep->{'Alternatives'}}) {
3298
push( @dep_on, $_->{'Package'} );
3302
# init %this_watches to names of packages which have not been installed as
3303
# source dependencies
3304
undef %main::this_watches;
3305
foreach $pkg (keys %conf::watches) {
3306
if (isin( $pkg, @dep_on )) {
3307
print "Excluding from watch: $pkg\n" if $main::debug;
3310
foreach $prg (@{$conf::watches{$pkg}}) {
3311
$prg = "/usr/bin/$prg" if $prg !~ m,^/,;
3312
$main::this_watches{"$main::chroot_dir$prg"} = $pkg;
3313
print "Will watch for $prg ($pkg)\n" if $main::debug;
3319
my($prg, @st, %used);
3321
foreach $prg (keys %main::this_watches) {
3322
if (!(@st = stat( $prg ))) {
3323
print "Watch: $prg: stat failed\n" if $main::debug;
3326
if ($st[8] > $main::build_start_time) {
3327
my $pkg = $main::this_watches{$prg};
3329
$prg2 =~ s/^\Q$main::chroot_dir\E// if $main::chroot_dir;
3330
push( @{$used{$pkg}}, $prg2 )
3331
if @main::have_dsc_build_deps ||
3332
!isin( $pkg, @conf::ignore_watches_no_build_deps );
3335
print "Watch: $prg: untouched\n" if $main::debug;
3342
NOTE: The package could have used binaries from the following packages
3343
(access time changed) without a source dependency:
3345
foreach (keys %used) {
3346
print PLOG " $_: @{$used{$_}}\n";
3354
fixup_pkgv( \$pkgv );
3355
lock_file( "SKIP" );
3356
goto unlock if !open( F, "SKIP" );
3360
if (!open( F, ">SKIP" )) {
3361
print "Can't open SKIP for writing: $!\n",
3362
"Would write: @pkgs\nminus $pkgv\n";
3367
if (/^\Q$pkgv\E$/) {
3369
print PLOG "$pkgv found in SKIP file -- skipping building it\n";
3377
unlock_file( "SKIP" );
3386
lock_file( "SBUILD-GIVEN-BACK" );
3388
if (open( F, ">>SBUILD-GIVEN-BACK" )) {
3389
print F "$pkgv $time\n";
3393
print PLOG "Can't open SBUILD-GIVEN-BACK: $!\n";
3397
unlock_file( "SBUILD-GIVEN-BACK" );
3402
my $subject = shift;
3406
if (!open( F, "<$file" )) {
3407
warn "Cannot open $file for mailing: $!\n";
3410
local $SIG{'PIPE'} = 'IGNORE';
3412
if (!open( MAIL, "|$conf::mailprog -oem $to" )) {
3413
warn "Could not open pipe to $conf::mailprog: $!\n";
3418
print MAIL "Subject: $subject\n\n";
3420
print MAIL "." if $_ eq ".\n";
3425
if (!close( MAIL )) {
3426
warn "$conf::mailprog failed (exit status $?)\n";
3435
$main::changes->{'installed'}->{$_} = 1;
3437
print "Added to installed list: @_\n" if $main::debug;
3442
$main::changes->{'removed'}->{$_} = 1;
3443
if (exists $main::changes->{'installed'}->{$_}) {
3444
delete $main::changes->{'installed'}->{$_};
3445
$main::changes->{'auto-removed'}->{$_} = 1;
3446
print "Note: $_ was installed\n" if $main::debug;
3449
print "Added to removed list: @_\n" if $main::debug;
3452
sub unset_installed {
3454
delete $main::changes->{'installed'}->{$_};
3456
print "Removed from installed list: @_\n" if $main::debug;
3461
delete $main::changes->{'removed'}->{$_};
3462
if (exists $main::changes->{'auto-removed'}->{$_}) {
3463
delete $main::changes->{'auto-removed'}->{$_};
3464
$main::changes->{'installed'}->{$_} = 1;
3465
print "Note: revived $_ to installed list\n" if $main::debug;
3468
print "Removed from removed list: @_\n" if $main::debug;
3480
my $free = `/bin/df $dir | tail -1`;
3481
my @free = split( /\s+/, $free );
3487
return grep( $_ eq $val, @_ );
3493
$$pkgv =~ s,^.*/,,; # strip path
3494
$$pkgv =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension
3495
$$pkgv =~ s/_[a-zA-Z\d+~-]+\.(changes|deb)$//; # strip extension
3501
map { ($_->{'Neg'} ? "!" : "") .
3503
($_->{'Rel'} ? " ($_->{'Rel'} $_->{'Version'})":"")}
3504
scalar($_), @{$_->{'Alternatives'}}) } @_ );
3509
my $for_srcdep = shift;
3510
my $lockfile = "$file.lock";
3514
if (!sysopen( F, $lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644 )){
3516
# lock file exists, wait
3517
goto repeat if !open( F, "<$lockfile" );
3521
if ($line !~ /^(\d+)\s+([\w\d.-]+)$/) {
3522
warn "Bad lock file contents ($lockfile) -- still trying\n";
3525
($pid, $user) = ($1, $2);
3526
if (kill( 0, $pid ) == 0 && $! == ESRCH) {
3527
# process doesn't exist anymore, remove stale lock
3528
warn "Removing stale lock file $lockfile ".
3529
" (pid $pid, user $user)\n";
3530
unlink( $lockfile );
3535
if (!$for_srcdep && $try > $main::max_lock_trys) {
3536
warn "Lockfile $lockfile still present after ".
3537
$main::max_lock_trys*$main::lock_interval.
3538
" seconds -- giving up\n";
3541
print PLOG "Another sbuild process ($pid by $user) is currently ",
3543
"removing packages -- waiting...\n"
3544
if $for_srcdep && $try == 1;
3545
sleep $main::lock_interval;
3548
warn "Can't create lock file $lockfile: $!\n";
3550
F->print("$$ $ENV{'LOGNAME'}\n");
3556
my $lockfile = "$file.lock";
3558
unlink( $lockfile );
3561
sub check_dpkg_version {
3562
my $t = `$conf::dpkg --version`;
3563
my $version = ($t =~ /version\s+(\S+)/)[0];
3566
if 0 == system "$conf::dpkg --compare-versions '$version' ge 1.4.1.18";
3569
sub binNMU_version {
3572
if ($v =~ /^(.*)-([^-]+)$/) {
3573
my ($upstream, $debian) = ($1, $2);
3574
my @parts = split( /\./, $debian );
3576
return "$upstream-$debian.0.$main::binNMUver";
3578
elsif (@parts == 2) {
3579
return "$upstream-$debian.$main::binNMUver";
3582
$parts[$#parts]+=$main::binNMUver;
3583
return "$upstream-".join( ".", @parts );
3587
return "$v.0.$main::binNMUver";
3592
my $signame = shift;
3593
my($job,@npkgs,@pkgs);
3596
$SIG{'INT'} = 'IGNORE';
3597
$SIG{'QUIT'} = 'IGNORE';
3598
$SIG{'TERM'} = 'IGNORE';
3599
$SIG{'ALRM'} = 'IGNORE';
3600
$SIG{'PIPE'} = 'IGNORE';
3601
print PLOG "sbuild received SIG$signame -- shutting down\n";
3602
chdir( $main::cwd );
3604
goto not_ni_shutdown if !$main::batchmode;
3606
# most important: dump out names of unfinished jobs to REDO
3607
foreach $job (@ARGV) {
3609
fixup_pkgv( \$job2 );
3610
push( @npkgs, $job2 )
3611
if !$main::job_state{$job} || $job eq $main::current_job;
3613
print LOG "The following jobs were not finished: @npkgs\n";
3615
my $f = "$main::HOME/build/REDO";
3616
if (-f "$main::HOME/build/REDO.lock") {
3617
# if lock file exists, write to a different file -- timing may
3619
$f = "$main::HOME/build/REDO2";
3621
if (open( F, "<$f" )) {
3625
if (open( F, ">>$f" )) {
3626
foreach $job (@npkgs) {
3627
next if grep( /^\Q$job\E\s/, @pkgs );
3628
print F "$job $main::distribution $main::component\n";
3633
print "Cannot open $f: $!\n";
3635
open( F, ">SBUILD-REDO-DUMPED" );
3637
print LOG "SBUILD-REDO-DUMPED created\n";
3638
unlink( "SBUILD-FINISHED" );
3640
# next: say which packages should be uninstalled
3641
@pkgs = keys %{$main::changes->{'installed'}};
3643
if (open( F, ">>NEED-TO-UNINSTALL" )) {
3647
print "The following packages still need to be uninstalled ",
3648
"(--purge):\n@pkgs\n";
3652
# next: kill currently running command (if one)
3653
if ($main::sub_pid) {
3654
print "Killing $main::sub_task subprocess $main::sub_pid\n";
3655
system "$conf::sudo perl -e 'kill( -15, $main::sub_pid )'";
3657
remove_srcdep_lock_file();
3659
# close logs and send mails
3660
if ( $main::current_job ) {
3661
fixup_pkgv( \$main::current_job );
3662
close_pkg_log( $main::current_job );
3665
unlink( $main::jobs_file ) if $main::batchmode;