]>
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> [options] register [repository]
B<mr> [options] register [repository]
-B<mr> [options] config section [parameter=[value] ...]
+B<mr> [options] config section ["parameter=[value]" ...]
B<mr> [options] action [params ...]
=head1 DESCRIPTION
B<mr> [options] action [params ...]
=head1 DESCRIPTION
-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 respository. It
-supports any combination of subversion, git, cvs, and bzr repositories,
-and support for other revision control systems can easily be a dded.
+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
+respository. It supports any combination of subversion, git, cvs, mecurial and
+bzr repositories, and support for other revision control systems can easily be
+added.
B<mr> cds into and operates on all registered repositories at or below your
working directory. Or, if you are in a subdirectory of a repository that
B<mr> cds into and operates on all registered repositories at or below your
working directory. Or, if you are in a subdirectory of a repository that
-Register an existing repository in the mrconfig file. By default, the
+Register an existing repository in a mrconfig file. By default, the
repository in the current directory is registered, or you can specify a
directory to register.
repository in the current directory is registered, or you can specify a
directory to register.
-By default it registers it to the ~/.mrconfig file. To make it write to a
-different file, use the -c option .
+The mrconfig file that is modified is chosen by either the -c option, or by
+looking for the closest known one at or below the current directory .
-Adds, modifies, removes, or prints a value from the mrconfig file. The next
+Adds, modifies, removes, or prints a value from a mrconfig file. The next
parameter is the name of the section the value is in. To add or modify
values, use one or more instances of "parameter=value". Use "parameter=" to
remove a parameter. Use just "parameter" to get the value of a parameter.
parameter is the name of the section the value is in. To add or modify
values, use one or more instances of "parameter=value". Use "parameter=" to
remove a parameter. Use just "parameter" to get the value of a parameter.
+To see the built-in library of shell functions contained in mr:
+
+ mr config DEFAULT lib
+
+The ~/.mrconfig file is used by default. To use a different config file,
+use the -c option.
+
=item help
Displays this help.
=item help
Displays this help.
-Use the specified mrconfig file, instead of looking for one in your home
-directory.
+Use the specified mrconfig file. The default is B<~/.mrconfig>
paths.
Within a section, each parameter defines a shell command to run to handle a
paths.
Within a section, each parameter defines a shell command to run to handle a
-given action. mr contains default handlers for the "update", "status", and
-"commit" actions, so normally you only need to specify what to do for
-"checkout".
+given action. mr contains default handlers for "update", "status",
+"commit", and other standard actions. Normally you only need to specify what
+to do for "checkout".
Note that these shell commands are run in a "set -e" shell
environment, where any additional parameters you pass are available in
Note that these shell commands are run in a "set -e" shell
environment, where any additional parameters you pass are available in
are run inside the repository, though not necessarily at the top of it.
The "MR_REPO" environment variable is set to the path to the top of the
are run inside the repository, though not necessarily at the top of it.
The "MR_REPO" environment variable is set to the path to the top of the
-repository, and "MR_CONFIG" is set to the .mrconfig file that defines th e
-repo being acted on, or, if the repo is not yet in a config file, the
-.mrconfig file that mr thinks it should be added t o.
+repository. The "MR_CONFIG" environment variable is set to the .mrconfig fil e
+that defines the repo being acted on, or, if the repo is not yet in a config
+file, the .mrconfig file that should be modified to register the rep o.
A few parameters have special meanings:
A few parameters have special meanings:
will try to load a .mrconfig file from the root of the repository. (You
should avoid chaining from repositories with untrusted committers.)
will try to load a .mrconfig file from the root of the repository. (You
should avoid chaining from repositories with untrusted committers.)
-=item deleted
-
-If the "deleted" parameter is set and its command returns true, then
-B<mr> will treat the repository as deleted. It won't ever actually delete
-the repository, but it will warn if it sees the repository's directory.
-This is useful when one mrconfig file is shared amoung multiple machines,
-to keep track of and remember to delete old repositories.
-
=item lib
The "lib" parameter can specify some shell code that will be run before each
=item lib
The "lib" parameter can specify some shell code that will be run before each
};
$ENV{MR_CONFIG}="$ENV{HOME}/.mrconfig";
};
$ENV{MR_CONFIG}="$ENV{HOME}/.mrconfig";
+my $config_overridden=0;
my $directory=getcwd();
my $verbose=0;
my $stats=0;
my $directory=getcwd();
my $verbose=0;
my $stats=0;
Getopt::Long::Configure("no_permute");
my $result=GetOptions(
"d|directory=s" => sub { $directory=abs_path($_[1]) },
Getopt::Long::Configure("no_permute");
my $result=GetOptions(
"d|directory=s" => sub { $directory=abs_path($_[1]) },
- "c|config=s" => \$ENV{MR_CONFIG },
+ "c|config=s" => sub { $ENV{MR_CONFIG}=$_[1]; $config_overridden=1 },
"v|verbose" => \$verbose,
"s|stats" => \$stats,
"n|no-recurse" => \$no_recurse,
"v|verbose" => \$verbose,
"s|stats" => \$stats,
"n|no-recurse" => \$no_recurse,
+# commands that do not operate on all repos
if ($action eq 'help') {
exec($config{''}{DEFAULT}{$action}) || die "exec: $!";
}
if ($action eq 'help') {
exec($config{''}{DEFAULT}{$action}) || die "exec: $!";
}
exists $config{$topdir}{$section}{$_}) {
print $config{$topdir}{$section}{$_}."\n";
$found=1;
exists $config{$topdir}{$section}{$_}) {
print $config{$topdir}{$section}{$_}."\n";
$found=1;
+ last if $section eq 'DEFAULT';
exit 0;
}
elsif ($action eq 'register') {
exit 0;
}
elsif ($action eq 'register') {
+ if (! $config_overridden) {
+ # Find the closest known mrconfig file to the current
+ # directory.
+ $directory.="/" unless $directory=~/\/$/;
+ foreach my $topdir (reverse sort keys %config) {
+ next unless length $topdir;
+ if ($directory=~/^\Q$topdir\E/) {
+ $ENV{MR_CONFIG}=$configfiles{$topdir};
+ last;
+ }
+ }
+ }
my $command="set -e; ".$config{''}{DEFAULT}{lib}."\n".
"my_action(){ $config{''}{DEFAULT}{$action}\n }; my_action ".
join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
my $command="set -e; ".$config{''}{DEFAULT}{lib}."\n".
"my_action(){ $config{''}{DEFAULT}{$action}\n }; my_action ".
join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
my $lib=exists $config{$topdir}{$subdir}{lib} ?
$config{$topdir}{$subdir}{lib}."\n" : "";
my $lib=exists $config{$topdir}{$subdir}{lib} ?
$config{$topdir}{$subdir}{lib}."\n" : "";
- if (exists $config{$topdir}{$subdir}{deleted}) {
- my $test="set -e;".$lib.$config{$topdir}{$subdir}{deleted};
- print "mr $action: running deleted test >>$test<<\n" if $verbose;
- my $ret=system($test);
- if ($ret != 0) {
- if (($? & 127) == 2) {
- print STDERR "mr $action: interrupted\n";
- exit 2;
- }
- elsif ($? & 127) {
- print STDERR "mr $action: deleted test received signal ".($? & 127)."\n";
- }
- }
- if ($ret >> 8 == 0) {
- if (-d $dir) {
- print STDERR "mr error: $dir should be deleted yet still exists\n\n";
- push @failed, $dir;
- return;
- }
- else {
- print "mr $action: $dir skipped (as deleted) per config file\n" if $verbose;
- push @skipped, $dir;
- return;
- }
- }
- }
-
if ($action eq 'checkout') {
if (-d $dir) {
print "mr $action: $dir already exists, skipping checkout\n" if $verbose;
if ($action eq 'checkout') {
if (-d $dir) {
print "mr $action: $dir already exists, skipping checkout\n" if $verbose;
$dir=".";
}
$dir=abs_path($dir)."/";
$dir=".";
}
$dir=abs_path($dir)."/";
+
+ if (! exists $configfiles{$dir}) {
+ $configfiles{$dir}=$f;
+ }
# copy in defaults from first parent
my $parent=$dir;
# copy in defaults from first parent
my $parent=$dir;
else {
$config{$dir}{$section}{$parameter}=$value;
$knownactions{$parameter}=1;
else {
$config{$dir}{$section}{$parameter}=$value;
$knownactions{$parameter}=1;
- if (! exists $configfiles{$dir}) {
- $configfiles{$dir}=abs_path($f);
- }
if ($parameter eq 'chain' &&
length $dir && $section ne "DEFAULT" &&
-e $dir.$section."/.mrconfig") {
if ($parameter eq 'chain' &&
length $dir && $section ne "DEFAULT" &&
-e $dir.$section."/.mrconfig") {
- for dir in .git .svn .bzr CVS; do
+ for dir in .git .svn .bzr CVS .hg ; do
if [ -e "$MR_REPO/$dir" ]; then
flagfile="$MR_REPO/$dir/.mr_last$1"
break
if [ -e "$MR_REPO/$dir" ]; then
flagfile="$MR_REPO/$dir/.mr_last$1"
break
if [ -d "$MR_REPO"/.svn ]; then
svn update "$@"
elif [ -d "$MR_REPO"/.git ]; then
if [ -d "$MR_REPO"/.svn ]; then
svn update "$@"
elif [ -d "$MR_REPO"/.git ]; then
- git pull origin master "$@"
+ if [ -z "$@" ]; then
+ git pull -t origin master
+ else
+ git pull "$@"
+ fi
elif [ -d "$MR_REPO"/.bzr ]; then
bzr merge "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs update "$@"
elif [ -d "$MR_REPO"/.bzr ]; then
bzr merge "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs update "$@"
+ elif [ -d "$MR_REPO"/.hg ]; then
+ hg pull "$@" && hg update "$@"
else
error "unknown repo type"
fi
else
error "unknown repo type"
fi
bzr status "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs status "$@"
bzr status "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs status "$@"
+ elif [ -d "$MR_REPO"/.hg ]; then
+ hg status "$@"
else
error "unknown repo type"
fi
else
error "unknown repo type"
fi
bzr commit "$@" && bzr push
elif [ -d "$MR_REPO"/CVS ]; then
cvs commit "$@"
bzr commit "$@" && bzr push
elif [ -d "$MR_REPO"/CVS ]; then
cvs commit "$@"
+ elif [ -d "$MR_REPO"/.hg ]; then
+ hg commit -m "$@" && hg push
else
error "unknown repo type"
fi
else
error "unknown repo type"
fi
bzr diff "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs diff "$@"
bzr diff "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs diff "$@"
+ elif [ -d "$MR_REPO"/.hg ]; then
+ hg diff "$@"
else
error "unknown repo type"
fi
else
error "unknown repo type"
fi
bzr log "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs log "$@"
bzr log "$@"
elif [ -d "$MR_REPO"/CVS ]; then
cvs log "$@"
+ elif [ -d "$MR_REPO"/.hg ]; then
+ hg log "$@"
else
error "unknown repo type"
fi
else
error "unknown repo type"
fi
echo "Registering cvs repository $repo at root $root"
mr -c "$MR_CONFIG" config "$(pwd)" \
checkout="cvs -d '$root' co -d $basedir $repo"
echo "Registering cvs repository $repo at root $root"
mr -c "$MR_CONFIG" config "$(pwd)" \
checkout="cvs -d '$root' co -d $basedir $repo"
+ elif [ -d .hg ]; then
+ url=$(hg showconfig paths.default)
+ echo "Registering mercurial repo url: $url in $MR_CONFIG"
+ mr -c "$MR_CONFIG" config "$(pwd)" \
+ checkout="hg clone $url $basedir"
else
error "unable to register this repo type"
fi
else
error "unable to register this repo type"
fi