+sub bootstrap {
+ eval q{use File::Copy};
+ die $@ if $@;
+
+ my $src=shift @ARGV;
+ my $dir=shift @ARGV || ".";
+
+ if (! defined $src || ! length $src) {
+ die "mr: bootstrap requires source\n";
+ }
+
+ # Retrieve config file.
+ eval q{use File::Temp};
+ die $@ if $@;
+ my $tmpconfig=File::Temp->new();
+ if ($src =~ m!^[\w\d]+://!) {
+ # Download the config file to a temporary location.
+ my @downloader;
+ if ($src =~ m!^ssh://(.*)!) {
+ @downloader = ("scp", $1, $tmpconfig);
+ }
+ else {
+ @downloader = ("curl", "-A", "mr", "-L", "-s", $src, "-o", $tmpconfig);
+ push(@downloader, "-k") if $insecure;
+ }
+ my $status = system(@downloader);
+ die "mr bootstrap: invalid SSL certificate for $src (consider -k)\n"
+ if $downloader[0] eq 'curl' && $status >> 8 == 60;
+ die "mr bootstrap: download of $src failed\n" if $status != 0;
+ }
+ elsif ($src eq '-') {
+ # Config file is read from stdin.
+ copy(\*STDIN, $tmpconfig) || die "stdin: $!";
+ }
+ else {
+ # Config file is local.
+ die "mr bootstrap: cannot read file '$src'"
+ unless -r $src;
+ copy($src, $tmpconfig) || die "copy: $!";
+ }
+
+ # Sanity check on destination directory.
+ if (! -e $dir) {
+ system("mkdir", "-p", $dir);
+ }
+ chdir($dir) || die "chdir $dir: $!";
+
+ # Special case to handle checkout of the "." repo, which
+ # would normally be skipped.
+ my $topdir=abs_path(".")."/";
+ my @repo=($topdir, $topdir, ".");
+ loadconfig($tmpconfig, $topdir, $src);
+ record(\@repo, action("checkout", @repo, 1))
+ if exists $config{$topdir}{"."}{"checkout"};
+
+ if (-e ".mrconfig") {
+ print STDERR "mr bootstrap: .mrconfig file already exists, not overwriting with $src\n";
+ }
+ else {
+ move($tmpconfig, ".mrconfig") || die "rename: $!";
+ }
+
+ # Reload the config file (in case we got a different version)
+ # and checkout everything else.
+ startingconfig();
+ loadconfig(".mrconfig");
+ dispatch("checkout");
+ @skipped=grep { abs_path($_) ne abs_path($topdir) } @skipped;
+ showstats("bootstrap");
+ exitstats();
+}
+