]> 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:

Trust flag day.
[code/myrepos.git] / mr
diff --git a/mr b/mr
index e73f3c841bed60b6af94eed6f642f4e67ee54a62..41a5362e95cec0f5f66f601fba2792c5e264f725 100755 (executable)
--- a/mr
+++ b/mr
@@ -16,6 +16,8 @@ B<mr> [options] commit [-m "message"]
 
 B<mr> [options] record [-m "message"]
 
 
 B<mr> [options] record [-m "message"]
 
+B<mr> [options] push
+
 B<mr> [options] diff
 
 B<mr> [options] log
 B<mr> [options] diff
 
 B<mr> [options] log
@@ -398,26 +400,28 @@ the action that is performed for a given revision control system, you can
 override these rcs specific actions. To add a new revision control system,
 you can just add rcs specific actions for it.
 
 override these rcs specific actions. To add a new revision control system,
 you can just add rcs specific actions for it.
 
-The ~/.mrlog file contains commands that mr has remembered to run later,
-due to being offline. You can delete or edit this file to remove commands,
-or even to add other commands for 'mr online' to run. If the file is
-present, mr assumes it is in offline mode.
-
 =head1 UNTRUSTED MRCONFIG FILES
 
 Since mrconfig files can contain arbitrary shell commands, they can do
 anything. This flexibility is good, but it also allows a malicious mrconfig
 file to delete your whole home directory. Such a file might be contained
 =head1 UNTRUSTED MRCONFIG FILES
 
 Since mrconfig files can contain arbitrary shell commands, they can do
 anything. This flexibility is good, but it also allows a malicious mrconfig
 file to delete your whole home directory. Such a file might be contained
-inside a repository that your main ~/.mrconfig checks out and chains to. To
-avoid worries about evil commands in a mrconfig file, mr
-has the ability to read mrconfig files in untrusted mode. Such files are
-limited to running only known safe commands (like "git clone") in a
-carefully checked manner.
+inside a repository that your main ~/.mrconfig checks out. To
+avoid worries about evil commands in a mrconfig file, mr defaults to
+reading all mrconfig files other than the main ~/.mrconfig in untrusted
+mode. In untrusted mode, mrconfig files are limited to running only known
+safe commands (like "git clone") in a carefully checked manner.
+
+To configure mr to trust other mrconfig files, list them in ~/.mrtrust.
+One mrconfig file should be listed per line. Either the full pathname
+should be listed, or the pathname can start with "~/" to specify a file
+relative to your home directory.
 
 
-By default, mr trusts all mrconfig files. (This default will change in a
-future release!) But if you have a ~/.mrtrust file, mr will only trust
-mrconfig files that are listed within it. (One file per line.) All other
-files will be treated as untrusted.
+=head1 OFFLINE LOG FILE
+
+The ~/.mrlog file contains commands that mr has remembered to run later,
+due to being offline. You can delete or edit this file to remove commands,
+or even to add other commands for 'mr online' to run. If the file is
+present, mr assumes it is in offline mode.
 
 =head1 EXTENSIONS
 
 
 =head1 EXTENSIONS
 
@@ -425,9 +429,13 @@ mr can be extended to support things such as unison and git-svn. Some
 files providing such extensions are available in /usr/share/mr/. See
 the documentation in the files for details about using them.
 
 files providing such extensions are available in /usr/share/mr/. See
 the documentation in the files for details about using them.
 
+=head1 EXIT STATUS
+
+mr returns nonzero if a command failed in any of the repositories.
+
 =head1 AUTHOR
 
 =head1 AUTHOR
 
-Copyright 2007-2010 Joey Hess <joey@kitenet.net>
+Copyright 2007-2011 Joey Hess <joey@kitenet.net>
 
 Licensed under the GNU GPL version 2 or higher.
 
 
 Licensed under the GNU GPL version 2 or higher.
 
@@ -498,7 +506,7 @@ sub rcs_test {
        chomp $rcs;
        if ($rcs=~/\n/s) {
                $rcs=~s/\n/, /g;
        chomp $rcs;
        if ($rcs=~/\n/s) {
                $rcs=~s/\n/, /g;
-               print STDERR "mr $action: found multiple possible repository types ($rcs) for $topdir$subdir\n";
+               print STDERR "mr $action: found multiple possible repository types ($rcs) for ".fulldir($topdir, $subdir)."\n";
                return undef;
        }
        if (! length $rcs) {
                return undef;
        }
        if (! length $rcs) {
@@ -531,9 +539,15 @@ sub findcommand {
        }
 }
 
        }
 }
 
+sub fulldir {
+       my ($topdir, $subdir) = @_;
+       return $subdir =~ /^\// ? $subdir : $topdir.$subdir;
+}
+
 sub action {
        my ($action, $dir, $topdir, $subdir, $force_checkout) = @_;
 sub action {
        my ($action, $dir, $topdir, $subdir, $force_checkout) = @_;
-       
+       my $fulldir=fulldir($topdir, $subdir);
+
        $ENV{MR_CONFIG}=$configfiles{$topdir};
        my $lib=exists $config{$topdir}{$subdir}{lib} ?
                       $config{$topdir}{$subdir}{lib}."\n" : "";
        $ENV{MR_CONFIG}=$configfiles{$topdir};
        my $lib=exists $config{$topdir}{$subdir}{lib} ?
                       $config{$topdir}{$subdir}{lib}."\n" : "";
@@ -594,22 +608,22 @@ sub action {
        elsif (! defined $command) {
                my $rcs=rcs_test(@_);
                if (! defined $rcs) {
        elsif (! defined $command) {
                my $rcs=rcs_test(@_);
                if (! defined $rcs) {
-                       print STDERR "mr $action: unknown repository type and no defined $action command for $topdir$subdir\n";
+                       print STDERR "mr $action: unknown repository type and no defined $action command for $fulldir\n";
                        return FAILED;
                }
                else {
                        return FAILED;
                }
                else {
-                       print STDERR "mr $action: no defined action for $rcs repository $topdir$subdir, skipping\n";
+                       print STDERR "mr $action: no defined action for $rcs repository $fulldir, skipping\n";
                        return SKIPPED;
                }
        }
        else {
                if (! $no_chdir) {
                        return SKIPPED;
                }
        }
        else {
                if (! $no_chdir) {
-                       print "mr $action: $topdir$subdir\n" unless $quiet;
+                       print "mr $action: $fulldir\n" unless $quiet;
                }
                else {
                        my $s=$directory;
                }
                else {
                        my $s=$directory;
-                       $s=~s/^\Q$topdir$subdir\E\/?//;
-                       print "mr $action: $topdir$subdir (in subdir $s)\n" unless $quiet;
+                       $s=~s/^\Q$fulldir\E\/?//;
+                       print "mr $action: $fulldir (in subdir $s)\n" unless $quiet;
                }
 
                my $hookret=hook("pre_$action", $topdir, $subdir);
                }
 
                my $hookret=hook("pre_$action", $topdir, $subdir);
@@ -913,22 +927,16 @@ sub is_trusted_config {
 
        my $trustfile=$ENV{HOME}."/.mrtrust";
 
 
        my $trustfile=$ENV{HOME}."/.mrtrust";
 
-       if (! -e $trustfile) {
-               print "mr: Assuming $config is trusted.\n";
-               print "mr: For better security, you are encouraged to create ~/.mrtrust\n";
-               print "mr: and list all trusted mrconfig files in it.\n";
-               return 1;
-       }
-
        if (! %trusted) {
                $trusted{"$ENV{HOME}/.mrconfig"}=1;
        if (! %trusted) {
                $trusted{"$ENV{HOME}/.mrconfig"}=1;
-               open (TRUST, "<", $trustfile) || die "$trustfile: $!";
-               while (<TRUST>) {
-                       chomp;
-                       s/^~\//$ENV{HOME}\//;
-                       $trusted{abs_path($_)}=1;
+               if (open (TRUST, "<", $trustfile)) {
+                       while (<TRUST>) {
+                               chomp;
+                               s/^~\//$ENV{HOME}\//;
+                               $trusted{abs_path($_)}=1;
+                       }
+                       close TRUST;
                }
                }
-               close TRUST;
        }
 
        return $trusted{$config};
        }
 
        return $trusted{$config};
@@ -1012,6 +1020,11 @@ sub is_trusted_checkout {
        return 0;
 }
 
        return 0;
 }
 
+sub trusterror {
+       die shift()."\n".
+               "(To trust this file, list it in ~/.mrtrust.)\n";
+}
+
 my %loaded;
 sub loadconfig {
        my $f=shift;
 my %loaded;
 sub loadconfig {
        my $f=shift;
@@ -1085,7 +1098,7 @@ sub loadconfig {
                                if (! is_trusted_repo($section) ||
                                    $section eq 'ALIAS' ||
                                    $section eq 'DEFAULT') {
                                if (! is_trusted_repo($section) ||
                                    $section eq 'ALIAS' ||
                                    $section eq 'DEFAULT') {
-                                       die "mr: illegal section \"[$section]\" in untrusted $f line $line\n";
+                                       trusterror "mr: illegal section \"[$section]\" in untrusted $f line $line";
                                }
                        }
                        $section=expandenv($section) if $trusted;
                                }
                        }
                        $section=expandenv($section) if $trusted;
@@ -1112,10 +1125,10 @@ sub loadconfig {
                                # Untrusted files can only contain checkout
                                # parameters.
                                if ($parameter ne 'checkout') {
                                # Untrusted files can only contain checkout
                                # parameters.
                                if ($parameter ne 'checkout') {
-                                       die "mr: illegal setting \"$parameter=$value\" in untrusted $f line $line\n";
+                                       trusterror "mr: illegal setting \"$parameter=$value\" in untrusted $f line $line";
                                }
                                if (! is_trusted_checkout($value)) {
                                }
                                if (! is_trusted_checkout($value)) {
-                                       die "mr: illegal checkout command \"$value\" in untrusted $f line $line\n";
+                                       trusterror "mr: illegal checkout command \"$value\" in untrusted $f line $line";
                                }
                        }
 
                                }
                        }
 
@@ -1540,9 +1553,6 @@ sub exitstats {
        if (@failed) {
                exit 1;
        }
        if (@failed) {
                exit 1;
        }
-       elsif (! @ok && @skipped) {
-               exit 1;
-       }
        else {
                exit 0;
        }
        else {
                exit 0;
        }