~ubuntu-branches/ubuntu/raring/sbuild/raring-proposed

« back to all changes in this revision

Viewing changes to bin/sbuild

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-26 13:59:34 UTC
  • mfrom: (8.1.21 upstream) (3.3.19 sid)
  • Revision ID: james.westby@ubuntu.com-20110626135934-8blyh9rnoiiqflgt
Tags: 0.62.4-1ubuntu1
* Merge from debian unstable, Remaining changes:
  - debian/patches/do-not-install-debfoster-into-chroots.patch:
    do not install debfoster into the chroots because it is in universe and
    not needed for package building itself.
  - debian/patches/run-pre-build-hooks-as-root.patch:
    run pre-build hooks as root

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
use strict;
29
29
use warnings;
30
30
 
 
31
use Cwd qw(:DEFAULT abs_path);
31
32
use POSIX;
32
33
use Data::Dumper;
 
34
use Dpkg::Control;
33
35
use Sbuild qw(isin check_group_membership $debug_level);
34
36
use Sbuild::Conf qw();
35
 
use Sbuild::Log qw(open_log close_log);
36
37
use Sbuild::Sysconfig qw(%programs);
37
38
use Sbuild::Options;
38
39
use Sbuild::Build;
39
40
use Sbuild::Exception;
40
41
 
41
42
sub main ();
 
43
sub create_source_package ($);
42
44
sub write_jobs_file ();
43
 
sub append_to_FINISHED ($);
44
45
sub status_trigger ($$);
45
46
sub shutdown ($);
46
47
sub dump_main_state ();
59
60
umask(002);
60
61
 
61
62
# Job state
62
 
my %jobs = ();
63
 
my $current_job = undef;
 
63
my $job = undef;
64
64
 
65
65
main();
66
66
 
67
67
sub main () {
68
 
    my $dist = $conf->get('DISTRIBUTION');
69
 
    if (!defined($dist) || !$dist) {
70
 
        print STDERR "No distribution defined\n";
71
 
        exit(1);
72
 
    }
73
 
 
74
 
    print "Selected distribution " . $conf->get('DISTRIBUTION') . "\n"
75
 
        if $conf->get('DEBUG');
76
 
    print "Selected chroot " . $conf->get('CHROOT') . "\n"
77
 
        if $conf->get('DEBUG') and defined $conf->get('CHROOT');
78
 
    print "Selected architecture " . $conf->get('ARCH') . "\n"
79
 
        if $conf->get('DEBUG' && defined($conf->get('ARCH')));
80
 
 
81
 
    open_log($conf);
82
 
 
83
68
    $SIG{'INT'} = \&main::shutdown;
84
69
    $SIG{'TERM'} = \&main::shutdown;
85
70
    $SIG{'ALRM'} = \&main::shutdown;
88
73
    # If no arguments are supplied, assume we want to process the current dir.
89
74
    push @ARGV, '.' unless (@ARGV);
90
75
 
91
 
    # Create jobs
92
 
    eval {
93
 
        foreach my $job (@ARGV) {
94
 
            $jobs{$job} = Sbuild::Build->new($job, $conf);
95
 
            $jobs{$job}->set('Pkg Status Trigger', \&status_trigger)
96
 
        }
 
76
    die "Only one build is permitted\n"
 
77
        if (@ARGV != 1);
 
78
 
 
79
    # Create and run job
 
80
    my $status = eval {
 
81
        my $jobname = $ARGV[0];
 
82
        my $source_dir = 0;
 
83
 
 
84
        if (-d $jobname) {
 
85
            $jobname = create_source_package($jobname);
 
86
            $source_dir = 1;
 
87
        }
 
88
 
 
89
        # Check after source package build (which might set dist)
 
90
        my $dist = $conf->get('DISTRIBUTION');
 
91
        if (!defined($dist) || !$dist) {
 
92
            print STDERR "No distribution defined\n";
 
93
            exit(1);
 
94
        }
 
95
 
 
96
        print "Selected distribution " . $conf->get('DISTRIBUTION') . "\n"
 
97
            if $conf->get('DEBUG');
 
98
        print "Selected chroot " . $conf->get('CHROOT') . "\n"
 
99
            if $conf->get('DEBUG') and defined $conf->get('CHROOT');
 
100
        print "Selected architecture " . $conf->get('ARCH') . "\n"
 
101
            if $conf->get('DEBUG' && defined($conf->get('ARCH')));
 
102
 
 
103
        $job = Sbuild::Build->new($jobname, $conf);
 
104
        $job->set('Pkg Status Trigger', \&status_trigger);
97
105
        write_jobs_file(); # Will now update on trigger.
98
106
 
99
 
        # Run each job.  Potential for parallelising this step.
100
 
        foreach (keys %jobs) {
101
 
            my $jobname = $_;
102
 
 
103
 
            my $job = $jobs{$jobname};
104
 
            $current_job = $jobname;
105
 
 
106
 
            # Do the build
107
 
            $job->run();
108
 
 
109
 
            dump_main_state() if $conf->get('DEBUG');
110
 
        }
 
107
        # Run job.
 
108
        $job->run();
 
109
 
 
110
        dump_main_state() if $conf->get('DEBUG');
111
111
    };
112
112
 
113
113
    my $e;
119
119
            dump_main_state();
120
120
            print STDERR $e->trace->as_string, "\n";
121
121
        }
 
122
    } elsif (!defined($e)) {
 
123
        print STDERR "E: $@\n" if $@;
122
124
    }
123
125
 
124
 
    close_log($conf);
125
126
    unlink($conf->get('JOB_FILE'))
126
127
        if $conf->get('BATCH_MODE');
127
 
    unlink("SBUILD-FINISHED") if $conf->get('BATCH_MODE');
128
128
 
129
129
    # Until buildd parses status info from sbuild output, skipped must
130
130
    # be treated as a failure.
131
 
    if (defined($current_job) && defined($jobs{$current_job})) {
132
 
        if ($jobs{$current_job}->get_status() eq "successful" ||
 
131
    if (defined($job)) {
 
132
        if ($job->get_status() eq "successful" ||
133
133
            ($conf->get('SBUILD_MODE') ne "buildd" &&
134
 
             $jobs{$current_job}->get_status() eq "skipped")) {
 
134
             $job->get_status() eq "skipped")) {
135
135
            exit 0;
136
 
        } elsif ($jobs{$current_job}->get_status() eq "attempted") {
 
136
        } elsif ($job->get_status() eq "attempted") {
137
137
            exit 2;
138
 
        } elsif ($jobs{$current_job}->get_status() eq "given-back") {
 
138
        } elsif ($job->get_status() eq "given-back") {
139
139
            #Probably needs a give back:
140
140
            exit 3;
141
141
        }
143
143
        # reported to the admin as failure:
144
144
        exit 1;
145
145
    }
 
146
    exit 1;
 
147
}
 
148
 
 
149
sub create_source_package ($) {
 
150
    my $dsc = shift;
 
151
    $dsc = abs_path($dsc);
 
152
 
 
153
    open(my $pipe, '-|', 'dpkg-parsechangelog',
 
154
         '-l' . $dsc . '/debian/changelog')
 
155
        or Sbuild::Exception::Build->throw(
 
156
            error => "Could not parse $dsc/debian/changelog: $!",
 
157
            failstage => "pack-source");
 
158
 
 
159
    my $pclog = Dpkg::Control->new(type => CTRL_CHANGELOG);
 
160
    if (!$pclog->parse($pipe, 'dpkg-parsechangelog')) {
 
161
        Sbuild::Exception::Build->throw(
 
162
            error => "Could not parse $dsc/debian/changelog: $!",
 
163
            failstage => "pack-source");
 
164
    }
 
165
 
 
166
    $pipe->close or Sbuild::Exception::Build->throw(
 
167
        error => "dpkg-parsechangelog failed (exit status $?)",
 
168
        failstage => "pack-source");
 
169
 
 
170
    my $package = $pclog->{'Source'};
 
171
    my $version = $pclog->{'Version'};
 
172
 
 
173
    if (!defined($package) || !defined($version)) {
 
174
        Sbuild::Exception::Build->throw(
 
175
            error => "Missing Source or Version in $dsc/debian/changelog",
 
176
            failstage => "pack-source");
 
177
    }
 
178
 
 
179
    my $dist = $pclog->{'Distribution'};
 
180
    my $pver = Dpkg::Version->new($version, check => 1);
 
181
    if (!$pver) {
 
182
        Sbuild::Exception::Build->throw(
 
183
            error => "Bad version $version in $dsc/debian/changelog",
 
184
            failstage => "pack-source");
 
185
    }
 
186
 
 
187
    my ($epoch, $uversion, $dversion);
 
188
    $epoch = $pver->epoch();
 
189
    $uversion = $pver->version();
 
190
    $dversion = $pver->revision();
 
191
 
 
192
    if (!defined($conf->get('DISTRIBUTION')) ||
 
193
        !$conf->get('DISTRIBUTION')) {
 
194
        $conf->set('DISTRIBUTION', $dist);
 
195
    }
 
196
 
 
197
    my $dir = getcwd();
 
198
    my $origdir=$dir;
 
199
    # Note: need to support cases when invoked from a subdirectory
 
200
    # of the build directory, i.e. $dsc/foo -> $dsc/.. in addition
 
201
    # to $dsc -> $dsc/.. as below.
 
202
    if ($dir eq abs_path($dsc) &&
 
203
        $dir eq $conf->get('BUILD_DIR')) {
 
204
        # We won't attempt to build the source package from the source
 
205
        # directory so the source package files will go to the parent dir.
 
206
        $dir = abs_path("$dir/..");
 
207
        $conf->set('BUILD_DIR', $dir);
 
208
    }
 
209
 
 
210
    $dsc = "${dir}/${package}_${uversion}-${dversion}.dsc";
 
211
 
 
212
    system($conf->get('FAKEROOT'), 'debian/rules', 'clean');
 
213
    if ($?) {
 
214
        Sbuild::Exception::Build->throw(
 
215
            error => "Failed to clean source directory",
 
216
            failstage => "pack-source");
 
217
    }
 
218
    chdir($dir) or Sbuild::Exception::Build->throw(
 
219
        error => "Failed to change directory",
 
220
        failstage => "pack-source");
 
221
    my @dpkg_source_command = ($conf->get('DPKG_SOURCE'), '-b');
 
222
    push @dpkg_source_command, @{$conf->get('DPKG_SOURCE_OPTIONS')}
 
223
    if ($conf->get('DPKG_SOURCE_OPTIONS'));
 
224
    push @dpkg_source_command, "${package}-${uversion}";
 
225
    system(@dpkg_source_command);
 
226
    if ($?) {
 
227
        Sbuild::Exception::Build->throw(
 
228
            error => "Failed to package source directory",
 
229
            failstage => "pack-source");
 
230
    }
 
231
    chdir($origdir) or Sbuild::Exception::Build->throw(
 
232
        error => "Failed to change directory",
 
233
        failstage => "pack-source");
 
234
 
 
235
    return $dsc;
146
236
}
147
237
 
148
238
# only called from main loop, but depends on job state.
153
243
        local( *F );
154
244
 
155
245
        return if !open( F, ">$file" );
156
 
        foreach (keys %jobs) {
157
 
            my $job = $jobs{$_};
158
 
 
 
246
        if (defined($job)) {
159
247
            print F $job->get('Package_OVersion') . ": " .
160
248
                $job->get_status() . "\n";
161
249
        }
163
251
    }
164
252
}
165
253
 
166
 
sub append_to_FINISHED ($) {
167
 
    my $job = shift;
168
 
 
169
 
    local( *F );
170
 
 
171
 
    if ($conf->get('BATCH_MODE')) {
172
 
        open(F, ">>SBUILD-FINISHED");
173
 
        print F $job->get('Package_OVersion');
174
 
        close(F);
175
 
    }
176
 
}
177
 
 
178
254
sub status_trigger ($$) {
179
255
    my $build = shift;
180
256
    my $status = shift;
199
275
}
200
276
 
201
277
sub shutdown ($) {
202
 
    my $job = undef;
203
278
    my $signame = shift;
204
279
 
205
280
    $SIG{'INT'} = 'IGNORE';
208
283
    $SIG{'ALRM'} = 'IGNORE';
209
284
    $SIG{'PIPE'} = 'IGNORE';
210
285
 
211
 
    $job = $jobs{$current_job} if (defined($current_job) &&
212
 
                                   defined($jobs{$current_job}));
213
 
 
214
286
    if (defined($job)) {
215
287
        $job->request_abort("Received $signame signal");
216
288
    } else {
224
296
}
225
297
 
226
298
sub dump_main_state () {
227
 
    print STDERR Data::Dumper->Dump([$current_job,
228
 
                                     \%jobs],
229
 
                                    [qw($current_job
230
 
                                        %jobs)] );
 
299
    print STDERR Data::Dumper->Dump([$job],
 
300
                                    [qw($job)] );
231
301
}