Home | History | Annotate | Download | only in gnome-2-16
      1 #!/usr/bin/perl
      2 
      3 use strict;
      4 use warnings;
      5 use Getopt::Long qw(:config gnu_getopt no_auto_abbrev);
      6 use rpm_spec;
      7 
      8 # --------- defaults -------------------------------------------------------
      9 my $default_spec_dir = `dirname $0`;
     10 $default_spec_dir =~ s/\s//g;
     11 
     12 # use "rpmbuild" (RPM v4) if present or "rpm" (RPM v3) if not
     13 my $RPM_BUILD = 'rpmbuild';
     14 my $cmd_found = `which rpmbuild | wc -l`;
     15 if ($cmd_found == 0) {
     16 	$RPM_BUILD = 'rpm';
     17 }
     18 
     19 my $default_log_dir = '/tmp';
     20 my $default_tarball_dir = "/sgnome/tarballs/gnome2.14";
     21 my $default_source_dirs = $default_spec_dir . "/ext-sources" .
     22 			":" . $default_spec_dir . "/manpages/man1" .
     23 			":" . $default_spec_dir . "/manpages/man3" .
     24 			":" . $default_spec_dir . "/manpages/man4" .
     25 			":" . $default_spec_dir . "/manpages/man5" .
     26                         ":" . "/sgnome/tarballs/moz-evo";
     27 my $default_patch_dir = $default_spec_dir . "/patches";
     28 my $default_sys_rpm_dir = "/usr/src/packages";
     29 my $default_nightly_date_format = '%y%m%d';
     30 
     31 # --------- global vars ----------------------------------------------------
     32 # config settings
     33 my $the_spec_dir = $default_spec_dir;
     34 my $the_log_dir = $default_log_dir;
     35 my $the_summary_log;
     36 my $the_summary_title;
     37 my $the_logdir_url;
     38 my $the_rpm_url;
     39 my $the_srpm_url;
     40 my $the_source_dirs = $default_source_dirs;
     41 my @the_source_dirlist;
     42 my $the_tarball_dir = $default_tarball_dir;
     43 my $the_good_build_dir;
     44 my $the_good_rpms_copy_dir;
     45 my $the_patch_dir = $default_patch_dir;
     46 my $the_sys_rpm_dir = $default_sys_rpm_dir;
     47 my $rpm_target = "i586";
     48 
     49 my $check_deps = 1;
     50 my $live_summary = 0;
     51 
     52 my $build_command;
     53 my $build_and_install = 1;
     54 my $prep_only = 0;
     55 
     56 my $exit_val = 0;
     57 my $verbose = 1;
     58 my $debug_level = 0;
     59 my $full_path = 0;
     60 my $halt_on_errors = 0;
     61 my $mail_errors_file;
     62 my $mail_errors_to;
     63 my $mail_errors_cc;
     64 my $prodname = "unnamed";
     65 my $is_nightly = 0;
     66 my $the_nightly_date_format = $default_nightly_date_format;
     67 my $is_nodeps = 0;
     68 
     69 # counter used as an id for the spec files
     70 my $spec_id = 0;
     71 
     72 # array of spec objects
     73 my @specs_to_build = ();
     74 my @build_status;
     75 my @status_details;
     76 my @remove_list = ();
     77 
     78 my %provider;
     79 my %warned_about;
     80 
     81 # --------- utility functions ----------------------------------------------
     82 our $opt_specdir = $default_spec_dir;
     83 
     84 # return the name of the log file given the id of the spec file
     85 sub get_log_name ($) {
     86     my $spec_id = shift;
     87     my $spec = $specs_to_build[$spec_id];
     88     my $spec_file = $spec->get_param ('file_name');
     89     my $base_name = $spec_file;
     90     $base_name =~ s/^.*\/([^\/]+)/$1/;
     91     my $log_name = "$base_name";
     92     $log_name =~ s/(\.spec|)$/.log/;
     93 
     94     return $log_name;
     95 }
     96 
     97 my $current_log;
     98 
     99 sub open_log ($) {
    100     my $log_filename = shift;
    101 
    102     if (not defined ($log_filename)) {
    103 	return;
    104     }
    105 
    106     if (defined ($current_log)) {
    107 	if ($current_log ne $log_filename) {
    108 	    close LOG_FILE;
    109 	}
    110     }
    111 
    112     $current_log = undef;
    113 
    114     if (! open LOG_FILE, ">>$log_filename") {
    115 	msg_warning (0, "Failed to open log file $log_filename");
    116 	return;
    117     }
    118 
    119     $current_log = $log_filename;
    120 
    121     msg_log ("--- log starts --- " . `date`);
    122 }
    123 
    124 sub close_log () {
    125     msg_log ("--- log ends --- " . `date`);
    126     close LOG_FILE;
    127     $current_log = undef;
    128 }
    129 
    130 sub print_message ($$) {
    131     my $min_verbose = shift;
    132     my $message = shift;
    133 
    134     chomp $message;
    135 
    136     if ($verbose > $min_verbose) {
    137 	print "$message\n";
    138     }
    139     if (defined ($current_log)) {
    140 	print LOG_FILE "$message\n";
    141     }
    142 }
    143 
    144 sub msg_error ($) {
    145     my $message = shift;
    146 
    147     print_message (0, "ERROR: $message");
    148     if ($halt_on_errors > 0) {
    149 	print "ERROR: Exiting...\n";
    150 	exit (255);
    151     }
    152 }
    153 
    154 sub msg_warning ($$) {
    155     my $min_verbose = shift;
    156     my $message = shift;
    157 
    158     print_message ($min_verbose, "WARNING: $message");
    159 }
    160 
    161 sub msg_info ($$) {
    162     my $min_verbose = shift;
    163     my $message = shift;
    164 
    165     print_message ($min_verbose, "INFO: $message");
    166 }
    167 
    168 sub msg_debug ($$) {
    169     my $min_debug = shift;
    170     my $message = shift;
    171 
    172     if ($debug_level > $min_debug) {
    173 	print "DEBUG: $message\n";
    174     }
    175 }
    176 
    177 sub msg_log ($) {
    178     my $message = shift;
    179 
    180     if (defined ($current_log)) {
    181 	print LOG_FILE "$message\n";
    182     }
    183 }
    184 
    185 sub find_file ($) {
    186     my $glob = shift;
    187 
    188     my @files = `find $glob 2>&1`;
    189     if ($? == 0) {
    190 	my $file = $files[$#files];
    191 	chomp $file;
    192 	return ($file);
    193     }
    194 
    195     return (undef);
    196 }
    197 
    198 sub mail_log ($) {
    199     my $spec_id = shift;
    200     my $address;
    201     my $cc;
    202     my $log_name = get_log_name ($spec_id);
    203     my $spec_name = $specs_to_build[$spec_id]->{name};
    204     my $base_name = $log_name;
    205     $log_name =~ s/\.log$//;
    206 
    207     if (defined ($mail_errors_file)) {
    208 	$address = get_address_from_file ($mail_errors_file, $base_name);
    209     }
    210     
    211     if (not defined ($address)) {
    212 	$address = $mail_errors_to;
    213     }
    214 
    215     if (not defined ($address)) {
    216 	$address = $mail_errors_cc;
    217     } else {
    218 	$cc = $mail_errors_cc;
    219     }
    220 
    221     if (not defined ($address)) {
    222 	return;
    223     }
    224 
    225     my $log_file = get_log_name ($spec_id);
    226     msg_info (1, "mailing the build log to $address");
    227 
    228     my $subject;
    229 
    230     my $log_pointer;
    231     if (defined ($the_logdir_url)) {
    232 	$log_pointer = "$the_logdir_url/${log_name}.log";
    233     } else {
    234 	$log_pointer = "$the_log_dir/$log_file";
    235     }
    236 
    237     if (defined ($prodname)) {
    238 	$subject = "BUILD FAILED ($prodname): $spec_name";
    239     } else {
    240 	$subject = "BUILD FAILED: $spec_name";	
    241     }
    242 
    243     if (defined ($cc)) {
    244 	`( echo "Full log: $log_pointer" ; echo; echo "--- tail of the log follows ---"; echo; tail -100 $the_log_dir/$log_file ) | mailx -s "$subject" -c "$cc" $address`;
    245     } else {
    246 	`( echo "Full log: $log_pointer" ; echo; echo "--- tail of the log follows ---"; echo; tail -100 $the_log_dir/$log_file ) | mailx -s "$subject" $address`;
    247     }
    248 }
    249 
    250 sub get_address_from_file ($$) {
    251     my $fname = shift;
    252     my $pkg = shift;
    253 
    254     $pkg =~ s/\.spec$//;
    255 
    256     if (! open ADDR_FILE, "<$fname") {
    257         msg_warning (0, "Could not open file $fname");
    258 	return undef;
    259     }
    260     my @lines = <ADDR_FILE>;
    261     my @addresses = grep /^$pkg:/, @lines;
    262     my $address = $addresses[0];
    263     if (not defined ($address)) {
    264 	return undef;
    265     }
    266     $address =~ s/^$pkg://;
    267     $address =~ s/\s//g;
    268     close ADDR_FILE;
    269     return $address;
    270 }
    271 
    272 # --------- functions to process the command line args ---------------------
    273 sub add_spec ($) {
    274     my $spec_name = shift;
    275 
    276     my $spec;
    277 
    278     if (-f $spec_name) {
    279 	$spec = rpm_spec->new ($spec_name, $rpm_target);
    280     } else {
    281 	if (not $spec_name =~ /\.spec$/) {
    282 	    $spec_name = "${opt_specdir}/${spec_name}.spec";
    283 	}
    284 	$spec = rpm_spec->new ("$spec_name", $rpm_target);
    285     }
    286 
    287     if (not defined ($spec)) {
    288 	msg_error ("$spec_name not found\n");
    289     } else {
    290 	if ($is_nightly) {
    291 	    $spec->add_define ("nightly", "1");
    292 	}
    293 	my $this_spec_id = $spec_id ++;
    294 	$specs_to_build[$this_spec_id] = $spec;
    295 	my @packages = $spec->get_param_array ('packages');
    296 
    297 	$build_status[$this_spec_id] = 'NOT_BUILT';
    298 	$status_details[$this_spec_id] = '';
    299 
    300 	foreach my $pkg (@packages) {
    301 	    my @provides = $spec->get_pkg_param_array ($pkg, 'provides');
    302 	    foreach my $prov (@provides) {
    303 		if (not defined $prov) {
    304 		    next;
    305 		}
    306 		$prov =~ s/ .*//;
    307 		$provider{$prov} = $this_spec_id;
    308 	    }
    309 	}
    310     }
    311 }
    312 
    313 sub set_quiet {
    314     $verbose = 0;
    315 }
    316 
    317 sub process_args {
    318     my $arg = shift;
    319 
    320     if (not defined ($build_command)) {
    321 	if (($arg ne "build") and ($arg ne "build-order") and
    322 	    ($arg ne "uninstall-pkgs") and
    323 	    ($arg ne "build-install") and ($arg ne "build-only") and
    324 	    ($arg ne "prep") and
    325 	    ($arg ne "install-order")) {
    326 	    msg_error ("unknown command: $arg");
    327 	    usage (1);
    328 	}
    329 	$build_command = $arg;
    330     } else {
    331 	add_spec ($arg);
    332     }
    333 }
    334 
    335 sub process_options {
    336     
    337   Getopt::Long::Configure ("bundling");
    338     
    339     our $opt_logdir = $default_log_dir;
    340     our $opt_sourcedirs = $default_source_dirs;
    341     our $opt_tarballdir = $default_tarball_dir;
    342     our $opt_good_build_dir;
    343     our $opt_good_rpms_copy_dir;
    344     our $opt_patchdir = $default_patch_dir;
    345     our $opt_rpmdir = $default_sys_rpm_dir;
    346     our $opt_deps = 1;
    347     our $opt_live_summary = 0;
    348     our $opt_summary_log;
    349     our $opt_summary_title;
    350     our $opt_logdir_url;
    351     our $opt_rpm_url;
    352     our $opt_srpm_url;
    353     our $opt_date = $default_nightly_date_format;
    354     
    355     GetOptions ('v|verbose+' => \$verbose,
    356 		'debug=n' => \$debug_level,
    357 		'q|quiet' => \&set_quiet,
    358 		'specdir|spec|S=s',
    359 		'halt-on-errors!', \$halt_on_errors,
    360 		'mail-errors-to=s' => \$mail_errors_to,
    361 		'mail-errors-cc=s' => \$mail_errors_cc,
    362 		'mail-errors-file=s' => \$mail_errors_file,
    363 		'prodname=s' => \$prodname,
    364 		'sourcedirs|sourcedir|src|srcdirs|srcdir|sources|source|s=s',
    365 		'logdir|log|l=s',
    366 		'summary-log=s',
    367 		'live-summary|live!',
    368 		'summary-title=s',
    369 		'logdir-url=s',
    370 		'rpm-url=s',
    371 		'srpm-url=s',
    372 		'target=s' => \$rpm_target,
    373 		'deps!',
    374 		'tarballdir|tar|tarball|tardir|t=s',
    375 		'good-build-dir=s',
    376 		'good-rpms-copy-dir=s',
    377 		'nightly!' => \$is_nightly,
    378 		'date|date-format|nightly-date-format=s',
    379 		'patchdir|patch|p=s',
    380 		'rpmdir|rpm|r=s',
    381 		'full-path' => \$full_path,
    382 		'nodeps!' => \$is_nodeps,
    383 		'help' => \&usage,
    384 		'<>' => \&process_args);
    385     
    386     $the_spec_dir = $opt_specdir;
    387     $the_log_dir = $opt_logdir;
    388     $the_summary_log = $opt_summary_log;
    389     $the_summary_title = $opt_summary_title;
    390     $the_logdir_url = $opt_logdir_url;
    391     $the_rpm_url = $opt_rpm_url;
    392     $the_srpm_url = $opt_srpm_url;
    393     $the_source_dirs = $opt_sourcedirs;
    394     $the_tarball_dir = $opt_tarballdir;
    395     $the_patch_dir = $opt_patchdir;
    396     $the_sys_rpm_dir = $opt_rpmdir;
    397     $the_good_build_dir = $opt_good_build_dir;
    398     $the_good_rpms_copy_dir = $opt_good_rpms_copy_dir;
    399     $check_deps = $opt_deps;
    400     $live_summary = $opt_live_summary;
    401     $the_nightly_date_format = $opt_date;
    402 
    403     if ($is_nodeps) {
    404         $check_deps = 0; 
    405     }
    406 
    407     @the_source_dirlist = split /:/, $the_source_dirs;
    408 }
    409 
    410 sub usage (;$) {
    411     my $retval = shift;
    412     if (not defined ($retval)) {
    413 	$retval = 0;
    414     }
    415 
    416     print << "EOF";
    417 build-gnome2 [options] [command] specs...
    418 
    419 Options:
    420 
    421     -v|--verbose:    
    422                   Increase verbosity: the more -v's the more diag messages
    423 
    424     -q|--quiet:
    425                   Silent operation.
    426 
    427     --specdir=dir, --spec=dir:
    428                   Use dir as the default directory for spec files.
    429                   Default: $default_spec_dir
    430 
    431     --tarballdir=dir, --tardir=dir, --tar=dir:
    432                   Search for source tarballs in dir.
    433                   Default: $default_tarball_dir
    434 
    435     --sourcedir=dir, --srcdir=dir, --src=dir:
    436                   Location of the additional sources referenced in the spec
    437                   files. Default: $default_spec_dir
    438 
    439     --patchdir=dir, --patch=dir:
    440                   Look for the patches referenced in the spec files in dir.
    441                   Default: $default_patch_dir
    442  
    443     --rpmdir=dir --rpm=dir:
    444                   Use dir as the rpm base directory (where the SPECS,
    445                   SOURCES, RPMS, SRPMS, BUILD directories are found).
    446                   Default: $default_sys_rpm_dir
    447 
    448     --logdir=dir, --log=dir:
    449                   Write build logs to dir. Default: $default_log_dir
    450                   
    451     --nodeps, --deps:
    452                   Ignore/verify dependencies before building a component.
    453                   Default: --deps
    454 
    455     --target=arch
    456 		  If used, the same option will be passed to rpm when
    457 		  building the package(s)
    458 
    459     --halt-on-errors:
    460                   Halt on the first build error, do not attempt to continue.
    461 
    462     --full-path:
    463                   Print the full path to the rpm when running install-order.
    464 
    465     --nightly, --nonightly:
    466                   Suffix/Don't suffix the rpm Release with the current date.
    467                   Default: --nonightly;
    468 
    469     --date-format=format, --date=format:
    470                   Use "date +format" to generate the date suffix for
    471                   the nightly builds. Default: $default_nightly_date_format
    472 
    473 
    474 Commands:
    475 
    476     build          Build and install the specs listed on the command line
    477 
    478     build-only     Build the specs listed on the command line, don't install
    479                    them.
    480 
    481     prep           run the %prep section of the spec files listed on the
    482                    command line
    483 
    484     build-order    Print the build order of the specs listed on the
    485                    command line.
    486 
    487     install-order  Print the rpms in the order they should be installed
    488 	
    489     install-pkgs   (not implemented yet): install the packages defined
    490                    by the spec files listed on the command line from
    491                    the PKGS directory.
    492 	
    493     uninstall-pkgs Remove all rpms defined in the spec files listed
    494 	           on the command line. (runs rpm --erase --nodeps)
    495 
    496 specs...
    497 
    498     List of spec files to build. Either full path names or names of spec
    499     files in the default spec directory (with or without the .spec suffix).
    500 EOF
    501     exit $retval;
    502 }
    503 
    504 # --------- print reports --------------------------------------------------
    505 # plain text report on stdout and
    506 # html report if summary log file name
    507 # was specified on the command line
    508 sub print_status {
    509     print_status_text ();
    510     print_status_html ();
    511 }
    512 
    513 sub print_live_status {
    514     if ($live_summary) {
    515 	print_status_html ();
    516     }
    517 }
    518 
    519 sub print_status_text {
    520     my $spec_name;
    521     print "\nSummary:\n\n";
    522     printf "%20s | %10s | %s\n", "package", "status", "details";
    523     print "---------------------+------------+------------------------------------------\n";
    524     for (my $i = 0; $i <= $#specs_to_build; $i++) {
    525 	$spec_name=$specs_to_build[$i]->{name};
    526 	printf "%20s | %10s | %s\n", $spec_name, $build_status[$i], 
    527 		$status_details[$i];
    528     }
    529 }
    530 
    531 sub print_status_html {
    532     my $spec_name;
    533 
    534     if (not defined ($the_summary_log)) {
    535 	return;
    536     }
    537 
    538     if (! open SUM_LOG, ">$the_summary_log") {
    539 	msg_warning (0, "Failed to open file $the_summary_log for writing");
    540 	return;
    541     }
    542 	
    543     print SUM_LOG "<HTML>\n<HEAD>\n<TITLE>Build report</TITLE>\n";
    544     print SUM_LOG "</HEAD>\n<BODY BGCOLOR=#FFFFFF>\n";
    545     if (defined ($the_summary_title)) {
    546 	print SUM_LOG "<P><H3>$the_summary_title</H3><P>\n";
    547     }
    548     print SUM_LOG "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=5 WIDTH=90%>\n";
    549     print SUM_LOG " <TR>\n";
    550     print SUM_LOG "  <TD BGCOLOR=#666699><B>package</B></TD>\n";
    551     print SUM_LOG "  <TD BGCOLOR=#666699><B>version</B></TD>\n";
    552     print SUM_LOG "  <TD BGCOLOR=#666699><B>release</B></TD>\n";
    553     print SUM_LOG "  <TD BGCOLOR=#666699><B>status</B></TD>";
    554     print SUM_LOG "  <TD BGCOLOR=#666699><B>details</B></TD>\n";
    555     print SUM_LOG " </TR>\n";
    556     for (my $i = 0; $i <= $#specs_to_build; $i++) {
    557 	my $log_name = get_log_name ($i);
    558 	$spec_name=$specs_to_build[$i]->{name};
    559 	my $version = $specs_to_build[$i]->{version};
    560 	my $release = $specs_to_build[$i]->{release};
    561 	print SUM_LOG " <TR>\n";
    562 	if (defined ($the_srpm_url)) {
    563 	    if (($build_status[$i] eq "PASSED") and defined ($the_srpm_url)) {
    564 		print SUM_LOG "  <TD><A HREF=\"$the_srpm_url/$spec_name-$version-$release.src.rpm\">$spec_name</A></TD>\n";
    565 	    } else {
    566 		print SUM_LOG "  <TD>$spec_name</TD>\n";
    567 	    }
    568 	} else {
    569 	    print SUM_LOG "  <TD>$spec_name</TD>\n";
    570 	}
    571 	print SUM_LOG "  <TD>", $version, "</TD>\n";
    572 	print SUM_LOG "  <TD>", $release, "</TD>\n";
    573 	my $color_start = "";
    574 	my $color_end = "";
    575 	if ($build_status[$i] eq "PASSED") {
    576 	    $color_start = "<FONT COLOR=#11AA11>";
    577 	    $color_end = "</FONT>";
    578 	} elsif ($build_status[$i] eq "BEING_BUILT") {
    579 	    $color_start = "<FONT COLOR=#FFA500>";
    580 	    $color_end = "</FONT>";
    581 	} elsif ($build_status[$i] eq "DEP") {
    582 	    $color_start = "<FONT COLOR=#FFA500>";
    583 	    $color_end = "</FONT>";
    584 	} elsif ($build_status[$i] eq "NOT_BUILT") {
    585 	    $color_start = "";
    586 	    $color_end = "";
    587 	} else {
    588 	    $color_start = "<FONT COLOR=#CC1111>";
    589 	    $color_end = "</FONT>";
    590 	}
    591 	if (defined ($the_logdir_url) and ($build_status[$i] ne "NOT_BUILT")) {
    592 	    print SUM_LOG "  <TD><A HREF=\"$the_logdir_url/$log_name\">",
    593 	    $color_start, $build_status[$i], $color_end,
    594 	    "</A></TD>\n";
    595 	} else {
    596 	    print SUM_LOG "  <TD>", 
    597 	    $color_start, $build_status[$i], $color_end,
    598 	    "</A></TD>\n";
    599 	}
    600 	if ($build_status[$i] eq "PASSED") {
    601 	    if (defined ($the_rpm_url)) {
    602 		print SUM_LOG "  <TD>RPMS: \n";
    603 		my @rpms = $specs_to_build[$i]-> get_param_array ('rpms');
    604 		my $ctr = 1;
    605 		for my $rpm (@rpms) {
    606 		    print SUM_LOG "    <A HREF=\"$the_rpm_url/$rpm\">[$ctr]</a> \n";
    607 		    $ctr++;
    608 		}
    609 		print SUM_LOG "  </TD>\n";
    610 	    } else {
    611 		print SUM_LOG "  <TD>&nbsp;</TD>\n";
    612 	    }
    613 	} else {
    614 	    print SUM_LOG "  <TD><PRE>", $status_details[$i], "</PRE></TD>\n";
    615 	}
    616 	print SUM_LOG " </TR>\n";
    617     }
    618     print SUM_LOG "</TABLE><P>\n";
    619     print SUM_LOG "<SMALL>", `date`, "</SMALL>\n";
    620     print SUM_LOG "</BODY>\n</HTML>\n";
    621     close SUM_LOG;
    622 }
    623 
    624 # --------- rpm utility functions ------------------------------------------
    625 sub is_provided ($) {
    626     my $capability = shift;
    627 
    628     $capability =~ s/\s.*//;
    629     `sh -c "rpm -q --whatprovides $capability" >/dev/null 2>&1`;
    630     my $result = (! $?);
    631     `sh -c "rpm -q $capability" >/dev/null 2>&1`;
    632     $result = ($result or (! $?));
    633     
    634     return ($result);
    635 }
    636 
    637 sub what_provides ($) {
    638     my $capability = shift;
    639 
    640     $capability =~ s/ .*//;
    641     my $rpm=`sh -c "rpm -q --whatprovides $capability" 2>&1`;
    642     if ($?) {
    643 	$rpm=`sh -c "rpm -q $capability" 2>&1`;
    644     }
    645     chomp $rpm;
    646     return ($rpm);
    647 }
    648 
    649 sub spec_id_of ($) {
    650     my $name = shift;
    651 
    652     for (my $i = 0; $i <= $#specs_to_build; $i++) {
    653 	if ($specs_to_build[$i]->{name} eq $name) {
    654 	    return $i;
    655 	}
    656     }
    657 
    658     return undef;
    659 }
    660 
    661 sub install_good_rpms ($) {
    662     my $spec_id = shift;
    663 
    664     return if not defined($spec_id);
    665     my $spec = $specs_to_build[$spec_id];
    666 
    667     my @rpms =  $spec->get_param_array ('rpms');
    668     map $_ =~ s/$spec->{version}-$spec->{release}.$spec->{buildarchitecture}.rpm/[0-9]*-[0-9]*.*.rpm/, @rpms;
    669     map $_ =~ s/^/$the_good_build_dir\//, @rpms;
    670 
    671     for (my $i = 0; $i <= $#rpms; $i++) {
    672 	my $current_rpm = $rpms[$i];
    673 	msg_info (1, "Looking for last known good rpm as $current_rpm");
    674 	$rpms[$i] = find_file ($current_rpm);
    675 	if (not defined ($rpms[$i])) {
    676 	    msg_error ("No file matches $current_rpm");
    677 	    return 0;
    678 	} else {
    679 	    msg_info (1, "Found $rpms[$i]");
    680 	}
    681     }
    682 
    683     my $command = "rpm --upgrade -v @rpms";
    684 
    685     if ($verbose > 0) {
    686 	map msg_info (0, "Installing last known good rpm: $_\n"), @rpms;
    687     }
    688 
    689     my $msg=`$command 2>&1`;
    690 
    691     if ($? > 0) {
    692 	msg_error "failed to install last known good rpm: $msg";
    693 	$status_details[$spec_id] = $status_details[$spec_id] . 
    694 	    "; Failed to install last known good rpm: " . $msg;
    695 	return 0;
    696     }
    697 
    698     if (defined ($the_good_rpms_copy_dir)) {
    699 	`mkdir -p $the_good_rpms_copy_dir`;
    700 	`cp @rpms $the_good_rpms_copy_dir`;
    701     }
    702 
    703     return 1;
    704 }
    705 
    706 sub install_rpms ($) {
    707     my $spec_id = shift;
    708     my $spec = $specs_to_build[$spec_id];
    709 
    710     my @rpms =  $spec->get_param_array ('rpm_paths');
    711     map $_ =~ s/^/$the_sys_rpm_dir\//, @rpms;
    712     my $command = "rpm --upgrade -v @rpms";
    713 
    714     if ($verbose > 0) {
    715 	map msg_info (0, "Installing $_\n"), @rpms;
    716     }
    717 
    718     my $msg=`$command 2>&1`;
    719     if ($? > 0) {
    720 	msg_error "failed to install rpm: $msg";
    721 	$build_status[$spec_id] = 'FAILED';
    722 	$status_details[$spec_id] = $msg;
    723 	return 0;
    724     }
    725 
    726     return 1;
    727 }
    728 
    729 sub print_rpms ($) {
    730     my $spec_id = shift;
    731     my $spec = $specs_to_build[$spec_id];
    732 
    733     if ($full_path) {
    734 	my @rpms =  $spec->get_param_array ('rpm_paths');
    735 	map print("$the_sys_rpm_dir\/$_\n"), @rpms;
    736     } else {
    737 	my @rpms =  $spec->get_param_array ('rpms');
    738 	map print("$_\n"), @rpms;
    739     }
    740 }
    741 
    742 sub print_spec ($) {
    743     my $spec_id = shift;
    744     my $spec = $specs_to_build[$spec_id];
    745 
    746     print "$spec->{file_name}\n";
    747 }
    748 
    749 sub push_to_remove_list ($) {
    750     my $spec_id = shift;
    751     my $spec = $specs_to_build[$spec_id];
    752 
    753     my @rpms =  $spec->get_param_array ('packages');
    754     map unshift (@remove_list, $_), @rpms;
    755 }
    756 
    757 # --------- dependency checking code ---------------------------------------
    758 sub warn_always ($$$) {
    759     my $spec_name = shift;
    760     my $dep = shift;
    761     my $reason = shift;
    762 
    763     if ($reason eq "DEP_FAILED") {
    764 	msg_warning (1, "$spec_name requires $dep");
    765 	msg_warning (1, "but that failed to build");
    766 	msg_warning (1, "Can't build $spec_name");
    767     } elsif ($reason eq "NOT_FOUND") {
    768 	msg_warning (0, "no spec file or installed package provides $dep");
    769 	msg_warning (0, "can't build $spec_name");
    770     }
    771 }
    772 
    773 sub warn_once ($$$) {
    774     my $spec_name = shift;
    775     my $dep = shift;
    776     my $reason = shift;
    777 
    778     if ($reason eq "DEP_FAILED") {
    779 	# should not happen
    780 	msg_error ("assertion failed: warn_once / DEP_FAILED");
    781     } elsif ($reason eq "NOT_FOUND") {
    782 	if (not defined ($warned_about{$dep})) {
    783 	    msg_warning (1, "$dep is required but not found");
    784 	    $warned_about{$dep}=1;
    785 	}
    786     }
    787 }
    788 
    789 sub get_dependencies ($@) {
    790     my $spec_id = shift;
    791     my @packages = @_;
    792     my $spec = $specs_to_build[$spec_id];
    793 
    794     my @dependencies = ();
    795     my @this_pkg_requires;
    796     foreach my $pkg (@packages) {
    797 	@this_pkg_requires = $spec->get_pkg_param_array ($pkg, 'requires');
    798 	msg_debug (3, "adding \"@this_pkg_requires\" to the dependencies of $spec->{name}");
    799 	push (@dependencies, @this_pkg_requires);
    800     }
    801 
    802     return @dependencies;
    803 }
    804 
    805 sub check_dependency ($$&&@) {
    806     my $spec_id = shift;
    807     my $capability = shift;
    808     my $recursive_callback = shift;
    809     my $warning_callback = shift;
    810     my @rec_cb_opts = @_;
    811     my $spec_name = $specs_to_build[$spec_id]->{name};
    812 
    813     my $result = 1;
    814 
    815     if (not defined ($capability)) {
    816 	return 1;
    817     }
    818 
    819     if ((defined ($provider{$capability})) and
    820 	($provider{$capability} == $spec_id)) {
    821 	return 1;
    822     }
    823 
    824     if (defined $provider{$capability}) {
    825 	if ($build_status[$provider{$capability}] eq "PASSED") {
    826 	    return 1;
    827 	} elsif ($build_status[$provider{$capability}] ne "NOT_BUILT") {
    828 	    if (!is_provided ($capability)) {
    829 		&$warning_callback ($spec_name, $capability, "DEP_FAILED");
    830 		return 0;
    831 	    }
    832 	    return 1;
    833 	}
    834 
    835 	msg_info (1, "need to build $capability first");
    836 	my $save_log_name = $current_log;
    837 	my $result = &$recursive_callback ($provider{$capability}, @rec_cb_opts);
    838 	open_log ($save_log_name);
    839 	return $result;
    840     } elsif (!is_provided ($capability)) {
    841 	&$warning_callback ($spec_name, $capability, "NOT_FOUND");
    842 	return 0;
    843     } else {
    844 	return 1;
    845     }
    846 
    847     # should not happen
    848     msg_error("Assertion failed: check_dependency: return 0");
    849     return 0;
    850 }
    851 
    852 # --------- copy build spec files, tarballs, patches -----------------------
    853 sub copy_spec ($) {
    854     my $spec_id = shift;
    855     my $spec = $specs_to_build[$spec_id];
    856     my $spec_file = $spec->get_param ('file_name');
    857     my $base_name = $spec_file;
    858     $base_name =~ s/^.*\/([^\/]+)/$1/;
    859     my $target = "$the_sys_rpm_dir/SPECS/$base_name";
    860 
    861     msg_info (1, "copying spec file $base_name to the SPECS dir");
    862 
    863     if ($is_nightly) {
    864 	my $the_nightly_date = `date "+$the_nightly_date_format"`;
    865 	if ($? > 0) {
    866 	    msg_error ("incorrect date format: $the_nightly_date_format");
    867 	    $build_status[$spec_id] = 'ERROR';
    868 	    $status_details[$spec_id] = "incorrect nightly date format: $the_nightly_date";
    869 	    return 0;
    870 	}
    871 
    872 	open SPEC_OUT, ">$target";
    873 	my $msg=`cp $spec_file /tmp/.gnome_build.tmp.$$ 2>&1`;
    874 	if ($? > 0) {
    875 	    msg_error ("failed to copy $spec_file");
    876 	    msg_error ("can't continue with $spec->{name}");
    877 	    $build_status[$spec_id] = 'FAILED';
    878 	    $status_details[$spec_id] = "cound not copy spec file: $msg";
    879 	    return 0;
    880 	}
    881 	open SPEC_IN, "</tmp/.gnome_build.tmp.$$";
    882 	my $line;
    883 	while (1) {
    884 	    $line = <SPEC_IN>;
    885 	    if (not defined ($line)) {
    886 		last;
    887 	    }
    888 	    if ($line =~ /^Release\s*:/) {
    889 		$line =~ s/\s*$/.$the_nightly_date/;
    890 	    }
    891 	    print SPEC_OUT $line;
    892 	}
    893 	close SPEC_OUT;
    894 	close SPEC_IN;
    895 
    896 	`rm -f /tmp/.gnome_build.tmp.$$`;
    897 	my $s = rpm_spec->new ($target, $rpm_target);
    898 	$specs_to_build[$spec_id] = $s;
    899 	$s->add_define ("nightly", "1");
    900     } else {
    901 	`cmp -s $spec_file $target`;
    902 	if ($? != 0) {  # the files differ
    903 	    my $msg=`cp $spec_file $target 2>&1`;
    904 	    if ($? > 0) {
    905 		msg_error "failed to copy $spec_file";
    906 		$build_status[$spec_id] = 'FAILED';
    907 		$status_details[$spec_id] = "failed to copy spec file: $msg";
    908 		return 0;
    909 	    }
    910 	} else {
    911 	    msg_info (3, "   $spec_file and");
    912 	    msg_info (3, "   $target");
    913 	    msg_info (3, "   are the same; not copying");
    914 	}
    915     }
    916     
    917     return 1;
    918 }
    919 
    920 sub find_source ($$) {
    921     my $spec_id = shift;
    922     my $src = shift;
    923     my $is_tarball = 0;
    924     my $src_path;
    925 
    926     if ($src =~ /\.(tar\.gz|tgz|tar\.bz2|tar\.bzip2)$/) {
    927 	$is_tarball = 1;
    928 
    929 	$src_path = "$the_tarball_dir/$src";
    930 	if (! -f "$src_path") {
    931 	    msg_info (3, "   $src not found in $the_tarball_dir");
    932 	} else {
    933 	    msg_info (3, "   found in $the_tarball_dir");
    934 	    return $src_path;
    935 	}
    936     }
    937     foreach my $extsrcdir (@the_source_dirlist) {
    938 	$src_path = "$extsrcdir/$src";
    939 	if (! -f "$src_path") {
    940 	    msg_info (3, "   $src not found in $extsrcdir");
    941 	} else {
    942 	    msg_info (3, "   found in $extsrcdir");
    943 	    return "$src_path";
    944 	}
    945     }
    946 
    947     if (!$is_tarball) {
    948 	$src_path = "$the_tarball_dir/$src";
    949 	if (! -f "$src_path") {
    950 	    msg_info (3, "   trying the tarball directory");
    951 	    msg_info (3, "   $src not found in $the_tarball_dir");
    952 	} else {
    953 	    msg_info (3, "   found in $the_tarball_dir");
    954 	    msg_warning (1, "$src is not expected to be in the tarball dir");
    955 	    return $src_path;
    956 	}
    957     }
    958 
    959     $build_status[$spec_id] = 'FAILED';
    960     $status_details[$spec_id] = "Source $src not found";
    961     msg_error ("Source file $src not found");
    962     return undef;
    963 }
    964 
    965 sub copy_sources ($) {
    966     my $spec_id = shift;
    967     my $spec = $specs_to_build[$spec_id];
    968 
    969     my @sources = $spec->get_param_array ('sources');
    970     my $src_path;
    971     my $target;
    972 
    973     msg_info (1, "copying sources to $the_sys_rpm_dir/SOURCES");
    974 
    975     foreach my $src (@sources) {
    976 	if (not defined ($src)) {
    977 	    next;
    978 	}
    979         $src_path = find_source ($spec_id, $src);
    980 	if (not defined ($src_path)) {
    981 	    return 0;
    982 	}
    983 
    984 	msg_info (2, "   copying $src");
    985 
    986 	$target = "$the_sys_rpm_dir/SOURCES/$src";
    987 
    988 	`cmp -s $src_path $target`;
    989 
    990 	if ($? != 0) {  # the files differ
    991 	    my $msg=`cp $src_path $target 2>&1`;
    992 	    if ($? > 0) {
    993 		msg_error ("failed to copy $src_path");
    994 		$build_status[$spec_id] = 'ERROR';
    995 		$status_details[$spec_id] = $msg;
    996 		return 0;
    997 	    }
    998 	}
    999     
   1000     }
   1001 
   1002     return 1;
   1003 }
   1004 
   1005 sub copy_patches ($) {
   1006     my $spec_id = shift;
   1007     my $spec = $specs_to_build[$spec_id];
   1008 
   1009     my @patches = $spec->get_param_array ('patches');
   1010     my $patch_path;
   1011     my $target;
   1012     foreach my $patch (@patches) {
   1013 	if (not defined ($patch)) {
   1014 	    next;
   1015 	}
   1016 
   1017 	msg_info (2, "copying patch $patch");
   1018 
   1019 	$patch_path = "$the_patch_dir/$patch";
   1020 
   1021 	if (! -f "$patch_path") {
   1022 	    $build_status[$spec_id] = 'ERROR';
   1023 	    $status_details[$spec_id] = "Patch $patch_path not found";
   1024 	    msg_error ("Patch $patch_path not found");
   1025 	    return 0;
   1026 	}
   1027 
   1028 	$target = "$the_sys_rpm_dir/SOURCES/$patch";
   1029 
   1030 	`cmp -s $patch_path $target`;
   1031 
   1032 	if ($? != 0) {  # the files differ
   1033 	    my $msg=`cp $patch_path $target 2>&1`;
   1034 	    if ($? > 0) {
   1035 		msg_error "failed to copy $patch_path";
   1036 		$build_status[$spec_id] = 'ERROR';
   1037 		$status_details[$spec_id] = $msg;
   1038 		return 0;
   1039 	    }
   1040 	} else {
   1041 	    msg_info (3, "   $patch and");
   1042 	    msg_info (3, "   $the_sys_rpm_dir/SOURCES/$patch");
   1043 	    msg_info (3, "   are the same; not copying");
   1044 	}
   1045     
   1046     }
   1047 
   1048     return 1;
   1049 }
   1050 
   1051 # --------- build command --------------------------------------------------
   1052 sub do_build () {
   1053     print_live_status;
   1054 
   1055     for (my $i = 0; $i <= $#specs_to_build; $i++) {
   1056 	if ($build_status[$i] eq "NOT_BUILT") {
   1057 	    if (! build_spec ($i)) {
   1058 		if (defined ($the_good_build_dir)) {
   1059 		    msg_info (0, "Attempting to use a known good rpm");
   1060 		    install_good_rpms ($i);
   1061 		}
   1062 	    }
   1063 	    print_live_status;
   1064 	}
   1065 	if ($build_status[$i] ne "PASSED") {
   1066 	    if ($build_status[$i] ne "DEP_FAILED") {
   1067 		mail_log ($i);
   1068 	    }
   1069 	    $exit_val++;
   1070 	}
   1071     }
   1072 
   1073     if ($verbose > 0) {
   1074 	print_status;
   1075     }
   1076 }
   1077 
   1078 sub build_spec ($) {
   1079     my $spec_id = shift;
   1080     my $spec = $specs_to_build[$spec_id];
   1081     my $logname = $the_log_dir . "/" . get_log_name ($spec_id);
   1082 
   1083     msg_debug (0, "Trying to build $spec->{name}");
   1084     open_log ($logname);
   1085 
   1086     if ($build_status[$spec_id] ne "NOT_BUILT") {
   1087 	if ($build_status[$spec_id] eq "DEP") {
   1088 	    $build_status[$spec_id]="ERROR";
   1089 	    $status_details[$spec_id]="Circular dependency detected";
   1090 	    msg_error ("Circular dependency detected " .
   1091 		"while trying to build $spec->{name}");
   1092 	}
   1093 	return 0;
   1094     }
   1095 
   1096     my @packages = $spec->get_param_array ('packages');
   1097     msg_debug (3, "packages: $spec->{file_name} defines: @packages");
   1098 
   1099     foreach my $pkg (@packages) {
   1100 	if (not defined ($pkg)) {
   1101 	    next;
   1102 	}
   1103 	if ($build_and_install) {
   1104 	    msg_info (2, "Checking if $pkg is installed");
   1105 	    if (is_provided ($pkg) and $check_deps) {
   1106 		my $provider = what_provides ($pkg);
   1107 		msg_warning (0, "$pkg is already provided by $provider");
   1108 		msg_warning (0, "not building $pkg");
   1109 		$build_status[$spec_id]='SKIPPED';
   1110 		$status_details[$spec_id]="$pkg already installed";
   1111 		
   1112 		return 0;
   1113 	    }
   1114 	}
   1115     }
   1116 
   1117     if ($check_deps) {
   1118 	my @dependencies = get_dependencies ($spec_id, @packages);
   1119 
   1120 	my $this_result;
   1121 	my $result = 1;
   1122 
   1123 	$build_status[$spec_id] = "DEP";
   1124 	$status_details[$spec_id] = "building dependencies first";
   1125 	
   1126 	msg_info (1, "Checking dependencies of $spec->{name}");
   1127 
   1128 	foreach my $dep (@dependencies) {
   1129 	    $dep =~ s/\s.*//;
   1130 	    
   1131 	    $this_result = check_dependency ($spec_id, $dep,
   1132 					     \&build_spec, \&warn_always, ());
   1133 	    if (!$this_result and $build_and_install) {
   1134 		if (defined ($the_good_build_dir)) {
   1135 		    msg_info (0, "Attempting to use a known good rpm");
   1136 		    $this_result = install_good_rpms (spec_id_of ($dep));
   1137 		}
   1138 		if (! $this_result) {
   1139 		    msg_warning (1, "$spec->{name} requires $dep");
   1140 		}
   1141 	    }
   1142 	    $result = ($this_result and $result);
   1143 	}
   1144 	
   1145 	if (! $result) {
   1146 	    $build_status[$spec_id]="DEP_FAILED";
   1147 	    $status_details[$spec_id]="Dependency check failed";
   1148 		
   1149 	    msg_warning (0, "Dependency check for $spec->{name} failed");
   1150 
   1151 	    return 0;
   1152 	}
   1153     }
   1154 
   1155     copy_spec ($spec_id) || return 0;
   1156     copy_sources ($spec_id) || return 0;
   1157     copy_patches ($spec_id) || return 0;
   1158 
   1159     if ($live_summary) {
   1160 	$build_status[$spec_id] = 'BEING_BUILT';
   1161 	$status_details[$spec_id] = "$RPM_BUILD running";
   1162 	print_live_status;
   1163     }
   1164     run_rpmbuild_ba ($spec_id) || return 0;
   1165 
   1166     if ($build_and_install) {
   1167 	install_rpms ($spec_id) || return 0;
   1168     }
   1169 
   1170     $build_status[$spec_id] = "PASSED";
   1171     $status_details[$spec_id] = "";
   1172 
   1173     close_log;
   1174 
   1175     return 1;
   1176 
   1177 }
   1178 
   1179 sub run_rpmbuild_ba ($) {
   1180     my $spec_id = shift;
   1181     my $spec = $specs_to_build[$spec_id];
   1182     my $spec_file = $spec->get_param ('file_name');
   1183     my $base_name = $spec_file;
   1184     $base_name =~ s/^.*\/([^\/]+)/$1/;
   1185     my $log_name = "$base_name";
   1186     $log_name = get_log_name ($spec_id);
   1187 
   1188     msg_info (0, "Running rpm build of $spec->{name} ($base_name)");
   1189     msg_info (1, "Log file: $the_log_dir/$log_name");
   1190 
   1191     my $save_log_name = $current_log;
   1192     msg_log ("INFO: Starting $RPM_BUILD at " . `date`);
   1193     close_log;
   1194     my $tempfile = "/tmp/rpm.out.$$";
   1195     my $defnightly = "";
   1196     if ($is_nightly) {
   1197 	$defnightly = " --define \"nightly 1\""
   1198     }
   1199     my $rpmopt = "-ba";
   1200     if ($prep_only) {
   1201 	$rpmopt = "-bp";
   1202     }
   1203     if (!$check_deps) {
   1204 	$rpmopt = "$rpmopt --nodeps";
   1205     }
   1206     if (defined ($the_sys_rpm_dir) and $the_sys_rpm_dir ne "/usr/src/packages") {
   1207 	$rpmopt = "$rpmopt --define \"_topdir $the_sys_rpm_dir\"";
   1208     }
   1209     if (defined($rpm_target) and ($rpm_target eq $spec->{buildarchitecture})) {
   1210         system ("$RPM_BUILD --target $rpm_target $rpmopt $the_sys_rpm_dir/SPECS/$base_name $defnightly > $tempfile 2>&1");
   1211     } else {
   1212         system ("$RPM_BUILD $rpmopt $the_sys_rpm_dir/SPECS/$base_name $defnightly > $tempfile 2>&1");
   1213     }
   1214     my $rpm_result = $?;
   1215     system ("sed -e 's/^/RPM: /' $tempfile >> $the_log_dir/$log_name 2>&1; rm -f $tempfile");
   1216     open_log ($save_log_name);
   1217     msg_log ("INFO: $RPM_BUILD finished at " . `date`);
   1218 
   1219     if ($rpm_result) {
   1220 	msg_error ("Build of $spec->{name} FAILED");
   1221 	$build_status[$spec_id] = "FAILED";
   1222 	$status_details[$spec_id] = 'RPM build failed';
   1223 	return 0;
   1224     }
   1225 
   1226     msg_info (0, "$spec->{name} PASSED");
   1227     return 1;
   1228 }
   1229 
   1230 # --------- build-order and install-order commands -------------------------
   1231 sub do_build_order () {
   1232     for (my $i = 0; $i <= $#specs_to_build; $i++) {
   1233 	print_order ($i, \&print_spec);
   1234     }
   1235 }
   1236 
   1237 sub do_install_order () {
   1238     for (my $i = 0; $i <= $#specs_to_build; $i++) {
   1239 	print_order ($i, \&print_rpms);
   1240     }
   1241 }
   1242 
   1243 sub print_order ($&) {
   1244     my $spec_id = shift;
   1245     my $print_command = shift;
   1246     my $spec = $specs_to_build[$spec_id];
   1247 
   1248     if ($build_status[$spec_id] ne "NOT_BUILT") {
   1249 	if ($build_status[$spec_id] eq "DEP") {
   1250 	    $build_status[$spec_id]="ERROR";
   1251 	    $status_details[$spec_id]="Circular dependency detected";
   1252 	    msg_error ("Circular dependency detected " .
   1253 		"while checking dependencies of $spec->{name}");
   1254 	}
   1255 	return 0;
   1256     }
   1257 
   1258     if ($check_deps) {
   1259 	my @packages = $spec->get_param_array ('packages');
   1260 	my @dependencies = get_dependencies ($spec_id, @packages);
   1261 
   1262 	$build_status[$spec_id] = "DEP";
   1263 	
   1264 	msg_info (1, "Checking dependencies of $spec->{name}");
   1265 
   1266 	foreach my $dep (@dependencies) {
   1267 	    $dep =~ s/\s.*//;	
   1268     
   1269 	    check_dependency ($spec_id, $dep, \&print_order, \&warn_once, ($print_command));	}
   1270     }
   1271     
   1272     copy_spec ($spec_id) || return 0;
   1273 
   1274     $build_status[$spec_id] = "PASSED";
   1275     &$print_command ($spec_id);
   1276 }
   1277 
   1278 # --------- uninstall-pkgs command -----------------------------------------
   1279 sub do_uninstall_pkgs () {
   1280     for (my $i = 0; $i <= $#specs_to_build; $i++) {
   1281 	print_order ($i, \&push_to_remove_list);
   1282     }
   1283 
   1284     foreach my $pkg_to_remove (@remove_list) {
   1285 	msg_info (0, "Removing $pkg_to_remove");
   1286 	my $cmd_out = `rpm -v --erase --nodeps $pkg_to_remove 2>&1`;
   1287 	if ($? > 0) {
   1288 	    $exit_val++;
   1289 	}
   1290 	$cmd_out =~ s/^/INFO: rpm: /;
   1291 	if ($verbose > 0) {
   1292 	    print $cmd_out . "\n";
   1293 	}
   1294     }
   1295 }
   1296 
   1297 # --------- main program ---------------------------------------------------
   1298 sub main {
   1299     process_options;
   1300 
   1301     if (not defined ($build_command)) {
   1302 	usage (1);
   1303     }
   1304     
   1305     if (not defined ($specs_to_build[0])) {
   1306 	msg_info (0, "Nothing to do.");
   1307 	exit (0);
   1308     }
   1309 
   1310     if ($build_command eq "build") {
   1311 	do_build;
   1312     } if ($build_command eq "build-install") {
   1313 	do_build;
   1314     } if ($build_command eq "build-only") {
   1315 	$build_and_install = 0;
   1316 	do_build;
   1317     } if ($build_command eq "prep") {
   1318 	$build_and_install = 0;
   1319 	$prep_only = 1;
   1320 	do_build;
   1321     } elsif ($build_command eq "uninstall-pkgs") {
   1322 	do_uninstall_pkgs;
   1323     } elsif ($build_command eq "build-order") {
   1324 	do_build_order;
   1325     } elsif ($build_command eq "install-order") {
   1326 	do_install_order;
   1327     }
   1328 
   1329     exit ($exit_val);
   1330 }
   1331 
   1332 main;
   1333