2 #############################################################################
4 ## Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
5 ## Contact: http://www.qt-project.org/legal
7 ## This file is part of the utilities of the Qt Toolkit.
9 ## $QT_BEGIN_LICENSE:LGPL$
10 ## Commercial License Usage
11 ## Licensees holding valid commercial Qt licenses may use this file in
12 ## accordance with the commercial license agreement provided with the
13 ## Software or, alternatively, in accordance with the terms contained in
14 ## a written agreement between you and Digia. For licensing terms and
15 ## conditions see http://qt.digia.com/licensing. For further information
16 ## use the contact form at http://qt.digia.com/contact-us.
18 ## GNU Lesser General Public License Usage
19 ## Alternatively, this file may be used under the terms of the GNU Lesser
20 ## General Public License version 2.1 as published by the Free Software
21 ## Foundation and appearing in the file LICENSE.LGPL included in the
22 ## packaging of this file. Please review the following information to
23 ## ensure the GNU Lesser General Public License version 2.1 requirements
24 ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26 ## In addition, as a special exception, Digia gives you certain additional
27 ## rights. These rights are described in the Digia Qt LGPL Exception
28 ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
30 ## GNU General Public License Usage
31 ## Alternatively, this file may be used under the terms of the GNU
32 ## General Public License version 3.0 as published by the Free Software
33 ## Foundation and appearing in the file LICENSE.GPL included in the
34 ## packaging of this file. Please review the following information to
35 ## ensure the GNU General Public License version 3.0 requirements will be
36 ## met: http://www.gnu.org/copyleft/gpl.html.
41 #############################################################################
47 package Qt::InitRepository;
52 init-repository - initialize the Qt5 repository and all submodules
56 ./init-repository [options]
58 This script may be run after an initial `git clone' of Qt5 in order to check
70 Force initialization (even if the submodules are already checked out).
75 Be quiet. Will exit cleanly if the repository is already initialized.
86 Skip webkit and webkit examples submodules.
87 It may be desirable to skip these modules due to the large size of the webkit
90 =item --module-subset=<module1>,<module2>...
92 Only initialize the specified subset of modules given as the argument. Specified
93 modules must already exist in .gitmodules.
94 The string "all" results in cloning all known modules. The default is the set of
99 Skip the `git submodule update' command.
102 =item --ignore-submodules
104 Set git config to ignore submodules by default when doing operations on the
105 qt5 repo, such as `pull', `fetch', `diff' etc.
107 After using this option, pass `--ignore-submodules=none' to git to override
113 B<Repository options:>
119 Switch to internal URLs and make use of the Berlin git mirrors.
120 (Implies `--mirror').
124 Switch to internal URLs and make use of the Oslo git mirrors.
125 (Implies `--mirror').
130 Use the HTTP protocol for git operations. This may be useful if the git
131 protocol is blocked by a firewall. Note that this only works with the
132 external Gitorious server.
134 The `--http' option does not affect the gerrit remotes.
137 =item --codereview-username <Gerrit/JIRA username>
139 Specify the user name for the (potentially) writable `gerrit' remote
140 for each module, for use with the Gerrit code review tool.
142 If this option is omitted, the gerrit remote is created without a username
143 and port number, and thus relies on a correct SSH configuration.
146 =item --alternates <path to other Qt5 repo>
148 Adds alternates for each submodule to another full qt5 checkout. This makes
149 this qt5 checkout very small, as it will use the object store of the
150 alternates before unique objects are stored in its own object store.
152 This option has no effect when using `--no-update'.
154 B<NOTE:> This will make this repo dependent on the alternate, which is
155 potentially dangerous! The dependency can be broken by also using
156 the `--copy-objects' option, or by running C<git repack -a> in each
157 submodule, where required. Please read the note about the `--shared' option
158 in the documentation of `git clone' for more information.
163 When `--alternates' is used, automatically do a C<git repack -a> in each
164 submodule after cloning, to ensure that the repositories are independent
165 from the source used as a reference for cloning.
167 Note that this negates the disk usage benefits gained from the use of
171 =item --mirror <url-base>
173 Uses <url-base> as the base URL for submodule git mirrors.
177 --mirror user@machine:/foo/bar
179 ...will use the following as a mirror for qtbase:
181 user@machine:/foo/bar/qt/qtbase.git
183 The mirror is permitted to contain a subset of the submodules; any
184 missing modules will fall back to the canonical URLs.
190 use Carp qw( confess );
191 use English qw( -no_match_vars );
192 use Getopt::Long qw( GetOptionsFromArray );
193 use Pod::Usage qw( pod2usage );
194 use Cwd qw( getcwd );
197 'http' => 'http://git.gitorious.org/' ,
200 my %GERRIT_REPOS = map { $_ => "qt/$_" } qw(
239 my @DEFAULT_REPOS = qw(
269 = 'ssh://@USER@codereview.qt-project.org@PORT@/';
271 my $BER_MIRROR_URL_BASE
274 my $OSLO_MIRROR_URL_BASE
279 my ($class, @arguments) = @_;
283 $self->parse_arguments(@arguments);
288 # Like `system', but possibly log the command, and die on non-zero exit code
291 my ($self, @cmd) = @_;
293 if (!$self->{quiet}) {
297 if (system(@cmd) != 0) {
298 confess "@cmd exited with status $CHILD_ERROR";
306 my ($self, @args) = @_;
308 %{$self} = (%{$self},
310 'codereview-username' => "",
311 'detach-alternates' => 0 ,
313 'ignore-submodules' => 0 ,
318 'module-subset' => join(",", @DEFAULT_REPOS),
321 GetOptionsFromArray(\@args,
322 'alternates=s' => \$self->{qw{ alternates }},
323 'codereview-username=s' => \$self->{qw{ codereview-username }},
324 'copy-objects' => \$self->{qw{ detach-alternates }},
325 'force' => \$self->{qw{ force }},
326 'ignore-submodules' => \$self->{qw{ ignore-submodules }},
327 'mirror=s' => \$self->{qw{ mirror-url }},
328 'quiet' => \$self->{qw{ quiet }},
329 'update!' => \$self->{qw{ update }},
330 'webkit!' => \$self->{qw{ webkit }},
331 'module-subset=s' => \$self->{qw{ module-subset }},
333 'help|?' => sub { pod2usage(1); },
334 'http' => sub { $self->{protocol} = 'http'; },
337 $self->{'mirror-url'} = $BER_MIRROR_URL_BASE;
340 $self->{'mirror-url'} = $OSLO_MIRROR_URL_BASE;
344 # Replace any double trailing slashes from end of mirror
345 $self->{'mirror-url'} =~ s{//+$}{/};
347 if ($self->{'module-subset'} eq "all") {
348 $self->{'module-subset'} = "";
350 $self->{'module-subset'} = {
351 map { $_ => 1 } split(qr{,}, $self->{'module-subset'})
358 sub check_if_already_initialized
362 # We consider the repo as `initialized' if submodule.qtbase.url is set
363 if (qx(git config --get submodule.qtbase.url)) {
364 if ($self->{force}) {
365 my @configresult = qx(git config -l);
366 foreach (@configresult) {
367 # Example line: submodule.qtqa.url=git://gitorious.org/qt/qtqa.git
368 if (/(submodule\.[^.=]+)\.url=.*/) {
369 $self->exe('git', 'config', '--remove-section', $1);
374 exit 0 if ($self->{quiet});
375 print "Will not reinitialize already initialized repository (use -f to force)!\n";
383 sub git_submodule_init
388 if ($self->{quiet}) {
389 push @init_args, '--quiet';
391 $self->exe('git', 'submodule', 'init', @init_args);
393 my $template = getcwd()."/.commit-template";
395 $self->exe('git', 'config', 'commit.template', $template);
401 sub git_disable_webkit_submodule
405 $self->exe('git', 'config', '--remove', 'submodule.qtwebkit');
406 $self->exe('git', 'config', '--remove', 'submodule.qtwebkit-examples');
411 sub git_prune_submodules
415 my @configresult = qx(git config -l);
416 foreach my $line (@configresult) {
417 if ($line =~ /submodule\.([^.=]+)\.url=/) {
418 my $module_name = $1;
419 if (!$self->{'module-subset'}{$module_name}) {
420 $self->exe('git', 'config', '--remove', "submodule.$module_name");
426 sub git_set_submodule_config
430 my @configresult = qx(git config -l);
431 my $protocol = $self->{protocol};
432 my $url_base_for_protocol = $PROTOCOLS{$protocol};
434 foreach my $line (@configresult) {
435 # Example line: submodule.qtqa.url=git://gitorious.org/qt/qtqa.git
436 next if ($line !~ /submodule\.([^.=]+)\.url=(.*)/);
442 # rewrite URL to chosen protocol
443 $value =~ s,^git://gitorious\.org/,$url_base_for_protocol,;
446 $self->exe('git', 'config', "submodule.$key.url", $value);
448 if ($self->{'ignore-submodules'}) {
449 $self->exe('git', 'config', "submodule.$key.ignore", 'all');
456 sub git_clone_all_submodules
460 # manually clone each repo here, so we can easily use reference repos, mirrors etc
461 my @configresult = qx(git config -l);
462 foreach my $line (@configresult) {
463 if ($line =~ /submodule\.([^.=]+)\.url=(.*)/) {
464 $self->git_clone_one_submodule($1, $2);
468 if ($self->{update}) {
469 $self->exe('git', 'submodule', 'update', '--recursive');
477 my ($self, $repo_basename) = @_;
479 my $gerrit_repo_basename = $GERRIT_REPOS{$repo_basename};
480 if ($gerrit_repo_basename) {
483 # If given a username, make a "verbose" remote.
484 # Otherwise, rely on proper SSH configuration.
485 if ($self->{'codereview-username'}) {
486 $gerrit_repo_url = $GERRIT_SSH_BASE;
487 $gerrit_repo_url =~ s,\@USER\@,$self->{'codereview-username'}\@,;
488 $gerrit_repo_url =~ s,\@PORT\@,:29418,;
491 $gerrit_repo_url = $GERRIT_SSH_BASE;
492 $gerrit_repo_url =~ s,\@[^\@]+\@,,g;
495 $gerrit_repo_url .= $gerrit_repo_basename;
496 $self->exe('git', 'config', 'remote.gerrit.url', $gerrit_repo_url);
497 $self->exe('git', 'config', 'remote.gerrit.fetch', '+refs/heads/*:refs/remotes/gerrit/*', '/heads/');
503 sub git_clone_one_submodule
505 my ($self, $submodule, $url) = @_;
507 my $alternates = $self->{ 'alternates' };
508 my $mirror_url = $self->{ 'mirror-url' };
509 my $protocol = $self->{ 'protocol' };
511 # `--reference FOO' args for the clone, if any.
515 # alternates is a qt5 repo, so the submodule will be under that.
516 if (-d "$alternates/$submodule") {
517 @reference_args = ('--reference', "$alternates/$submodule");
520 print " *** $alternates/$submodule not found, ignoring alternate for this submodule\n";
526 $mirror = $mirror_url."qt/$submodule";
527 $mirror .= ".git" unless (-d $mirror); # Support local disk mirror
531 # Only use the mirror if it can be reached.
532 eval { $self->exe('git', 'ls-remote', $mirror, 'test/if/mirror/exists') };
534 warn "mirror [$mirror] is not accessible; $url will be used\n";
539 my $do_clone = (! -d "$submodule/.git");
541 $self->exe('git', 'clone', @reference_args, ($mirror ? $mirror : $url), $submodule);
544 chdir($submodule) or confess "chdir $submodule: $OS_ERROR";
546 $self->exe('git', 'config', 'remote.origin.url', $url);
548 $self->exe('git', 'config', 'remote.mirror.url', $mirror);
549 $self->exe('git', 'config', 'remote.mirror.fetch', '+refs/heads/*:refs/remotes/mirror/*');
553 $self->exe('git', 'fetch', ($mirror ? $mirror : $url));
556 my $template = getcwd()."/../.commit-template";
558 $self->exe('git', 'config', 'commit.template', $template);
561 $self->git_add_remotes($submodule);
563 if ($self->{'detach-alternates'}) {
564 $self->exe('git', 'repack', '-a');
566 my $alternates_path = '.git/objects/info/alternates';
567 if (-e $alternates_path) {
568 unlink($alternates_path) || confess "unlink $alternates_path: $OS_ERROR";
572 chdir("..") or confess "cd ..: $OS_ERROR";
581 $self->check_if_already_initialized;
582 $self->git_submodule_init;
584 if (!$self->{webkit}) {
585 $self->git_disable_webkit_submodule;
588 if ($self->{'module-subset'}) {
589 $self->git_prune_submodules;
592 $self->git_set_submodule_config;
594 $self->git_clone_all_submodules;
596 $self->git_add_remotes('qt5');
601 #==============================================================================
603 Qt::InitRepository->new(@ARGV)->run if (!caller);