]>
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:
B<mr> is a Multiple Repository management tool. It can checkout, update, or
perform other actions on a set of repositories as if they were one combined
repository. It supports any combination of subversion, git, cvs, mercurial,
B<mr> is a Multiple Repository management tool. It can checkout, update, or
perform other actions on a set of repositories as if they were one combined
repository. It supports any combination of subversion, git, cvs, mercurial,
-bzr, darcs and fossil repositories, and support for other revi sion
+bzr, darcs and fossil repositories, and support for other ver sion
control systems can easily be added.
B<mr> cds into and operates on all registered repositories at or below your
control systems can easily be added.
B<mr> cds into and operates on all registered repositories at or below your
looks for a .mrconfig file in the current directory, or in one of its
parent directories.
looks for a .mrconfig file in the current directory, or in one of its
parent directories.
-These predefined commands should be fairly familiar to users of any revi sion
+These predefined commands should be fairly familiar to users of any ver sion
=item record
Records changes to the local repository, but does not push them to the
=item record
Records changes to the local repository, but does not push them to the
-remote repository. Only supported for distributed revi sion control systems.
+remote repository. Only supported for distributed ver sion 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
The optional -m parameter allows specifying a commit message.
=item push
Pushes committed local changes to the remote repository. A no-op for
-centralized revi sion control systems.
+centralized ver sion control systems.
update"
Additional parameters can be passed to most commands, and are passed on
update"
Additional parameters can be passed to most commands, and are passed on
-unchanged to the underlying revi sion control system. This is mostly useful
-if the repositories mr will act on all use the same revi sion control
+unchanged to the underlying ver sion control system. This is mostly useful
+if the repositories mr will act on all use the same ver sion control
-Be quiet. This supresses mr's usual output, as well as any output from
+Be quiet. This supp resses mr's usual output, as well as any output from
commands that are run (including stderr output). If a command fails,
the output will be shown.
commands that are run (including stderr output). If a command fails,
the output will be shown.
When looking for a command to run for a given action, mr first looks for
a parameter with the same name as the action. If that is not found, it
When looking for a command to run for a given action, mr first looks for
a parameter with the same name as the action. If that is not found, it
-looks for a parameter named "rcs _action" (substituting in the name of the
-revision control system and the action). The name of the revi sion control
-system is itself determined by running each defined "rcs _test" action,
+looks for a parameter named "VCS _action" (substituting in the name of the
+version control system and the action). The name of the ver sion control
+system is itself determined by running each defined "VCS _test" action,
until one succeeds.
Internally, mr has settings for "git_update", "svn_update", etc. To change
until one succeeds.
Internally, mr has settings for "git_update", "svn_update", etc. To change
-the action that is performed for a given revi sion control system, you can
-override these rcs specific actions. To add a new revi sion control system,
-you can just add rcs specific actions for it.
+the action that is performed for a given ver sion control system, you can
+override these VCS specific actions. To add a new ver sion control system,
+you can just add VCS specific actions for it.
=head1 UNTRUSTED MRCONFIG FILES
=head1 UNTRUSTED MRCONFIG FILES
-my %r cs;
-sub r cs_test {
+my %v cs;
+sub v cs_test {
my ($action, $dir, $topdir, $subdir) = @_;
my ($action, $dir, $topdir, $subdir) = @_;
- if (exists $r cs{$dir}) {
- return $r cs{$dir};
+ if (exists $v cs{$dir}) {
+ return $v cs{$dir};
sort {
length $a <=> length $b
||
$a cmp $b
} grep { /_test$/ } keys %{$config{$topdir}{$subdir}}) {
sort {
length $a <=> length $b
||
$a cmp $b
} grep { /_test$/ } keys %{$config{$topdir}{$subdir}}) {
- my ($rcs)=$r cs_test=~/(.*)_test/;
- $test="my_$rcs_test() {\n$config{$topdir}{$subdir}{$r cs_test}\n}\n".$test;
- $test.="if my_$rcs_test; then echo $r cs; fi\n";
+ my ($vcs)=$v cs_test=~/(.*)_test/;
+ $test="my_$vcs_test() {\n$config{$topdir}{$subdir}{$v cs_test}\n}\n".$test;
+ $test.="if my_$vcs_test; then echo $v cs; fi\n";
}
$test=$config{$topdir}{$subdir}{lib}."\n".$test
if exists $config{$topdir}{$subdir}{lib};
}
$test=$config{$topdir}{$subdir}{lib}."\n".$test
if exists $config{$topdir}{$subdir}{lib};
- print "mr $action: running r cs test >>$test<<\n" if $verbose;
- my $r cs=`$test`;
- chomp $r cs;
- if ($r cs=~/\n/s) {
- $r cs=~s/\n/, /g;
- print STDERR "mr $action: found multiple possible repository types ($r cs) for ".fulldir($topdir, $subdir)."\n";
+ print "mr $action: running v cs test >>$test<<\n" if $verbose;
+ my $v cs=`$test`;
+ chomp $v cs;
+ if ($v cs=~/\n/s) {
+ $v cs=~s/\n/, /g;
+ print STDERR "mr $action: found multiple possible repository types ($v cs) for ".fulldir($topdir, $subdir)."\n";
- if (! length $r cs) {
- return $r cs{$dir}=undef;
+ if (! length $v cs) {
+ return $v cs{$dir}=undef;
- return $rcs{$dir}=$r cs;
+ return $vcs{$dir}=$v cs;
- if (defined $r cs &&
- exists $config{$topdir}{$subdir}{$r cs."_".$action}) {
- return $config{$topdir}{$subdir}{$r cs."_".$action};
+ if (defined $v cs &&
+ exists $config{$topdir}{$subdir}{$v cs."_".$action}) {
+ return $config{$topdir}{$subdir}{$v cs."_".$action};
my $is_checkout=($action eq 'checkout');
my $is_update=($action =~ /update/);
my $is_checkout=($action eq 'checkout');
my $is_update=($action =~ /update/);
+ ($ENV{MR_REPO}=$dir) =~ s!/$!! ;
$ENV{MR_ACTION}=$action;
foreach my $testname ("skip", "deleted") {
$ENV{MR_ACTION}=$action;
foreach my $testname ("skip", "deleted") {
return FAILED;
}
elsif (! defined $command) {
return FAILED;
}
elsif (! defined $command) {
- my $rcs=r cs_test(@_);
- if (! defined $r cs) {
+ my $vcs=v cs_test(@_);
+ if (! defined $v cs) {
print STDERR "mr $action: unknown repository type and no defined $action command for $fulldir\n";
return FAILED;
}
else {
print STDERR "mr $action: unknown repository type and no defined $action command for $fulldir\n";
return FAILED;
}
else {
- print STDERR "mr $action: no defined action for $r cs repository $fulldir, skipping\n";
+ print STDERR "mr $action: no defined action for $v cs repository $fulldir, skipping\n";
-# figure out which repos to act on
+# Figure out which repos to act on. Returns a list of array refs
+# in the format:
+#
+# [ "$full_repo_path/", "$mr_config_path/", $section_header ]
sub selectrepos {
my @repos;
foreach my $repo (repolist()) {
sub selectrepos {
my @repos;
foreach my $repo (repolist()) {
close $in unless ref $f eq 'GLOB';
my $section;
close $in unless ref $f eq 'GLOB';
my $section;
+
+ # Keep track of the current line in the config file;
+ # when a file is included track the current line from the include.
+ my $included=undef;
+ my $includeline=0;
+ my $nextline = sub {
+ if ($included) {
+ $includeline++;
+ $included--;
+ }
+ else {
+ $included=undef;
+ $includeline=0;
+ $line++;
+ }
+ my $l=shift @lines;
+ chomp $l;
+ return $l
+ };
+ my $lineerror = sub {
+ my $msg=shift;
+ if (defined $included) {
+ die "mr: $f line $line include line $includeline: $msg\n";
+ }
+ else {
+ die "mr: $f line $line: $msg\n";
+ }
+ };
+
- $_=shift @lines;
- $line++;
- chomp;
+ $_=$nextline->();
+
+ if (! $trusted && /[[:cntrl:]]/) {
+ trusterror("mr: illegal control character", $f, $line, $bootstrap_url);
+ }
+
next if /^\s*\#/ || /^\s*$/;
if (/^\[([^\]]*)\]\s*$/) {
$section=$1;
next if /^\s*\#/ || /^\s*$/;
if (/^\[([^\]]*)\]\s*$/) {
$section=$1;
# continued value
while (@lines && $lines[0]=~/^\s(.+)/) {
# continued value
while (@lines && $lines[0]=~/^\s(.+)/) {
- shift(@lines);
- $line++;
$value.="\n$1";
chomp $value;
$value.="\n$1";
chomp $value;
if ($parameter eq "include") {
print "mr: including output of \"$value\"\n" if $verbose;
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";
}
if ($?) {
print STDERR "mr: include command exited nonzero ($?)\n";
}
+ $included += @inc;
+ unshift @lines, @inc;
next;
}
if (! defined $section) {
next;
}
if (! defined $section) {
- die "$f line $.: parameter ($parameter) not in section\n" ;
+ $lineerror->("parameter ($parameter) not in section") ;
}
if ($section eq 'ALIAS') {
$alias{$parameter}=$value;
}
if ($section eq 'ALIAS') {
$alias{$parameter}=$value;
if ($parameter eq 'chain' &&
length $dir && $section ne "DEFAULT") {
my $chaindir="$section";
if ($parameter eq 'chain' &&
length $dir && $section ne "DEFAULT") {
my $chaindir="$section";
- if ($chaindir !~ m!/!) {
+ if ($chaindir !~ m!^ /!) {
$chaindir=$dir.$chaindir;
}
if (-e "$chaindir/.mrconfig") {
$chaindir=$dir.$chaindir;
}
if (-e "$chaindir/.mrconfig") {
- die "$f line $line: parse error\n" ;
+ $lineerror->("parse error") ;