X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/466a94bc78c2ee68a2aef9f2448606126c141e99..2b5fbf08dab8d43d1e9487416cf4d5f2007aba73:/mr diff --git a/mr b/mr index e76887e..613f86a 100755 --- a/mr +++ b/mr @@ -1,13 +1,11 @@ #!/usr/bin/perl -#man{{{ - =head1 NAME mr - a Multiple Repository management tool =head1 SYNOPSIS -/ + B [options] checkout B [options] update @@ -216,7 +214,7 @@ with no number specified. This can greatly speed up operations such as updates. 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 @@ -343,6 +341,12 @@ 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. +=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 @@ -353,8 +357,6 @@ http://kitenet.net/~joey/code/mr/ =cut -#}}} - use warnings; use strict; use Getopt::Long; @@ -390,7 +392,7 @@ my (@ok, @failed, @skipped); main(); my %rcs; -sub rcs_test { #{{{ +sub rcs_test { my ($action, $dir, $topdir, $subdir) = @_; if (exists $rcs{$dir}) { @@ -416,7 +418,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 $dir\n"; return undef; } if (! length $rcs) { @@ -425,9 +427,9 @@ sub rcs_test { #{{{ else { return $rcs{$dir}=$rcs; } -} #}}} +} -sub findcommand { #{{{ +sub findcommand { my ($action, $dir, $topdir, $subdir, $is_checkout) = @_; if (exists $config{$topdir}{$subdir}{$action}) { @@ -447,11 +449,11 @@ sub findcommand { #{{{ else { return undef; } -} #}}} +} -sub action { #{{{ +sub action { my ($action, $dir, $topdir, $subdir) = @_; - + $ENV{MR_CONFIG}=$configfiles{$topdir}; my $lib=exists $config{$topdir}{$subdir}{lib} ? $config{$topdir}{$subdir}{lib}."\n" : ""; @@ -509,22 +511,22 @@ 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 $dir\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 $dir, skipping\n"; return SKIPPED; } } else { if (! $no_chdir) { - print "mr $action: $topdir$subdir\n" unless $quiet; + print "mr $action: $dir\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$dir\E\/?//; + print "mr $action: $dir (in subdir $s)\n" unless $quiet; } $command="set -e; ".$lib. "my_action(){ $command\n }; my_action ". @@ -546,8 +548,10 @@ sub action { #{{{ if (-e "$ENV{HOME}/.mrlog" && $action ne 'remember') { # recreate original command line to # remember, and avoid recursing - @ARGV=('-n', $action, @ARGV); + my @orig=@ARGV; + @ARGV=('-n', $action, @orig); action("remember", $dir, $topdir, $subdir); + @ARGV=@orig; } } elsif ($ret != 0) { @@ -564,10 +568,10 @@ sub action { #{{{ return OK; } } -} #}}} +} # run actions on multiple repos, in parallel -sub mrs { #{{{ +sub mrs { my $action=shift; my @repos=@_; @@ -634,9 +638,9 @@ sub mrs { #{{{ } } } -} #}}} +} -sub record { #{{{ +sub record { my $dir=shift()->[0]; my $ret=shift; @@ -662,9 +666,9 @@ sub record { #{{{ 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"; @@ -682,9 +686,9 @@ sub showstats { #{{{ print STDERR "mr $action: (failed: ".join(" ", @failed).")\n"; } } -} #}}} +} -sub showstat { #{{{ +sub showstat { my $count=shift; my $singular=shift; my $plural=shift; @@ -692,10 +696,10 @@ sub showstat { #{{{ 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}}) { @@ -713,10 +717,10 @@ sub repolist { #{{{ || $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}; @@ -755,9 +759,9 @@ sub selectrepos { #{{{ $no_chdir=1; } return @repos; -} #}}} +} -sub expandenv { #{{{ +sub expandenv { my $val=shift; @@ -767,10 +771,10 @@ sub expandenv { #{{{ } return $val; -} #}}} +} my %loaded; -sub loadconfig { #{{{ +sub loadconfig { my $f=shift; my @toload; @@ -846,6 +850,9 @@ sub loadconfig { #{{{ if ($parameter eq "include") { print "mr: including output of \"$value\"\n" if $verbose; unshift @lines, `$value`; + if ($?) { + print STDERR "mr: include command exited nonzero ($?)\n"; + } next; } @@ -899,9 +906,9 @@ sub loadconfig { #{{{ foreach (@toload) { loadconfig($_); } -} #}}} +} -sub modifyconfig { #{{{ +sub modifyconfig { my $f=shift; # the section to modify or add my $targetsection=shift; @@ -996,9 +1003,9 @@ sub modifyconfig { #{{{ 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 @@ -1027,13 +1034,13 @@ sub dispatch { #{{{ 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"; } @@ -1069,9 +1076,9 @@ sub config { #{{{ } 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. @@ -1114,10 +1121,10 @@ sub register { #{{{ 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}; @@ -1138,9 +1145,9 @@ sub expandaction { #{{{ } } return $action; -} #}}} +} -sub getopts { #{{{ +sub getopts { my @saved=@ARGV; Getopt::Long::Configure("bundling", "no_permute"); my $result=GetOptions( @@ -1163,9 +1170,9 @@ sub getopts { #{{{ last if $option eq $ARGV[0]; $ENV{MR_SWITCHES}.="$option "; } -} #}}} +} -sub init { #{{{ +sub init { $SIG{INT}=sub { print STDERR "mr: interrupted\n"; exit 2; @@ -1187,9 +1194,9 @@ sub init { #{{{ use FindBin qw($Bin $Script); $ENV{MR_PATH}=$Bin."/".$Script; }; -} #}}} +} -sub main { #{{{ +sub main { getopts(); init(); @@ -1210,11 +1217,10 @@ sub main { #{{{ else { exit 0; } -} #}}} +} # Finally, some useful actions that mr knows about by default. # These can be overridden in ~/.mrconfig. -#DATA{{{ __DATA__ [ALIAS] co = checkout @@ -1298,7 +1304,7 @@ git_push = git push "$@" 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 "$@" @@ -1383,6 +1389,7 @@ online = info "no offline commands to run" fi offline = + umask 077 touch ~/.mrlog info "offline mode enabled" remember = @@ -1398,6 +1405,5 @@ remember = 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