]>
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:
=head1 NAME
mr - a Multiple Repository management tool
=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
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 yei ld
+ssh connection limits. Running between 3 and 5 jobs at a time will yie ld
a good speedup in updates without loading the machine too much.
=back
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.
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 <joey@kitenet.net>
=head1 AUTHOR
Copyright 2007 Joey Hess <joey@kitenet.net>
use warnings;
use strict;
use Getopt::Long;
use warnings;
use strict;
use Getopt::Long;
my ($action, $dir, $topdir, $subdir) = @_;
if (exists $rcs{$dir}) {
my ($action, $dir, $topdir, $subdir) = @_;
if (exists $rcs{$dir}) {
chomp $rcs;
if ($rcs=~/\n/s) {
$rcs=~s/\n/, /g;
chomp $rcs;
if ($rcs=~/\n/s) {
$rcs=~s/\n/, /g;
- print STDERR "mr $action: found multiple possible repository types ($rcs) for $topdir$sub dir\n";
+ print STDERR "mr $action: found multiple possible repository types ($rcs) for $dir\n";
return undef;
}
if (! length $rcs) {
return undef;
}
if (! length $rcs) {
else {
return $rcs{$dir}=$rcs;
}
else {
return $rcs{$dir}=$rcs;
}
my ($action, $dir, $topdir, $subdir, $is_checkout) = @_;
if (exists $config{$topdir}{$subdir}{$action}) {
my ($action, $dir, $topdir, $subdir, $is_checkout) = @_;
if (exists $config{$topdir}{$subdir}{$action}) {
my ($action, $dir, $topdir, $subdir) = @_;
$ENV{MR_CONFIG}=$configfiles{$topdir};
my ($action, $dir, $topdir, $subdir) = @_;
$ENV{MR_CONFIG}=$configfiles{$topdir};
elsif (! defined $command) {
my $rcs=rcs_test(@_);
if (! defined $rcs) {
elsif (! defined $command) {
my $rcs=rcs_test(@_);
if (! defined $rcs) {
- print STDERR "mr $action: unknown repository type and no defined $action command for $topdir$sub dir\n";
+ print STDERR "mr $action: unknown repository type and no defined $action command for $dir\n";
- print STDERR "mr $action: no defined action for $rcs repository $topdir$sub dir, skipping\n";
+ print STDERR "mr $action: no defined action for $rcs repository $dir, skipping\n";
return SKIPPED;
}
}
else {
if (! $no_chdir) {
return SKIPPED;
}
}
else {
if (! $no_chdir) {
- print "mr $action: $topdir$sub dir\n" unless $quiet;
+ print "mr $action: $dir\n" unless $quiet;
}
else {
my $s=$directory;
}
else {
my $s=$directory;
- $s=~s/^\Q$topdir$sub dir\E\/?//;
- print "mr $action: $topdir$sub dir (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 ".
}
$command="set -e; ".$lib.
"my_action(){ $command\n }; my_action ".
# run actions on multiple repos, in parallel
# run actions on multiple repos, in parallel
my $action=shift;
my @repos=@_;
my $action=shift;
my @repos=@_;
my $dir=shift()->[0];
my $ret=shift;
my $dir=shift()->[0];
my $ret=shift;
else {
die "unknown exit status $ret";
}
else {
die "unknown exit status $ret";
}
my $action=shift;
if (! @ok && ! @failed && ! @skipped) {
die "mr $action: no repositories found to work on\n";
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";
}
}
print STDERR "mr $action: (failed: ".join(" ", @failed).")\n";
}
}
my $count=shift;
my $singular=shift;
my $plural=shift;
my $count=shift;
my $singular=shift;
my $plural=shift;
return "$count ".($count > 1 ? $plural : $singular);
}
return;
return "$count ".($count > 1 ? $plural : $singular);
}
return;
# an ordered list of repos
# an ordered list of repos
my @list;
foreach my $topdir (sort keys %config) {
foreach my $subdir (sort keys %{$config{$topdir}}) {
my @list;
foreach my $topdir (sort keys %config) {
foreach my $subdir (sort keys %{$config{$topdir}}) {
||
$a->{subdir} cmp $b->{subdir}
} @list;
||
$a->{subdir} cmp $b->{subdir}
} @list;
# figure out which repos to act on
# figure out which repos to act on
my @repos;
foreach my $repo (repolist()) {
my $topdir=$repo->{topdir};
my @repos;
foreach my $repo (repolist()) {
my $topdir=$repo->{topdir};
$no_chdir=1;
}
return @repos;
$no_chdir=1;
}
return @repos;
foreach (@toload) {
loadconfig($_);
}
foreach (@toload) {
loadconfig($_);
}
my $f=shift;
# the section to modify or add
my $targetsection=shift;
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;
open(my $out, ">", $f) || die "mr: write $f: $!\n";
print $out @out;
close $out;
my $action=shift;
# actions that do not operate on all repos
my $action=shift;
# actions that do not operate on all repos
record($repo, action($action, @$repo));
}
}
record($repo, action($action, @$repo));
}
}
exec($config{''}{DEFAULT}{help}) || die "exec: $!";
exec($config{''}{DEFAULT}{help}) || die "exec: $!";
if (@_ < 2) {
die "mr config: not enough parameters\n";
}
if (@_ < 2) {
die "mr config: not enough parameters\n";
}
}
modifyconfig($ENV{MR_CONFIG}, $section, %changefields) if %changefields;
exit 0;
}
modifyconfig($ENV{MR_CONFIG}, $section, %changefields) if %changefields;
exit 0;
if ($config_overridden) {
# Find the directory that the specified config file is
# located in.
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: $!";
join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
print "mr register: running >>$command<<\n" if $verbose;
exec($command) || die "exec: $!";
# alias expansion and command stemming
# alias expansion and command stemming
my $action=shift;
if (exists $alias{$action}) {
$action=$alias{$action};
my $action=shift;
if (exists $alias{$action}) {
$action=$alias{$action};
my @saved=@ARGV;
Getopt::Long::Configure("bundling", "no_permute");
my $result=GetOptions(
my @saved=@ARGV;
Getopt::Long::Configure("bundling", "no_permute");
my $result=GetOptions(
last if $option eq $ARGV[0];
$ENV{MR_SWITCHES}.="$option ";
}
last if $option eq $ARGV[0];
$ENV{MR_SWITCHES}.="$option ";
}
$SIG{INT}=sub {
print STDERR "mr: interrupted\n";
exit 2;
$SIG{INT}=sub {
print STDERR "mr: interrupted\n";
exit 2;
use FindBin qw($Bin $Script);
$ENV{MR_PATH}=$Bin."/".$Script;
};
use FindBin qw($Bin $Script);
$ENV{MR_PATH}=$Bin."/".$Script;
};
# Finally, some useful actions that mr knows about by default.
# These can be overridden in ~/.mrconfig.
# Finally, some useful actions that mr knows about by default.
# These can be overridden in ~/.mrconfig.
__DATA__
[ALIAS]
co = checkout
__DATA__
[ALIAS]
co = checkout
ed = echo "A horse is a horse, of course, of course.."
T = echo "I pity the fool."
right = echo "Not found."
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
# vim:sw=8:sts=0:ts=8:noet