=item --quiet
-Be quiet.
+Be quiet. This supresses mr's usual output, as well as any output from
+commands that are run (including stderr output). If a command fails,
+the output will be shown.
=item -k
Unlike all other parameters, this parameter does not need to be placed
within a section.
+=item deleted
+
+If the "deleted" parameter is set and its command returns true, then
+B<mr> will treat the repository as deleted. It won't ever actually delete
+the repository, but it will warn if it sees the repository's directory.
+This is useful when one mrconfig file is shared amoung multiple machines,
+to keep track of and remember to delete old repositories.
+
=item lib
The "lib" parameter can specify some shell code that will be run before each
my $is_update=($action =~ /update/);
$ENV{MR_REPO}=$dir;
+
+ foreach my $testname ("skip", "deleted") {
+ my $testcommand=findcommand($testname, $dir, $topdir, $subdir, $is_checkout);
+
+ if (defined $testcommand) {
+ my $test="set -e;".$lib.
+ "my_action(){ $testcommand\n }; my_action '$action'";
+ print "mr $action: running $testname test >>$test<<\n" if $verbose;
+ my $ret=system($test);
+ if ($ret != 0) {
+ if (($? & 127) == 2) {
+ print STDERR "mr $action: interrupted\n";
+ return ABORT;
+ }
+ elsif ($? & 127) {
+ print STDERR "mr $action: $testname test received signal ".($? & 127)."\n";
+ return ABORT;
+ }
+ }
+ if ($ret >> 8 == 0) {
+ if ($testname eq "deleted") {
+ if (-d $dir) {
+ print STDERR "mr error: $dir should be deleted yet still exists\n";
+ return FAILED;
+ }
+ }
+ print "mr $action: skip $dir skipped\n" if $verbose;
+ return SKIPPED;
+ }
+ }
+ }
if ($is_checkout) {
if (! $force_checkout) {
}
}
- my $skiptest=findcommand("skip", $dir, $topdir, $subdir, $is_checkout);
my $command=findcommand($action, $dir, $topdir, $subdir, $is_checkout);
- if (defined $skiptest) {
- my $test="set -e;".$lib.
- "my_action(){ $skiptest\n }; my_action '$action'";
- print "mr $action: running skip test >>$test<<\n" if $verbose;
- my $ret=system($test);
- if ($ret != 0) {
- if (($? & 127) == 2) {
- print STDERR "mr $action: interrupted\n";
- return ABORT;
- }
- elsif ($? & 127) {
- print STDERR "mr $action: skip test received signal ".($? & 127)."\n";
- return ABORT;
- }
- }
- if ($ret >> 8 == 0) {
- print "mr $action: $dir skipped per config file\n" if $verbose;
- return SKIPPED;
- }
- }
-
if ($is_checkout && ! -d $dir) {
print "mr $action: creating parent directory $dir\n" if $verbose;
system("mkdir", "-p", $dir);
}
}
else {
+ my $actionmsg;
if (! $no_chdir) {
- print "mr $action: $fulldir\n" unless $quiet;
+ $actionmsg="mr $action: $fulldir";
}
else {
my $s=$directory;
$s=~s/^\Q$fulldir\E\/?//;
- print "mr $action: $fulldir (in subdir $s)\n" unless $quiet;
+ $actionmsg="mr $action: $fulldir (in subdir $s)";
}
+ print "$actionmsg\n" unless $quiet;
my $hookret=hook("pre_$action", $topdir, $subdir);
return $hookret if $hookret != OK;
$command="set -e; ".$lib.
"my_action(){ $command\n }; my_action ".
- join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
+ join(" ", map { s/\\/\\\\/g; s/"/\"/g; '"'.$_.'"' } @ARGV);
print "mr $action: running >>$command<<\n" if $verbose;
- my $ret=system($command);
+ my $ret;
+ if ($quiet) {
+ my $output = qx/$command 2>&1/;
+ $ret = $?;
+ if ($ret != 0) {
+ print "$actionmsg\n";
+ print STDERR $output;
+ }
+ }
+ else {
+ $ret=system($command);
+ }
if ($ret != 0) {
if (($? & 127) == 2) {
print STDERR "mr $action: interrupted\n";
my $shell="set -e;".$lib.
"my_hook(){ $command\n }; my_hook";
print "mr $hook: running >>$shell<<\n" if $verbose;
- my $ret=system($shell);
+ my $ret;
+ if ($quiet) {
+ my $output = qx/$shell 2>&1/;
+ $ret = $?;
+ if ($ret != 0) {
+ print STDERR $output;
+ }
+ }
+ else {
+ $ret=system($shell);
+ }
if ($ret != 0) {
if (($? & 127) == 2) {
print STDERR "mr $hook: interrupted\n";
}
sub trusterror {
- die shift()."\n".
- "(To trust this file, list it in ~/.mrtrust.)\n";
+ my ($err, $file, $line, $url)=@_;
+
+ if (defined $url) {
+ die "$err in untrusted $url line $line\n".
+ "(To trust this url, --trust-all can be used; but please use caution;\n".
+ "this can allow arbitrary code execution!)\n";
+ }
+ else {
+ die "$err in untrusted $file line $line\n".
+ "(To trust this file, list it in ~/.mrtrust.)\n";
+ }
}
my %loaded;
sub loadconfig {
my $f=shift;
my $dir=shift;
+ my $bootstrap_url=shift;
my @toload;
$trusted=1;
}
else {
- if (! -e $f) {
- return;
- }
-
my $absf=abs_path($f);
if ($loaded{$absf}) {
return;
}
}
+ if (! -e $f) {
+ return;
+ }
+
print "mr: loading config $f\n" if $verbose;
open($in, "<", $f) || die "mr: open $f: $!\n";
}
if (! is_trusted_repo($section) ||
$section eq 'ALIAS' ||
$section eq 'DEFAULT') {
- trusterror "mr: illegal section \"[$section]\" in untrusted $f line $line";
+ trusterror("mr: illegal section \"[$section]\"", $f, $line, $bootstrap_url)
}
}
$section=expandenv($section) if $trusted;
# Untrusted files can only contain checkout
# parameters.
if ($parameter ne 'checkout') {
- trusterror "mr: illegal setting \"$parameter=$value\" in untrusted $f line $line";
+ trusterror("mr: illegal setting \"$parameter=$value\"", $f, $line, $bootstrap_url);
}
if (! is_trusted_checkout($value)) {
- trusterror "mr: illegal checkout command \"$value\" in untrusted $f line $line";
+ trusterror("mr: illegal checkout command \"$value\"", $f, $line, $bootstrap_url);
}
}
$ENV{MR_REPO}=~s/.*\/(.*)/$1/;
$command="set -e; ".$config{$directory}{DEFAULT}{lib}."\n".
"my_action(){ $command\n }; my_action ".
- join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
+ join(" ", map { s/\\/\\\\/g; s/"/\"/g; '"'.$_.'"' } @ARGV);
print "mr register: running >>$command<<\n" if $verbose;
exec($command) || die "exec: $!";
}
# would normally be skipped.
my $topdir=abs_path(".")."/";
my @repo=($topdir, $topdir, ".");
- loadconfig($tmpconfig, $topdir);
+ loadconfig($tmpconfig, $topdir, $url);
record(\@repo, action("checkout", @repo, 1))
if exists $config{$topdir}{"."}{"checkout"};