]> git.madduck.net Git - code/myrepos.git/blobdiff - mr

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

expand
[code/myrepos.git] / mr
diff --git a/mr b/mr
index 3f04b5b95041eb9b4e8d24458c64cdb2b45d1a3d..4235151895fa70daf0e917de9f9006b326aa3277 100755 (executable)
--- a/mr
+++ b/mr
@@ -22,6 +22,8 @@ B<mr> [options] diff
 
 B<mr> [options] log
 
+B<mr> [options] run command [param ...]
+
 B<mr> [options] bootstrap url [directory]
 
 B<mr> [options] register [repository]
@@ -102,6 +104,10 @@ Show a diff of uncommitted changes.
 
 Show the commit log.
 
+=item run command [param ...]
+
+Runs the specified command in each repository.
+
 =back
 
 These commands are also available:
@@ -216,7 +222,9 @@ Be verbose.
 
 =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
 
@@ -621,23 +629,36 @@ sub action {
                }
        }
        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";
@@ -693,7 +714,17 @@ sub hook {
        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";
@@ -1025,14 +1056,24 @@ sub is_trusted_checkout {
 }
 
 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;
 
@@ -1044,10 +1085,6 @@ sub loadconfig {
                $trusted=1;
        }
        else {
-               if (! -e $f) {
-                       return;
-               }
-
                my $absf=abs_path($f);
                if ($loaded{$absf}) {
                        return;
@@ -1082,6 +1119,10 @@ sub loadconfig {
                        }
                }
                
+               if (! -e $f) {
+                       return;
+               }
+
                print "mr: loading config $f\n" if $verbose;
                open($in, "<", $f) || die "mr: open $f: $!\n";
        }
@@ -1102,7 +1143,7 @@ sub loadconfig {
                                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;
@@ -1129,10 +1170,10 @@ sub loadconfig {
                                # 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);
                                }
                        }
 
@@ -1411,7 +1452,7 @@ sub register {
        $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: $!";
 }
@@ -1443,7 +1484,7 @@ sub bootstrap {
        # 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"};
 
@@ -1688,6 +1729,8 @@ darcs_log = darcs changes "$@"
 git_bare_log = git log "$@"
 fossil_log = fossil timeline "$@"
 
+run = "$@"
+
 svn_register =
        url=`LC_ALL=C svn info . | grep -i '^URL:' | cut -d ' ' -f 2`
        if [ -z "$url" ]; then