X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/c428c39904c8cffa8389687cee683cfa32836920..6277f4c870c0b808d70220c68a5748c02820e02c:/mr diff --git a/mr b/mr index 7eaaddd..7d35892 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 @@ -81,6 +79,11 @@ remote repository. Only supported for distributed revision control systems. The optional -m parameter allows specifying a commit message. +=item push + +Pushes committed local changes to the remote repository. A no-op for +centralized revision control systems. + =item diff Show a diff of uncommitted changes. @@ -211,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 @@ -338,6 +341,13 @@ 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 remote git +checkout. 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 @@ -348,8 +358,6 @@ http://kitenet.net/~joey/code/mr/ =cut -#}}} - use warnings; use strict; use Getopt::Long; @@ -385,7 +393,7 @@ my (@ok, @failed, @skipped); main(); my %rcs; -sub rcs_test { #{{{ +sub rcs_test { my ($action, $dir, $topdir, $subdir) = @_; if (exists $rcs{$dir}) { @@ -411,7 +419,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) { @@ -420,9 +428,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}) { @@ -442,11 +450,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" : ""; @@ -504,22 +512,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 ". @@ -541,8 +549,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) { @@ -559,10 +569,10 @@ sub action { #{{{ return OK; } } -} #}}} +} # run actions on multiple repos, in parallel -sub mrs { #{{{ +sub mrs { my $action=shift; my @repos=@_; @@ -629,9 +639,9 @@ sub mrs { #{{{ } } } -} #}}} +} -sub record { #{{{ +sub record { my $dir=shift()->[0]; my $ret=shift; @@ -657,9 +667,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"; @@ -677,9 +687,9 @@ sub showstats { #{{{ print STDERR "mr $action: (failed: ".join(" ", @failed).")\n"; } } -} #}}} +} -sub showstat { #{{{ +sub showstat { my $count=shift; my $singular=shift; my $plural=shift; @@ -687,10 +697,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}}) { @@ -708,10 +718,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}; @@ -750,9 +760,9 @@ sub selectrepos { #{{{ $no_chdir=1; } return @repos; -} #}}} +} -sub expandenv { #{{{ +sub expandenv { my $val=shift; @@ -762,10 +772,10 @@ sub expandenv { #{{{ } return $val; -} #}}} +} my %loaded; -sub loadconfig { #{{{ +sub loadconfig { my $f=shift; my @toload; @@ -841,6 +851,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; } @@ -894,9 +907,9 @@ sub loadconfig { #{{{ foreach (@toload) { loadconfig($_); } -} #}}} +} -sub modifyconfig { #{{{ +sub modifyconfig { my $f=shift; # the section to modify or add my $targetsection=shift; @@ -991,9 +1004,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 @@ -1022,13 +1035,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"; } @@ -1064,9 +1077,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. @@ -1109,10 +1122,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}; @@ -1133,9 +1146,9 @@ sub expandaction { #{{{ } } return $action; -} #}}} +} -sub getopts { #{{{ +sub getopts { my @saved=@ARGV; Getopt::Long::Configure("bundling", "no_permute"); my $result=GetOptions( @@ -1158,9 +1171,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; @@ -1182,9 +1195,9 @@ sub init { #{{{ use FindBin qw($Bin $Script); $ENV{MR_PATH}=$Bin."/".$Script; }; -} #}}} +} -sub main { #{{{ +sub main { getopts(); init(); @@ -1205,11 +1218,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 @@ -1288,6 +1300,13 @@ bzr_record = bzr commit "$@" hg_record = hg commit -m "$@" darcs_record = darcs record -a -m "$@" +svn_push = : +git_push = git push "$@" +bzr_push = bzr push "$@" +cvs_push = : +hg_push = hg push "$@" +darcs_push = darcs push -a "$@" + svn_diff = svn diff "$@" git_diff = git diff "$@" bzr_diff = bzr diff "$@" @@ -1371,6 +1390,7 @@ online = info "no offline commands to run" fi offline = + umask 077 touch ~/.mrlog info "offline mode enabled" remember = @@ -1386,6 +1406,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