#!/usr/bin/perl -w # Copyright (c) 2007-2008 Fabien Tassin # Description: The 'mozclient' module of mozilla-devscripts # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2, or (at # your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ############################################################################ use strict; use Getopt::Long qw(:config no_auto_abbrev no_ignore_case require_order bundling); my $mozclient_dir = "/usr/share/mozilla-devscripts"; my $pkg_conf_dir = "$mozclient_dir/mozclient"; my $patches_dir = "$pkg_conf_dir/patches"; my $work_dir = "mozclient-tmp"; my @conf_mandatory = qw(MOZCLIENT_APPNAME MOZCLIENT_FILE MOZCLIENT_GETVERSION MOZCLIENT_GETDATE MOZCLIENT_VCS); my @conf_optional = qw(MOZCLIENT_MODULES MOZCLIENT_PROJECT MOZCLIENT_BRANCH MOZCLIENT_POSTCOCMD MOZCLIENT_EMBEDDED MOZCLIENT_WANTMOZDIR MOZCLIENT_WANTPATCH MOZCLIENT_DYNTAG MOZCLIENT_DYNTAG_FILES MOZCLIENT_CVS_LOC MOZCLIENT_HG_LOC); my @conf_list = qw(MOZCLIENT_FILE); my $defaults = { 'MOZCLIENT_CVS_LOC' => ':pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot', 'MOZCLIENT_HG_LOC' => 'http://hg.mozilla.org/', 'MOZCLIENT_EXCLUDE_SCRIPT' => 'remove.binonly.sh', 'MOZILLA_CLIENT' => 'mozilla/client.mk', 'MOZCLIENT_PATCHES' => "$patches_dir", }; BEGIN { # We look for modules in /usr/share/mozilla-devscripts/mozclient/lib # We can prefer another path by using '--conf-dir path' or '-c path' unshift @INC, "/usr/share/mozilla-devscripts/mozclient/lib"; my @args = @ARGV; while (1) { my $arg = shift @args; last unless defined $arg; next unless $arg eq '-c' || $arg eq '--conf-dir'; my $path = shift @args; die "Usage error: $arg needs an argument\n" unless defined $path; unshift @INC, $path; last; } } sub help { print < nspr_4.7.2~beta+1.9~cvs20080516t2119.orig.tar.gz mozclient.pl --date 20080101t0000 nspr => nspr_4.7~beta+1.9b3~cvs20080101t0000.orig.tar.gz mozclient.pl --tag FIREFOX_3_0rc1_RELEASE nspr => nspr_4.7.1+1.9.orig.tar.gz mozclient.pl --tag FIREFOX_3_0rc1_RELEASE=1.2.3 nspr => nspr_1.2.3.orig.tar.gz EOF exit(0); } sub _split_args { my $str = shift; # We want to split words and quoted strings by blanks my @data; while (length($str)) { $str =~ m/^\s/ && do { $str =~ s/^\s+//; 1; } || $str =~ m/^'/ && do { $str =~ s/^'(.*?)'//; push @data, $1; 1; } || $str =~ m/^"/ && do { $str =~ s/^"(.*?)"//; push @data, $1; 1; } || $str =~ m/^\S+=".*?"/ && do { $str =~ s/^(\S+)="(.*?)"//; push @data, "$1=$2"; 1; } || do { $str =~ s/^(\S+)//; push @data, $1; }; } return \@data; } # Read the project conf file sub read_project_file { my $pkg = shift; my $file = sprintf "%s/%s.conf", $pkg_conf_dir, $pkg; my $data = {}; open(CONF, "$file") || die "Can't open $file: $!\n"; while (defined (my $line = )) { $line =~ s/([^\\])#.*/$1/; # drop comments, but not \# $line =~ s/(^\s+|\s+$)//; next if $line =~ m/^#/; next if $line =~ m/^\s*$/; $line =~ m/^(\S+)\s*=\s*(.*)/; $$data{$1} = defined $2 && length($2) ? $2 : undef; } close CONF; # Check all mandatory keywords/variables are there my $missing = []; my $extra = []; my $opts = {}; map { $$opts{$_} = 1 } @conf_mandatory, @conf_optional; map { push @$extra, $_ unless defined $$opts{$_} } keys %$data; map { push @$missing, $_ unless defined $$data{$_} } @conf_mandatory; if ($#$extra >= 0) { die "# Error in $file: unknown keywords found: " . (join ", ", @$extra) . "\n"; } if ($#$missing >= 0) { die "# Error in $file: mandatory keywords missing: " . (join ", ", @$missing) . "\n"; } # Set default values map { $$data{$_} = $$defaults{$_} unless defined $$data{$_} } keys %$defaults; # Transform into lists arguments that are supposed to be lists map { $$data{$_} = _split_args($$data{$_}) if defined $$data{$_} } @conf_list; return $data; } ############################################################################ use MozClient::CVS; use MozClient::Mercurial; # Main my $opt = {}; GetOptions($opt, 'conf-dir|c=s', 'debug|D+', 'list-tags|l', 'branch|b=s', 'date|d=s', 'tag|t=s', 'preserve-vcs|p') || &help(); &help() unless $#ARGV >= 0; my $conf = &read_project_file(shift @ARGV); my $client; my $vcs = $$conf{'MOZCLIENT_VCS'}; $vcs eq 'cvs' && do { $client = MozClient::CVS->new($conf, $opt); 1; } || $vcs eq 'hg' && do { $client = MozClient::Mercurial->new($conf, $opt); 1; } || do { die "VCS '$$conf{'MOZCLIENT_VCS'}' not supported yet"; }; $client->work_dir($work_dir); $client->check_dependencies(); $client->prepare_dir(); if ($client->want_list_tags) { $client->list_tags(); $client->cleanup_dir(); exit(0); } $client->setup(); # We need the mozilla client if we want to fetch a project $client->get_client() if defined $client->{'MOZCLIENT_PROJECT'}; # We also want to checkout using a date or a revision to avoid been # caught in mid-air with another commit, unless a tag is requested $client->set_revdate() unless defined $client->{'want_tag'}; if (!defined $client->{'have_date'} && !defined $client->{'want_tag'}) { die "Error: neither date nor tag found. Did getdate failed ?"; } # Finally do the real checkout $client->checkout(); # Do post-co commands if we have to $client->do_post_co_commands() if defined $client->{'MOZCLIENT_POSTCOCMD'}; # Remove binary only files and preserve a log file if we indeed removed # something. In case we didn't, drop the log file $client->nobin_cleanup(); # Create the tarball $client->pack();