#!/usr/bin/perl
 
-#man{{{
-
 =head1 NAME
 
 mr - a Multiple Repository management tool
 It is not recommended for interactive operations.
 
 Note that running more than 10 jobs at a time is likely to run afoul of
-ssh connection limits. Running between 3 and 5 jobs at a time will yeild
+ssh connection limits. Running between 3 and 5 jobs at a time will yield
 a good speedup in updates without loading the machine too much.
 
 =back
 override these rcs specific actions. To add a new revision control system,
 you can just add rcs specific actions for it.
 
+=head1 EXTENSIONS
+
+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.
+
 =head1 AUTHOR
 
 Copyright 2007 Joey Hess <joey@kitenet.net>
 
 =cut
 
-#}}}
-
 use warnings;
 use strict;
 use Getopt::Long;
 main();
 
 my %rcs;
-sub rcs_test { #{{{
+sub rcs_test {
        my ($action, $dir, $topdir, $subdir) = @_;
 
        if (exists $rcs{$dir}) {
        else {
                return $rcs{$dir}=$rcs;
        }
-} #}}}
+}
        
-sub findcommand { #{{{
+sub findcommand {
        my ($action, $dir, $topdir, $subdir, $is_checkout) = @_;
        
        if (exists $config{$topdir}{$subdir}{$action}) {
        else {
                return undef;
        }
-} #}}}
+}
 
-sub action { #{{{
+sub action {
        my ($action, $dir, $topdir, $subdir) = @_;
        
        $ENV{MR_CONFIG}=$configfiles{$topdir};
                        return OK;
                }
        }
-} #}}}
+}
 
 # run actions on multiple repos, in parallel
-sub mrs { #{{{
+sub mrs {
        my $action=shift;
        my @repos=@_;
 
                        }
                }
        }
-} #}}}
+}
 
-sub record { #{{{
+sub record {
        my $dir=shift()->[0];
        my $ret=shift;
 
        else {
                die "unknown exit status $ret";
        }
-} #}}}
+}
 
-sub showstats { #{{{
+sub showstats {
        my $action=shift;
        if (! @ok && ! @failed && ! @skipped) {
                die "mr $action: no repositories found to work on\n";
                        print STDERR "mr $action: (failed: ".join(" ", @failed).")\n";
                }
        }
-} #}}}
+}
 
-sub showstat { #{{{
+sub showstat {
        my $count=shift;
        my $singular=shift;
        my $plural=shift;
                return "$count ".($count > 1 ? $plural : $singular);
        }
        return;
-} #}}}
+}
 
 # an ordered list of repos
-sub repolist { #{{{
+sub repolist {
        my @list;
        foreach my $topdir (sort keys %config) {
                foreach my $subdir (sort keys %{$config{$topdir}}) {
                             ||
                $a->{subdir} cmp $b->{subdir}
        } @list;
-} #}}}
+}
 
 # figure out which repos to act on
-sub selectrepos { #{{{
+sub selectrepos {
        my @repos;
        foreach my $repo (repolist()) {
                my $topdir=$repo->{topdir};
                $no_chdir=1;
        }
        return @repos;
-} #}}}
+}
 
-sub expandenv { #{{{
+sub expandenv {
        my $val=shift;
        
 
        }
        
        return $val;
-} #}}}
+}
 
 my %loaded;
-sub loadconfig { #{{{
+sub loadconfig {
        my $f=shift;
 
        my @toload;
        foreach (@toload) {
                loadconfig($_);
        }
-} #}}}
+}
 
-sub modifyconfig { #{{{
+sub modifyconfig {
        my $f=shift;
        # the section to modify or add
        my $targetsection=shift;
        open(my $out, ">", $f) || die "mr: write $f: $!\n";
        print $out @out;
        close $out;     
-} #}}}
+}
 
-sub dispatch { #{{{
+sub dispatch {
        my $action=shift;
 
        # actions that do not operate on all repos
                        record($repo, action($action, @$repo));
                }
        }
-} #}}}
+}
 
-sub help { #{{{
+sub help {
        exec($config{''}{DEFAULT}{help}) || die "exec: $!";
-} #}}}
+}
 
-sub config { #{{{
+sub config {
        if (@_ < 2) {
                die "mr config: not enough parameters\n";
        }
        }
        modifyconfig($ENV{MR_CONFIG}, $section, %changefields) if %changefields;
        exit 0;
-} #}}}
+}
 
-sub register { #{{{
+sub register {
        if ($config_overridden) {
                # Find the directory that the specified config file is
                # located in.
                join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
        print "mr register: running >>$command<<\n" if $verbose;
        exec($command) || die "exec: $!";
-} #}}}
+}
 
 # alias expansion and command stemming
-sub expandaction { #{{{
+sub expandaction {
        my $action=shift;
        if (exists $alias{$action}) {
                $action=$alias{$action};
                }
        }
        return $action;
-} #}}}
+}
 
-sub getopts { #{{{
+sub getopts {
        my @saved=@ARGV;
        Getopt::Long::Configure("bundling", "no_permute");
        my $result=GetOptions(
                last if $option eq $ARGV[0];
                $ENV{MR_SWITCHES}.="$option ";
        }
-} #}}}
+}
 
-sub init { #{{{
+sub init {
        $SIG{INT}=sub {
                print STDERR "mr: interrupted\n";
                exit 2;
                use FindBin qw($Bin $Script);
                $ENV{MR_PATH}=$Bin."/".$Script;
        };
-} #}}}
+}
 
-sub main { #{{{
+sub main {
        getopts();
        init();
 
        else {
                exit 0;
        }
-} #}}}
+}
 
 # Finally, some useful actions that mr knows about by default.
 # These can be overridden in ~/.mrconfig.
-#DATA{{{
 __DATA__
 [ALIAS]
 co = checkout
 bzr_push = bzr push "$@"
 cvs_push = :
 hg_push = hg push "$@"
-darcs_push = darcs push -a
+darcs_push = darcs push -a "$@"
 
 svn_diff = svn diff "$@"
 git_diff = git diff "$@"
 ed = echo "A horse is a horse, of course, of course.."
 T = echo "I pity the fool."
 right = echo "Not found."
-#}}}
 
 # vim:sw=8:sts=0:ts=8:noet