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

Fix display when absolute directories are configured in mrconfig.
[code/myrepos.git] / mr
diff --git a/mr b/mr
index 839401f3fdbce3c68c26695e68ebfdc5a1cb0076..2bb3efa38c77a4ddc6bf0169d2c1077e5c21c1a9 100755 (executable)
--- a/mr
+++ b/mr
@@ -370,6 +370,20 @@ The "lib" parameter can specify some shell code that will be run before each
 command, this can be a useful way to define shell functions for other commands
 to use.
 
+=item fixups
+
+If the "fixups" parameter is set, its command is run whenever a repository
+is checked out, or updated. This provides an easy way to do things
+like permissions fixups, or other tweaks to the repository content,
+whenever the repository is changed.
+
+=item pre_ and post_
+
+If a "pre_action" parameter is set, its command is run before mr performs the
+specified action. Similarly, "post_action" parameters are run after mr
+successfully performs the specified action. For example, "pre_commit" is
+run before committing; "post_update" is run after updating.
+
 =back
 
 When looking for a command to run for a given action, mr first looks for
@@ -484,7 +498,7 @@ sub rcs_test {
        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) {
@@ -517,13 +531,20 @@ sub findcommand {
        }
 }
 
+sub fulldir {
+       my ($topdir, $subdir) = @_;
+       return $subdir =~ /^\// ? $subdir : $topdir.$subdir;
+}
+
 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" : "";
        my $is_checkout=($action eq 'checkout');
+       my $is_update=($action =~ /update/);
 
        $ENV{MR_REPO}=$dir;
 
@@ -537,7 +558,7 @@ sub action {
                        $dir=~s/^(.*)\/[^\/]+\/?$/$1/;
                }
        }
-       elsif ($action =~ /update/) {
+       elsif ($is_update) {
                if (! -d $dir) {
                        return action("checkout", $dir, $topdir, $subdir);
                }
@@ -579,23 +600,27 @@ sub action {
        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 {
-                       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) {
-                       print "mr $action: $topdir$subdir\n" unless $quiet;
+                       print "mr $action: $fulldir\n" unless $quiet;
                }
                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);
+               return $hookret if $hookret != OK;
+
                $command="set -e; ".$lib.
                        "my_action(){ $command\n }; my_action ".
                        join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
@@ -628,16 +653,49 @@ sub action {
                        return FAILED;
                }
                else {
-                       if ($action eq 'checkout' && ! -d $dir) {
+                       if ($is_checkout && ! -d $dir) {
                                print STDERR "mr $action: $dir missing after checkout\n";;
                                return FAILED;
                        }
 
+                       my $ret=hook("post_$action", $topdir, $subdir);
+                       return $ret if $ret != OK;
+                       
+                       if (($is_checkout || $is_update)) {
+                               my $ret=hook("fixups", $topdir, $subdir);
+                               return $ret if $ret != OK;
+                       }
+                       
                        return OK;
                }
        }
 }
 
+sub hook {
+       my ($hook, $topdir, $subdir) = @_;
+
+       my $command=$config{$topdir}{$subdir}{$hook};
+       return OK unless defined $command;
+       my $lib=exists $config{$topdir}{$subdir}{lib} ?
+                      $config{$topdir}{$subdir}{lib}."\n" : "";
+       my $shell="set -e;".$lib.
+               "my_hook(){ $command\n }; my_hook";
+       print "mr $hook: running >>$shell<<\n" if $verbose;
+       my $ret=system($shell);
+       if ($ret != 0) {
+               if (($? & 127) == 2) {
+                       print STDERR "mr $hook: interrupted\n";
+                       return ABORT;
+               }
+               elsif ($? & 127) {
+                       print STDERR "mr $hook: received signal ".($? & 127)."\n";
+                       return ABORT;
+               }
+       }
+
+       return OK;
+}
+
 # run actions on multiple repos, in parallel
 sub mrs {
        my $action=shift;
@@ -1559,12 +1617,12 @@ git_test = test -d "$MR_REPO"/.git
 bzr_test = test -d "$MR_REPO"/.bzr
 cvs_test = test -d "$MR_REPO"/CVS
 hg_test  = test -d "$MR_REPO"/.hg
+darcs_test = test -d "$MR_REPO"/_darcs
 fossil_test = test -f "$MR_REPO"/_FOSSIL_
 git_bare_test =
        test -d "$MR_REPO"/refs/heads && test -d "$MR_REPO"/refs/tags &&
        test -d "$MR_REPO"/objects && test -f "$MR_REPO"/config &&
        test "`GIT_CONFIG="$MR_REPO"/config git config --get core.bare`" = true
-darcs_test = test -d "$MR_REPO"/_darcs
 
 svn_update = svn update "$@"
 git_update = git pull "$@"
@@ -1667,7 +1725,7 @@ git_bare_register =
        mr -c "$MR_CONFIG" config "`pwd`" checkout="git clone --bare '$url' '$MR_REPO'"
 fossil_register =
        url=`fossil remote-url`
-       repo=`fossil info | grep repository | sed -e s/repository:*.//g -e s/\ //g`
+       repo=`fossil info | grep repository | sed -e 's/repository:*.//g' -e 's/ //g'`
        echo "Registering fossil repository $url in $MR_CONFIG"
        mr -c "$MR_CONFIG" config "`pwd`" checkout="mkdir -p '$MR_REPO' && cd '$MR_REPO' && fossil open '$repo'"