2006-12-05 22:58:38 +03:00
|
|
|
#
|
|
|
|
# Config object for release automation
|
|
|
|
#
|
|
|
|
|
|
|
|
package Bootstrap::Config;
|
|
|
|
|
|
|
|
use strict;
|
2007-05-09 06:02:33 +04:00
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
use POSIX "uname";
|
2007-04-18 02:49:31 +04:00
|
|
|
use File::Copy qw(move);
|
2007-05-09 06:02:33 +04:00
|
|
|
|
2007-07-12 21:47:39 +04:00
|
|
|
use Bootstrap::Util qw(GetLocaleManifest CvsCatfile);
|
2007-05-09 06:02:33 +04:00
|
|
|
|
2006-12-05 22:58:38 +03:00
|
|
|
# shared static config
|
|
|
|
my %config;
|
|
|
|
|
|
|
|
# single shared instance
|
|
|
|
my $singleton = undef;
|
|
|
|
|
|
|
|
sub new {
|
|
|
|
my $proto = shift;
|
|
|
|
my $class = ref($proto) || $proto;
|
|
|
|
|
|
|
|
return $singleton if defined $singleton;
|
|
|
|
|
|
|
|
my $this = {};
|
|
|
|
bless($this, $class);
|
|
|
|
$this->Parse();
|
|
|
|
$singleton = $this;
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub Parse {
|
|
|
|
my $this = shift;
|
|
|
|
|
2007-04-18 02:49:31 +04:00
|
|
|
open(CONFIG, "< bootstrap.cfg")
|
2007-02-08 01:14:24 +03:00
|
|
|
|| die("Can't open config file bootstrap.cfg");
|
2006-12-05 22:58:38 +03:00
|
|
|
|
|
|
|
while (<CONFIG>) {
|
2007-07-06 02:58:32 +04:00
|
|
|
# no comments or empty lines
|
|
|
|
next if ($_ =~ /^#/ || $_ =~ /^\s*$/);
|
2006-12-05 22:58:38 +03:00
|
|
|
s/^\s+//; # no leading white
|
|
|
|
s/\s+$//; # no trailing white
|
2007-07-06 02:58:32 +04:00
|
|
|
chomp $_; # no newline
|
2006-12-05 22:58:38 +03:00
|
|
|
my ($var, $value) = split(/\s*=\s*/, $_, 2);
|
2007-07-06 02:58:32 +04:00
|
|
|
$this->Set(var => $var, value => $value);
|
2006-12-05 22:58:38 +03:00
|
|
|
}
|
2007-04-18 02:49:31 +04:00
|
|
|
close(CONFIG);
|
2006-12-05 22:58:38 +03:00
|
|
|
}
|
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
##
|
|
|
|
# Get checks to see if a variable exists and returns it.
|
|
|
|
# Returns scalar
|
|
|
|
#
|
|
|
|
# This method supports system-specific overrides, or "sysvar"s.
|
|
|
|
# For example, if a caller is on win32 and does
|
|
|
|
# Get(sysvar => "buildDir") and win32_buildDir exists, the value of
|
|
|
|
# win32_buildDir will be returned. If not, the value of buildDir will
|
|
|
|
# be returned. Otherwise, the die() assertion will be hit.
|
|
|
|
##
|
|
|
|
|
2006-12-05 22:58:38 +03:00
|
|
|
sub Get {
|
|
|
|
my $this = shift;
|
|
|
|
|
|
|
|
my %args = @_;
|
|
|
|
my $var = $args{'var'};
|
2007-03-26 03:54:25 +04:00
|
|
|
# sysvar will attempt to prepend the OS name to the requested var
|
|
|
|
my $sysvar = $args{'sysvar'};
|
2006-12-05 22:58:38 +03:00
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
if ((! defined($args{'var'})) && (! defined($args{'sysvar'}))) {
|
|
|
|
die "ASSERT: Bootstep::Config::Get(): null var requested";
|
|
|
|
} elsif ((defined($args{'var'})) && (defined($args{'sysvar'}))) {
|
|
|
|
die "ASSERT: Bootstep::Config::Get(): both var and sysvar requested";
|
|
|
|
}
|
2007-03-26 03:54:25 +04:00
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
if (defined($args{'sysvar'})) {
|
|
|
|
# look for a system specific var first
|
|
|
|
my $osname = $this->SystemInfo(var => 'osname');
|
|
|
|
my $sysvarOverride = $osname . '_' . $sysvar;
|
|
|
|
|
|
|
|
if ($this->Exists(var => $sysvarOverride)) {
|
|
|
|
return $config{$sysvarOverride};
|
|
|
|
} elsif ($this->Exists(var => $sysvar)) {
|
|
|
|
return $config{$sysvar};
|
|
|
|
} else {
|
|
|
|
die("No such system config variable: $sysvar");
|
|
|
|
}
|
|
|
|
} elsif ($this->Exists(var => $var)) {
|
2006-12-05 22:58:38 +03:00
|
|
|
return $config{$var};
|
|
|
|
} else {
|
2007-03-26 03:54:25 +04:00
|
|
|
die("No such config variable: $var");
|
2008-01-08 20:39:11 +03:00
|
|
|
}
|
2008-04-28 17:48:27 +04:00
|
|
|
}
|
|
|
|
|
2007-07-06 02:58:32 +04:00
|
|
|
sub Set {
|
|
|
|
my $this = shift;
|
|
|
|
|
|
|
|
my %args = @_;
|
|
|
|
|
|
|
|
die "ASSERT: Config::Set(): null var and/or value\n" if
|
|
|
|
(!exists($args{'var'}) || !exists($args{'value'}));
|
|
|
|
|
|
|
|
die "ASSERT: Config::Set(): Cannot set null var\n" if
|
|
|
|
(!defined($args{'var'}) ||
|
|
|
|
(defined($args{'var'}) && $args{'var'} =~ /^\s*$/));
|
|
|
|
|
|
|
|
my $var = $args{'var'};
|
|
|
|
my $value = $args{'value'};
|
|
|
|
my $force = exists($args{'force'}) ? $args{'force'} : 0;
|
|
|
|
|
|
|
|
die "ASSERT: Config::Set(): $var already exists ($value)\n" if
|
|
|
|
(!$force && exists($config{$var}));
|
|
|
|
|
|
|
|
die "ASSERT: Config::Set(): Attempt to set null value for var $var\n" if
|
|
|
|
(!$force && (!defined($value) || $value =~ /^\s*$/));
|
|
|
|
|
|
|
|
return ($config{$var} = $value);
|
|
|
|
}
|
|
|
|
|
2007-05-09 06:02:33 +04:00
|
|
|
sub GetLocaleInfo {
|
|
|
|
my $this = shift;
|
|
|
|
|
|
|
|
if (! $this->Exists(var => 'localeInfo')) {
|
|
|
|
my $localeFileTag = $this->Get(var => 'productTag') . '_RELEASE';
|
|
|
|
$config{'localeInfo'} = GetLocaleManifest(
|
|
|
|
app => $this->Get(var => 'appName'),
|
|
|
|
cvsroot => $this->Get(var => 'mozillaCvsroot'),
|
|
|
|
tag => $localeFileTag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->Get(var => 'localeInfo');
|
|
|
|
}
|
|
|
|
|
2007-07-12 21:47:39 +04:00
|
|
|
##
|
|
|
|
# GetFtpCandidateDir - construct the FTP path for pushing builds & updates to
|
|
|
|
# returns scalar
|
|
|
|
#
|
|
|
|
# mandatory argument:
|
|
|
|
# bitsUnsigned - boolean - 1 for unsigned, 0 for signed
|
|
|
|
# adds "unsigned/" prefix for windows and version >= 2.0
|
|
|
|
##
|
|
|
|
|
|
|
|
sub GetFtpCandidateDir {
|
|
|
|
my $this = shift;
|
|
|
|
my %args = @_;
|
|
|
|
|
|
|
|
if (! defined($args{'bitsUnsigned'})) {
|
|
|
|
die "ASSERT: Bootstep::Config::GetFtpCandidateDir(): bitsUnsigned is a required argument";
|
|
|
|
}
|
|
|
|
my $bitsUnsigned = $args{'bitsUnsigned'};
|
|
|
|
|
|
|
|
my $product = $config{'product'};
|
|
|
|
my $version = $config{'version'};
|
|
|
|
my $rc = $config{'rc'};
|
|
|
|
|
|
|
|
my $candidateDir = CvsCatfile('/home', 'ftp', 'pub', $product, 'nightly',
|
|
|
|
$version . '-candidates', 'rc' . $rc ) . '/';
|
|
|
|
|
|
|
|
my $osFileMatch = $this->SystemInfo(var => 'osname');
|
|
|
|
|
|
|
|
if ($bitsUnsigned && ($osFileMatch eq 'win32') && ($version ge '2.0')) {
|
|
|
|
$candidateDir .= 'unsigned/';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $candidateDir;
|
|
|
|
}
|
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
##
|
|
|
|
# Exists checks to see if a config variable exists.
|
|
|
|
# Returns boolean (1 or 0)
|
|
|
|
#
|
|
|
|
# This method supports system-specific overrides, or "sysvar"s.
|
|
|
|
# For example, if a caller is on win32 and does
|
|
|
|
# Exists(sysvar => "win32_buildDir") and only buildDir exists, a 0
|
|
|
|
# will be returned. There is no "fallback" as in the case of Get.
|
|
|
|
##
|
|
|
|
|
2007-02-09 04:23:34 +03:00
|
|
|
sub Exists {
|
|
|
|
my $this = shift;
|
|
|
|
my %args = @_;
|
2007-03-26 03:54:25 +04:00
|
|
|
my $var = $args{'var'};
|
|
|
|
# sysvar will attempt to prepend the OS name to the requested var
|
|
|
|
my $sysvar = $args{'sysvar'};
|
2007-03-26 03:54:25 +04:00
|
|
|
|
2007-03-26 03:54:25 +04:00
|
|
|
if ((! defined($args{'var'})) && (! defined($args{'sysvar'}))) {
|
|
|
|
die "ASSERT: Bootstep::Config::Get(): null var requested";
|
|
|
|
} elsif ((defined($args{'var'})) && (defined($args{'sysvar'}))) {
|
|
|
|
die "ASSERT: Bootstep::Config::Get(): both var and sysvar requested";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($args{'sysvar'})) {
|
|
|
|
# look for a system specific var first
|
|
|
|
my $osname = $this->SystemInfo(var => 'osname');
|
|
|
|
my $sysvarOverride = $osname . '_' . $sysvar;
|
|
|
|
|
|
|
|
if (exists($config{$sysvarOverride})) {
|
|
|
|
return 1;
|
|
|
|
} elsif (exists($config{$sysvar})) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return exists($config{$var});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub SystemInfo {
|
|
|
|
my $this = shift;
|
|
|
|
my %args = @_;
|
2007-03-10 00:20:05 +03:00
|
|
|
|
2007-02-09 04:23:34 +03:00
|
|
|
my $var = $args{'var'};
|
2007-03-26 03:54:25 +04:00
|
|
|
|
|
|
|
my ($sysname, $hostname, $release, $version, $machine ) = uname;
|
|
|
|
|
|
|
|
if ($var eq 'sysname') {
|
|
|
|
return $sysname;
|
|
|
|
} elsif ($var eq 'hostname') {
|
|
|
|
return $hostname;
|
|
|
|
} elsif ($var eq 'release') {
|
|
|
|
return $release;
|
|
|
|
} elsif ($var eq 'version') {
|
|
|
|
return $version;
|
|
|
|
} elsif ($var eq 'machine') {
|
|
|
|
return $machine;
|
|
|
|
} elsif ($var eq 'osname') {
|
|
|
|
if ($sysname =~ /cygwin/i) {
|
|
|
|
return 'win32';
|
|
|
|
} elsif ($sysname =~ /darwin/i) {
|
|
|
|
return 'macosx';
|
|
|
|
} elsif ($sysname =~ /linux/i) {
|
|
|
|
return 'linux';
|
|
|
|
} else {
|
|
|
|
die("Unrecognized OS: $sysname");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
die("No system info named $var");
|
|
|
|
}
|
2007-04-18 02:49:31 +04:00
|
|
|
}
|
|
|
|
|
2007-04-18 02:49:31 +04:00
|
|
|
##
|
|
|
|
# Bump - modifies config files
|
|
|
|
#
|
|
|
|
# Searches and replaces lines of the form:
|
|
|
|
# # CONFIG: $BuildTag = '%productTag%_RELEASE';
|
|
|
|
# $BuildTag = 'FIREFOX_1_5_0_9_RELEASE';
|
|
|
|
#
|
|
|
|
# The comment containing "CONFIG:" is parsed, and the value in between %%
|
|
|
|
# is treated as the key. The next line will be overwritten by the value
|
|
|
|
# matching this key in the private %config hash.
|
|
|
|
#
|
|
|
|
# If any of the requested keys are not found, this function calls die().
|
|
|
|
##
|
|
|
|
|
|
|
|
sub Bump {
|
|
|
|
my $this = shift;
|
|
|
|
my %args = @_;
|
|
|
|
|
|
|
|
my $config = new Bootstrap::Config();
|
|
|
|
|
|
|
|
my $configFile = $args{'configFile'};
|
|
|
|
if (! defined($configFile)) {
|
|
|
|
die('ASSERT: Bootstrap::Config::Bump - configFile is a required argument');
|
|
|
|
}
|
|
|
|
|
|
|
|
my $tmpFile = $configFile . '.tmp';
|
|
|
|
|
|
|
|
open(INFILE, "< $configFile")
|
|
|
|
or die ("Bootstrap::Config::Bump - Could not open $configFile for reading: $!");
|
|
|
|
open(OUTFILE, "> $tmpFile")
|
|
|
|
or die ("Bootstrap::Config::Bump - Could not open $tmpFile for writing: $!");
|
|
|
|
|
|
|
|
my $skipNextLine = 0;
|
2007-06-14 07:45:00 +04:00
|
|
|
my $KEY_REGEX = qr/ ([\w\-]+) /x;
|
2007-04-18 02:49:31 +04:00
|
|
|
foreach my $line (<INFILE>) {
|
|
|
|
if ($skipNextLine) {
|
|
|
|
$skipNextLine = 0;
|
|
|
|
next;
|
|
|
|
} elsif ($line =~ /^# CONFIG:\s+/) {
|
|
|
|
print OUTFILE $line;
|
|
|
|
$skipNextLine = 1;
|
|
|
|
my $interpLine = $line;
|
|
|
|
$interpLine =~ s/^#\s+CONFIG:\s+//;
|
2007-06-14 07:45:00 +04:00
|
|
|
foreach my $variable (grep(/%/,split(/(%$KEY_REGEX?%)/, $line))) {
|
2007-04-18 02:49:31 +04:00
|
|
|
my $key = $variable;
|
2007-06-14 07:45:00 +04:00
|
|
|
if (! ($key =~ s/.*%($KEY_REGEX)%.*/$1/)) {
|
2007-04-18 02:49:31 +04:00
|
|
|
die("ASSERT: could not parse $variable");
|
|
|
|
}
|
|
|
|
|
2007-06-14 07:45:00 +04:00
|
|
|
$key =~ s/^%(.*)%$/$1/;
|
|
|
|
|
|
|
|
if ($key =~ /^\s*$/) {
|
|
|
|
die("ASSERT: could not get key from $variable");
|
|
|
|
}
|
|
|
|
|
2007-04-20 22:55:24 +04:00
|
|
|
if (! $config->Exists(sysvar => $key)) {
|
2007-04-18 02:49:31 +04:00
|
|
|
die("ASSERT: no replacement found for $key");
|
|
|
|
}
|
2007-04-20 22:55:24 +04:00
|
|
|
my $value = $config->Get(sysvar => $key);
|
2007-04-18 02:49:31 +04:00
|
|
|
$interpLine =~ s/\%$key\%/$value/g;
|
|
|
|
}
|
|
|
|
print OUTFILE $interpLine;
|
|
|
|
} else {
|
|
|
|
print OUTFILE $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(INFILE) or die ("Bootstrap::Config::Bump - Could not close $configFile for reading: $!");
|
|
|
|
close(OUTFILE) or die ("Bootstrap::Config::Bump - Could not close $tmpFile for writing: $!");
|
|
|
|
|
|
|
|
move($tmpFile, $configFile)
|
|
|
|
or die("Cannot rename $tmpFile to $configFile: $!");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-12-05 22:58:38 +03:00
|
|
|
1;
|