X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/7ec67608cca6d2ca8095c2ebf0585e36431056ea..ba5e0ca2eca4d80aefc362d4aabd531d3ed4c0d0:/mr diff --git a/mr b/mr index 883f4fb..a897a5f 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,18 +214,13 @@ 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 =head1 FILES -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. - B is configured by .mrconfig files. It starts by reading the .mrconfig file in your home directory, and this can in turn chain load .mrconfig files from repositories. @@ -343,6 +336,17 @@ 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. +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 + +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}) { @@ -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,9 +449,9 @@ sub findcommand { #{{{ else { return undef; } -} #}}} +} -sub action { #{{{ +sub action { my ($action, $dir, $topdir, $subdir) = @_; $ENV{MR_CONFIG}=$configfiles{$topdir}; @@ -566,10 +568,10 @@ sub action { #{{{ return OK; } } -} #}}} +} # run actions on multiple repos, in parallel -sub mrs { #{{{ +sub mrs { my $action=shift; my @repos=@_; @@ -636,9 +638,9 @@ sub mrs { #{{{ } } } -} #}}} +} -sub record { #{{{ +sub record { my $dir=shift()->[0]; my $ret=shift; @@ -664,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"; @@ -684,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; @@ -694,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}}) { @@ -715,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}; @@ -757,9 +759,9 @@ sub selectrepos { #{{{ $no_chdir=1; } return @repos; -} #}}} +} -sub expandenv { #{{{ +sub expandenv { my $val=shift; @@ -769,10 +771,10 @@ sub expandenv { #{{{ } return $val; -} #}}} +} my %loaded; -sub loadconfig { #{{{ +sub loadconfig { my $f=shift; my @toload; @@ -848,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; } @@ -901,9 +906,9 @@ sub loadconfig { #{{{ foreach (@toload) { loadconfig($_); } -} #}}} +} -sub modifyconfig { #{{{ +sub modifyconfig { my $f=shift; # the section to modify or add my $targetsection=shift; @@ -998,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 @@ -1029,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"; } @@ -1071,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. @@ -1116,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}; @@ -1140,9 +1145,9 @@ sub expandaction { #{{{ } } return $action; -} #}}} +} -sub getopts { #{{{ +sub getopts { my @saved=@ARGV; Getopt::Long::Configure("bundling", "no_permute"); my $result=GetOptions( @@ -1165,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; @@ -1189,9 +1194,9 @@ sub init { #{{{ use FindBin qw($Bin $Script); $ENV{MR_PATH}=$Bin."/".$Script; }; -} #}}} +} -sub main { #{{{ +sub main { getopts(); init(); @@ -1212,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 @@ -1271,7 +1275,7 @@ git_bare_test = svn_update = svn update "$@" git_update = git pull "$@" -bzr_update = bzr merge "$@" +bzr_update = bzr merge --pull "$@" cvs_update = cvs update "$@" hg_update = hg pull "$@" && hg update "$@" darcs_update = darcs pull -a "$@" @@ -1300,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 "$@" @@ -1385,6 +1389,7 @@ online = info "no offline commands to run" fi offline = + umask 077 touch ~/.mrlog info "offline mode enabled" remember = @@ -1400,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