aboutsummaryrefslogtreecommitdiffstats
path: root/init-repository
diff options
context:
space:
mode:
authorRohan McGovern <rohan.mcgovern@nokia.com>2011-05-06 10:52:54 +1000
committerRohan McGovern <rohan.mcgovern@nokia.com>2011-05-06 13:42:18 +1000
commit9bf69ecc2ffef367dded2d5b56a6f309cc183d91 (patch)
treeccdfe4a0d895268917a80edb8883620c519596fc /init-repository
parent780b928e4c2d691ea4716ac058f0ed4c77569770 (diff)
Improve maintainability of init-repository script.
Make it object-oriented. Document via pod and use pod2usage to implement `--help'. Use Getopt::Long instead of hand-rolled argument parsing. Make it pass `perlcritic -stern'. Check the exit code of all commands. Reviewed-by: Sunil Thaha Reviewed-by: Lincoln Ramsay Change-Id: Iac2a3358a05db7cdd953ba3d5396a8bb6bcfb44b
Diffstat (limited to 'init-repository')
-rwxr-xr-xinit-repository631
1 files changed, 425 insertions, 206 deletions
diff --git a/init-repository b/init-repository
index f343ef67..b6b30c7f 100755
--- a/init-repository
+++ b/init-repository
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
#############################################################################
##
## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
@@ -43,250 +43,469 @@
use strict;
use warnings;
-my $force = 0;
-my $quiet = 0;
-my $nokia_developer = 0;
-my $no_webkit = 0;
-my $no_update = 0;
-my $ignore_submodules = 0;
-my $alternates = "";
-my $detach_alternates = 0;
-my $mirror_url = "";
-my $mirror_webkit_url = "";
-
-my $protocol = "";
-my %protocols = (
- 'internal' => 'git://scm.dev.nokia.troll.no/',
- 'ssh' => 'git@scm.dev.nokia.troll.no:',
- 'http' => 'http://git.gitorious.org/'
+package Qt::InitRepository;
+
+
+=head1 NAME
+
+init-repository - initialize the Qt5 repository and all submodules
+
+=head1 SYNOPSIS
+
+ ./init-repository [options]
+
+This script may be run after an initial `git clone' of Qt5 in order to check
+out all submodules.
+
+
+=head2 Global options:
+
+=over
+
+=item --force, -f
+
+Force initialization (even if the submodules are already checked out).
+
+
+=item --quiet, -q
+
+Be quiet. Will exit cleanly if the repository is already initialized.
+
+=back
+
+
+=head2 Module options:
+
+=over
+
+=item --no-webkit
+
+Skip webkit and webkit examples submodules.
+It may be desirable to skip these modules due to the large size of the webkit
+git repository.
+
+
+=item --no-update
+
+Skip the `git submodule update' command.
+
+
+=item --ignore-submodules
+
+Set git config to ignore submodules by default when doing operations on the
+qt5 repo, such as `pull', `fetch', `diff' etc.
+
+After using this option, pass `--ignore-submodules=none' to git to override
+it as needed.
+
+=back
+
+
+=head2 Repository options:
+
+=over
+
+=item --nokia-developer
+
+Switch to internal Nokia URLs.
+
+
+=item --brisbane
+
+Switch to internal Nokia URLs and make use of the Brisbane git mirrors.
+(Implies `--mirror' and `--mirror-webkit').
+
+
+=item --ssh
+
+Use the SSH protocol for git operations. This may be useful if the git
+protocol is blocked by a firewall. Note that this requires a user account
+with an uploaded SSH key on all servers used. (Implies `--nokia-developer').
+
+
+=item --http
+
+Use the HTTP protocol for git operations. This may be useful if the git
+protocol is blocked by a firewall. Note that this only works with the
+external Gitorious server.
+
+
+=item --alternates <path to other Qt5 repo>
+
+Adds alternates for each submodule to another full qt5 checkout. This makes
+this qt5 checkout very small, as it will use the object store of the
+alternates before unique objects are stored in its own object store.
+
+This option has no effect when using `--no-update'.
+
+B<NOTE:> This will make this repo dependent on the alternate, which is
+potentially dangerous! The dependency can be broken by also using
+the `--copy-objects' option, or by running C<git repack -a> in each
+submodule, where required. Please read the note about the `--shared' option
+in the documentation of `git clone' for more information.
+
+
+=item --copy-objects
+
+When `--alternates' is used, automatically do a C<git repack -a> in each
+submodule after cloning, to ensure that the repositories are independent
+from the source used as a reference for cloning.
+
+Note that this negates the disk usage benefits gained from the use of
+`--alternates'.
+
+
+=item --mirror <url-base>
+
+Uses <url-base> as the base URL for submodule git mirrors.
+
+For example:
+
+ --mirror user@machine:/foo/bar
+
+...will use the following as a mirror for qtbase:
+
+ user@machine:/foo/bar/qtbase.git
+
+
+=item --mirror-webkit <url>
+
+Uses <url> as the URL for the webkit git mirror.
+
+=back
+
+=cut
+
+use Carp qw( confess );
+use English qw( -no_match_vars );
+use Getopt::Long qw( GetOptionsFromArray );
+use Pod::Usage qw( pod2usage );
+
+my %PROTOCOLS = (
+ 'internal' => 'git://scm.dev.nokia.troll.no/' ,
+ 'ssh' => 'git@scm.dev.nokia.troll.no:' ,
+ 'http' => 'http://git.gitorious.org/' ,
);
-my %staging_repos = (
- 'qt3support-staging' => 'git://gitorious.org/qt/qt3support-staging.git',
- 'qtactiveqt-staging' => 'git://gitorious.org/qt/qtactiveqt-staging.git',
- 'qtbase-earth-staging' => 'git://gitorious.org/qt/qtbase-earth-staging.git',
- 'qtbase-staging' => 'git://gitorious.org/qt/qtbase-staging.git',
- 'qtdeclarative-staging' => 'git://gitorious.org/qt/qtdeclarative-staging.git',
- 'qtdoc-staging' => 'git://gitorious.org/qt/qtdoc-staging.git',
- 'qtmultimedia-staging' => 'git://gitorious.org/qt/qtmultimedia-staging.git',
- 'qtphonon-staging' => 'git://gitorious.org/qt/qtphonon-staging.git',
- 'qtqa-staging' => 'git://gitorious.org/qt/qtqa-staging.git',
- 'qtscript-staging' => 'git://gitorious.org/qt/qtscript-staging.git',
- 'qtsvg-staging' => 'git://gitorious.org/qt/qtsvg-staging.git',
- 'qttools-staging' => 'git://gitorious.org/qt/qttools-staging.git',
- 'qttranslations-staging' => 'git://gitorious.org/qt/qttranslations-staging.git',
- 'qtwebkit-examples-and-demos-staging' => 'git://gitorious.org/qt/qtwebkit-examples-and-demos-staging.git',
- 'qtxmlpatterns-staging' => 'git://gitorious.org/qt/qtxmlpatterns-staging.git',
+my %STAGING_REPOS = map { $_ => "git://gitorious.org/qt/$_.git" } qw(
+ qt3support-staging
+ qtactiveqt-staging
+ qtbase-earth-staging
+ qtbase-staging
+ qtdeclarative-staging
+ qtdoc-staging
+ qtmultimedia-staging
+ qtphonon-staging
+ qtqa-staging
+ qtscript-staging
+ qtsvg-staging
+ qttools-staging
+ qttranslations-staging
+ qtwebkit-examples-and-demos-staging
+ qtxmlpatterns-staging
);
+my $BNE_MIRROR_URL_BASE
+ = 'git://bq-git.apac.nokia.com/qtsoftware/qt/';
+my $BNE_MIRROR_WEBKIT_URL
+ = 'git://bq-git.apac.nokia.com/qtsoftware/research/gitorious-org-webkit-qtwebkit-mirror.git';
-sub system_v
+sub new
{
- if (!$quiet) {
- print "+ ";
- print @_;
- print "\n";
- }
- return system(@_);
+ my ($class, @arguments) = @_;
+
+ my $self = {};
+ bless $self, $class;
+ $self->parse_arguments(@arguments);
+
+ return $self;
}
-sub printUsage
+# Like `system', but possibly log the command, and die on non-zero exit code
+sub exe
{
- print <<EOU;
-$0 <options>
- -f Force initialization.
- -q Quiet operation. Will exit cleanly if repository is already
- initialized.
-
-Module options
- -no-webkit Skip webkit and webkit examples submodules.
- -no-update Skip the 'git submodule update' command.
- -ignore-submodules
- Ignores submodules when doing operations on qt5 repo, such
- as 'pull', 'fetch', 'diff' etc. Use
- --ignore-submodules=none to override, when needed
-
-Repository options:
- -nokia-developer Switch to internal Nokia URLs.
- -brisbane Switch to internal Nokia URLs, and setup the brisbane
- mirrors. (Uses the -mirror and -mirror-webkit options.)
- -ssh Use SSH protocol, for restrictive firewalls. Note that this
- requires a user account with an uploaded SSH key on all
- servers used. (Implies -nokia-developer!)
- -http Use HTTP protocol, for restrictive firewalls. Note that this
- only works with the external Gitorious server.
- -alternates=<path to other Qt5 repo>
- Adds alternates for each submodule to another full qt5
- checkout. This makes this qt5 checkout very small, as it
- will use the object store of the alternates before unique
- objects are stored in its own object store.
- PS: This option does not work with -no-update!
- PSS:This will make this repo dependent on the alternate!
- The dependency can be broken by running 'git repack -a'
- in each submodule, where required.
- -copy-objects Copies all objects from the alternates into the individual
- repos, to ensure that the repositories are independent from
- the source used as a reference for cloning.
- -mirror=<url> Uses <url> as the base URL for cloning submodules.
- -mirror=user\@machine/foo/bar
- while for example clone qtbase from
- user\@machine/foo/bar/qtbase.git
- -mirror-webkit=<url>
- Uses <url> as the URL for cloning webkit.
-EOU
+ my ($self, @cmd) = @_;
+
+ if (!$self->{quiet}) {
+ print "+ @cmd\n";
+ }
+
+ if (system(@cmd) != 0) {
+ confess "@cmd exited with status $CHILD_ERROR";
+ }
+
+ return;
}
-while (@ARGV) {
- my $arg = $ARGV[0];
- if ($arg eq "-f") {
- $force = 1;
- } elsif ($arg eq "-q") {
- $quiet = 1;
- } elsif ($arg eq "-brisbane" || $arg eq "-brisbane-nokia-developer") {
- $nokia_developer = 1;
- $protocol = "internal";
- $mirror_url = "git://bq-git.apac.nokia.com/qtsoftware/qt/";
- $mirror_webkit_url = "git://bq-git.apac.nokia.com/qtsoftware/research/gitorious-org-webkit-qtwebkit-mirror.git";
- } elsif ($arg eq "-nokia-developer") {
- $nokia_developer = 1;
- $protocol = "internal";
- } elsif ($arg eq "-ssh" || $arg eq "-ssh-protocol") {
- $protocol = "ssh";
- } elsif ($arg eq "-http") {
- if ($nokia_developer) {
- print("*** Ignoring use of HTTP protocol, as it's only usable with external server\n");
- } else {
- $protocol = "http";
- }
- } elsif ($arg eq "/?" || $arg eq "-?" || $arg eq "/h" || $arg eq "-h" || $arg eq "--help") {
- printUsage();
- exit 0;
- } elsif ($arg eq "-no-webkit") {
- $no_webkit = 1;
- } elsif ($arg eq "-no-update") {
- $no_update = 1;
- } elsif ($arg eq "-ignore-submodules") {
- $ignore_submodules = 1;
- } elsif ($arg =~ /-alternates=(.*)/) {
- $alternates = "$1";
- } elsif ($arg eq "-copy-objects") {
- $detach_alternates = 1;
- } elsif ($arg =~ /-mirror=(.*)/) {
- $mirror_url = "$1/";
- $mirror_url =~ s,\/\/+$,/,;
- } elsif ($arg =~ /-mirror-webkit=(.*)/) {
- $mirror_webkit_url = "$1"
- } else {
- print("*** Unknown option: $arg\n");
- printUsage();
- exit(1);
+sub parse_arguments
+{
+ my ($self, @args) = @_;
+
+ %{$self} = (%{$self},
+ 'alternates' => "",
+ 'detach-alternates' => 0 ,
+ 'force' => 0 ,
+ 'ignore-submodules' => 0 ,
+ 'mirror-url' => "",
+ 'mirror-webkit-url' => "",
+ 'nokia-developer' => 0 ,
+ 'protocol' => "",
+ 'update' => 1 ,
+ 'webkit' => 1 ,
+ );
+
+ GetOptionsFromArray(\@args,
+ 'alternates=s' => \$self->{qw{ alternates }},
+ 'copy-objects' => \$self->{qw{ detach-alternates }},
+ 'force' => \$self->{qw{ force }},
+ 'ignore-submodules' => \$self->{qw{ ignore_submodules }},
+ 'mirror-webkit=s' => \$self->{qw{ mirror-webkit-url }},
+ 'mirror=s' => \$self->{qw{ mirror-url }},
+ 'nokia-developer' => \$self->{qw{ nokia-developer }},
+ 'quiet' => \$self->{qw{ quiet }},
+ 'update!' => \$self->{qw{ update }},
+ 'webkit!' => \$self->{qw{ webkit }},
+
+ 'help|?' => sub { pod2usage(1); },
+ 'http' => sub { $self->{protocol} = 'http'; },
+ 'ssh|ssh-protocol' => sub { $self->{protocol} = 'ssh'; },
+
+ 'brisbane|brisbane-nokia-developer' => sub {
+ $self->{'nokia-developer'} = 1;
+ $self->{'protocol'} = 'internal';
+ $self->{'mirror-url'} = $BNE_MIRROR_URL_BASE;
+ $self->{'mirror-webkit-url'} = $BNE_MIRROR_WEBKIT_URL;
+ },
+
+ 'nokia-developer' => sub {
+ $self->{'nokia-developer'} = 1;
+ $self->{'protocol'} = 'internal';
+ },
+ ) || pod2usage(2);
+
+ if ($self->{'nokia-developer'} && $self->{'protocol'} eq 'http') {
+ print "*** Ignoring use of HTTP protocol, as it's only usable with external server\n";
+ $self->{'protocol'} = '';
}
- shift;
+
+ # Replace any double trailing slashes from end of mirror
+ $self->{'mirror-url'} =~ s{//+$}{/};
+
+ return;
}
-if (`git config --get submodule.qtbase.url`) {
- if ($force) {
- my @configresult = `git config -l`;
- foreach (@configresult) {
- if (/(submodule\.[^.=]+)\.url=.*/) {
- system_v("git config --remove-section $1");
+sub check_if_already_initialized
+{
+ my ($self) = @_;
+
+ # We consider the repo as `initialized' if submodule.qtbase.url is set
+ if (qx(git config --get submodule.qtbase.url)) {
+ if ($self->{force}) {
+ my @configresult = qx(git config -l);
+ foreach (@configresult) {
+ # Example line: submodule.qtqa.url=git://gitorious.org/qt/qtqa.git
+ if (/(submodule\.[^.=]+)\.url=.*/) {
+ $self->exe('git', 'config', '--remove-section', $1);
+ }
}
}
- } else {
- exit 0 if ($quiet);
- print("Will not reinitialize already initialized repository (use -f to force)!\n");
- exit 1;
+ else {
+ exit 0 if ($self->{quiet});
+ print "Will not reinitialize already initialized repository (use -f to force)!\n";
+ exit 1;
+ }
+ }
+
+ return;
+}
+
+sub git_submodule_init
+{
+ my ($self) = @_;
+
+ my @init_args;
+ if ($self->{quiet}) {
+ push @init_args, '--quiet';
}
+ $self->exe('git', 'submodule', 'init', @init_args);
+
+ return;
}
-my $init_args = "";
-$init_args = "-q" if ($quiet);
-system_v("git submodule init $init_args");
-if ($no_webkit){
- system_v("git config --remove submodule.qtwebkit");
- system_v("git config --remove submodule.qtwebkit-examples-and-demos");
+sub git_disable_webkit_submodule
+{
+ my ($self) = @_;
+
+ $self->exe('git', 'config', '--remove', 'submodule.qtwebkit');
+ $self->exe('git', 'config', '--remove', 'submodule.qtwebkit-examples-and-demos');
+
+ return;
}
-my @configresult = `git config -l`;
-my $proto = $protocols{$protocol};
-foreach (@configresult) {
- if (/(submodule\.[^.=]+\.url)=(.*)/) {
- my $key = $1;
+sub git_set_submodule_config
+{
+ my ($self) = @_;
+
+ my @configresult = qx(git config -l);
+ my $protocol = $self->{protocol};
+ my $url_base_for_protocol = $PROTOCOLS{$protocol};
+
+ GITCONFIG:
+ foreach my $line (@configresult) {
+ # Example line: submodule.qtqa.url=git://gitorious.org/qt/qtqa.git
+ next GITCONFIG if ($line !~ /(submodule\.[^.=]+\.url)=(.*)/);
+
+ my $key = $1;
my $value = $2;
+
if ($protocol) {
# WebKit is special, and has only external link.
- if ($key ne "submodule.qtwebkit.url") {
+ if ($key ne 'submodule.qtwebkit.url') {
# qt-labs projects are still hosted under qt internally.
- $value =~ s,^git://gitorious\.org/qt-labs/,${proto}qt/, if ($protocol ne "http") ;
- $value =~ s,^git://gitorious\.org/,$proto,;
+ if ($protocol ne 'http') {
+ $value =~ s,^git://gitorious\.org/qt-labs/,${url_base_for_protocol}qt/,;
+ }
+ $value =~ s,^git://gitorious\.org/,$url_base_for_protocol,;
}
}
- system_v("git config \"$key\" \"$value\"");
- if ($ignore_submodules) {
+
+ $self->exe('git', 'config', $key, $value);
+
+ if ($self->{'ignore-submodules'}) {
$key =~ s,\.url,.ignore,;
- system_v("git config \"$key\" \"all\"");
+ $self->exe('git', 'config', $key, 'all');
}
}
+
+ return;
}
-# manually clone each repo here, so we can easily use reference repos, mirrors and add all staging
-# repos
-if (!$no_update) {
- @configresult = `git config -l`;
- foreach (@configresult) {
- if(/submodule\.([^.=]+)\.url=(.*)/){
- my $repo = $1;
- my $url = $2;
- my $ref = "";
- if ($alternates) {
- if (-d "$alternates/$repo") {
- $ref = "--reference $alternates/$repo";
- } else {
- print(" *** $alternates/$repo not found, ignoring alternate for this submodule\n");
- }
- }
+sub git_clone_all_submodules
+{
+ my ($self) = @_;
- my $mirror;
- if ($mirror_url && ($repo ne "qtwebkit")) {
- $mirror = $mirror_url.$repo;
- $mirror .= ".git" unless (-d $mirror); # Support local disk mirror
- } elsif ($mirror_webkit_url && ($repo eq "qtwebkit")) {
- $mirror = $mirror_webkit_url;
- }
+ # manually clone each repo here, so we can easily use reference repos, mirrors and
+ # add all staging repos
+ my @configresult = qx(git config -l);
+ foreach my $line (@configresult) {
+ if ($line =~ /submodule\.([^.=]+)\.url=(.*)/) {
+ $self->git_clone_one_submodule($1, $2);
+ }
+ }
- my $do_clone = (! -d "$repo/.git");
- system_v("git clone $ref " . ($mirror ? $mirror : $url) . " $repo") if ($do_clone);
- chdir($repo) or die "'cd $repo' failed...";
- system_v("git fetch " . ($mirror ? $mirror : $url)) if (!$do_clone);
+ $self->exe('git', 'submodule', 'update');
- if ($mirror) {
- system_v("git config remote.origin.url $url");
- system_v("git remote add mirror $mirror");
- }
+ return;
+}
- # add missing staging repos as remotes
- my @staging = grep(/^$repo/, keys %staging_repos);
- my @current_remotes = `git remote show`;
- chomp @current_remotes;
- my %diff = map { $_ => 1 } @current_remotes;
- my @add_staging = grep !$diff{"$_"}, @staging;
- foreach (@add_staging) {
- my $staging_repo = $_;
- my $staging_repo_url = $staging_repos{$_};
- if ($protocol) {
- $staging_repo_url =~ s,^git://gitorious\.org/qt-labs/,${proto}qt/, if ($protocol ne "http") ;
- $staging_repo_url =~ s,^git://gitorious\.org/,$proto,;
- }
- system_v("git remote add $staging_repo $staging_repo_url");
- }
+sub git_clone_one_submodule
+{
+ my ($self, $submodule, $url) = @_;
- if ($detach_alternates) {
- system_v("git repack -a");
- unlink(".git/objects/info/alternates");
+ my $alternates = $self->{ 'alternates' };
+ my $mirror_url = $self->{ 'mirror-url' };
+ my $mirror_webkit_url = $self->{ 'mirror-webkit-url' };
+ my $protocol = $self->{protocol};
+ my $url_base_for_protocol = $PROTOCOLS{$protocol};
+
+ # `--reference FOO' args for the clone, if any.
+ my @reference_args;
+
+ if ($alternates) {
+ # alternates is a qt5 repo, so the submodule will be under that.
+ if (-d "$alternates/$submodule") {
+ @reference_args = ('--reference', "$alternates/$submodule");
+ }
+ else {
+ print " *** $alternates/$submodule not found, ignoring alternate for this submodule\n";
+ }
+ }
+
+ my $mirror;
+ if ($mirror_url && ($submodule ne 'qtwebkit')) {
+ $mirror = $mirror_url.$submodule;
+ $mirror .= ".git" unless (-d $mirror); # Support local disk mirror
+ }
+ elsif ($mirror_webkit_url && ($submodule eq 'qtwebkit')) {
+ $mirror = $mirror_webkit_url;
+ }
+
+ my $do_clone = (! -d "$submodule/.git");
+ if ($do_clone) {
+ $self->exe('git', 'clone', @reference_args, ($mirror ? $mirror : $url), $submodule);
+ }
+
+ chdir($submodule) or confess "chdir $submodule: $OS_ERROR";
+
+ if (!$do_clone) {
+ $self->exe('git', 'fetch', ($mirror ? $mirror : $url));
+ }
+
+ if ($mirror) {
+ $self->exe('git', 'config', 'remote.origin.url', $url);
+ $self->exe('git', 'remote', 'add', 'mirror', $mirror);
+ }
+
+ my %current_remotes;
+ for my $line (qx(git remote show)) {
+ chomp $line;
+ $current_remotes{$line} = 1;
+ }
+
+ # We assume that any staging starting with `$submodule-' relates to this
+ # submodule. For example, for the `qtbase' module, `qtbase-staging'
+ # and `qtbase-earth-staging' are considered as related staging repos.
+ my @staging = grep { /^\Q$submodule\E-/; } keys %STAGING_REPOS;
+
+ STAGING:
+ foreach my $staging_repo (@staging) {
+ # nothing to do if remote already exists
+ next STAGING if ($current_remotes{$staging_repo});
+
+ my $staging_repo_url = $STAGING_REPOS{$staging_repo};
+ if ($protocol) {
+ if ($protocol ne 'http') {
+ $staging_repo_url =~ s,^git://gitorious\.org/qt-labs/,${url_base_for_protocol}qt/,;
}
- chdir("..") or die "'cd ..' failed..";
+ $staging_repo_url =~ s,^git://gitorious\.org/,$url_base_for_protocol,;
}
+ $self->exe('git', 'remote', 'add', $staging_repo, $staging_repo_url);
+ }
+
+ if ($self->{'detach-alternates'}) {
+ $self->exe('git', 'repack', '-a');
+
+ my $alternates_path = '.git/objects/info/alternates';
+ unlink($alternates_path) || confess "unlink $alternates_path: $OS_ERROR";
}
- system_v("git submodule update");
+
+ chdir("..") or confess "cd ..: $OS_ERROR";
+
+ return;
}
+
+sub run
+{
+ my ($self) = @_;
+
+ $self->check_if_already_initialized;
+ $self->git_submodule_init;
+
+ if (!$self->{webkit}) {
+ $self->git_disable_webkit_submodule;
+ }
+
+ $self->git_set_submodule_config;
+
+ if ($self->{update}) {
+ $self->git_clone_all_submodules;
+ }
+
+ return;
+}
+
+#==============================================================================
+
+Qt::InitRepository->new(@ARGV)->run if (!caller);
+1;