X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/d11b6a1b817dbbd24774f158de8e4351b82bfae0..42e5ed9236d5417f5827df3648e72f8e7ffe5b95:/mr?ds=sidebyside

diff --git a/mr b/mr
index 1253102..494e89b 100755
--- a/mr
+++ b/mr
@@ -209,7 +209,11 @@ directory, since the repository isn't checked out yet. All other commands
 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. The "MR_CONFIG" environment variable is set to the .mrconfig file
+repository. (For the "register" action, "MR_REPO" is instead set to the 
+basename of the directory that should be created when checking the
+repository out.)
+
+The "MR_CONFIG" environment variable is set to the .mrconfig file
 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 repo.
 
@@ -247,6 +251,15 @@ If the "chain" parameter is set and its command returns true, then B<mr>
 will try to load a .mrconfig file from the root of the repository. (You
 should avoid chaining from repositories with untrusted committers.)
 
+=item include
+
+If the "include" parameter is set, its command is ran, and should output
+additional mrconfig file content. The content is included as if it were
+part of the including file.
+
+Unlike all other parameters, this parameter does not need to be placed
+within a section.
+
 =item lib
 
 The "lib" parameter can specify some shell code that will be run before each
@@ -255,6 +268,18 @@ to use.
 
 =back
 
+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 revision control
+system is itself determined by running each defined "rcs_test" action,
+until one succeeds.
+
+Internally, mr has settings for "git_update", "svn_update", etc. To change
+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 AUTHOR
 
 Copyright 2007 Joey Hess <joey@kitenet.net>
@@ -402,14 +427,29 @@ elsif ($action eq 'register') {
 			next unless length $topdir;
 			if ($directory=~/^\Q$topdir\E/) {
 				$ENV{MR_CONFIG}=$configfiles{$topdir};
+				$directory=$topdir;
 				last;
 			}
 		}
 	}
-	my $command="set -e; ".$config{''}{DEFAULT}{lib}."\n".
-		"my_action(){ $config{''}{DEFAULT}{$action}\n }; my_action ".
+	if (@ARGV) {
+		my $subdir=shift @ARGV;
+		if (! chdir($subdir)) {
+			print STDERR "mr $action: failed to chdir to $subdir: $!\n";
+		}
+	}
+
+	$ENV{MR_REPO}=getcwd();
+	my $command=findcommand("register", $ENV{MR_REPO}, $directory, 'DEFAULT');
+	if (! defined $command) {
+		die "mr $action: unknown repository type\n";
+	}
+
+	$ENV{MR_REPO}=~s/.*\/(.*)/$1/;
+	$command="set -e; ".$config{$directory}{DEFAULT}{lib}."\n".
+		"my_action(){ $command\n }; my_action ".
 		join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
-	print STDERR "mr $action: running >>$command<<\n" if $verbose;
+	print "mr $action: running >>$command<<\n" if $verbose;
 	exec($command) || die "exec: $!";
 }
 
@@ -501,6 +541,52 @@ elsif (! @ok && @skipped) {
 }
 exit 0;
 
+sub rcs_test { #{{{
+	my ($action, $dir, $topdir, $subdir) = @_;
+
+	my $test="set -e\n";
+	foreach my $rcs_test (
+			sort {
+				length $a <=> length $b 
+				          ||
+				       $a cmp $b
+			} grep { /_test$/ } keys %{$config{$topdir}{$subdir}}) {
+		my ($rcs)=$rcs_test=~/(.*)_test/;
+		$test="my_$rcs_test() {\n$config{$topdir}{$subdir}{$rcs_test}\n}\n".$test;
+		$test.="if my_$rcs_test; then echo $rcs; fi\n";
+	}
+	$test=$config{$topdir}{$subdir}{lib}."\n".$test
+		if exists $config{$topdir}{$subdir}{lib};
+	
+	print "mr $action: running rcs test >>$test<<\n" if $verbose;
+	my $rcs=`$test`;
+	chomp $rcs;
+	if (! length $rcs) {
+		return undef;
+	}
+	else {
+		return $rcs;
+	}
+} #}}}
+	
+sub findcommand { #{{{
+	my ($action, $dir, $topdir, $subdir) = @_;
+	
+	if (exists $config{$topdir}{$subdir}{$action}) {
+		return $config{$topdir}{$subdir}{$action};
+	}
+
+	my $rcs=rcs_test(@_);
+
+	if (defined $rcs && 
+	    exists $config{$topdir}{$subdir}{$rcs."_".$action}) {
+		return $config{$topdir}{$subdir}{$rcs."_".$action};
+	}
+	else {
+		return undef;
+	}
+} #}}}
+
 sub action { #{{{
 	my ($action, $dir, $topdir, $subdir) = @_;
 
@@ -526,12 +612,15 @@ sub action { #{{{
 			return action("checkout", $dir, $topdir, $subdir);
 		}
 	}
-	
+
 	$ENV{MR_REPO}=$dir;
 
-	if (exists $config{$topdir}{$subdir}{skip}) {
+	my $skiptest=findcommand("skip", $dir, $topdir, $subdir);
+	my $command=findcommand($action, $dir, $topdir, $subdir);
+
+	if (defined $skiptest) {
 		my $test="set -e;".$lib.
-			"my_action(){ $config{$topdir}{$subdir}{skip}\n }; my_action '$action'";
+			"my_action(){ $skiptest\n }; my_action '$action'";
 		print "mr $action: running skip test >>$test<<\n" if $verbose;
 		my $ret=system($test);
 		if ($ret != 0) {
@@ -554,9 +643,16 @@ sub action { #{{{
 		print STDERR "mr $action: failed to chdir to $dir: $!\n";
 		return FAILED;
 	}
-	elsif (! exists $config{$topdir}{$subdir}{$action}) {
-		print STDERR "mr $action: no defined $action command for $topdir$subdir, skipping\n";
-		return SKIPPED;
+	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";
+			return FAILED;
+		}
+		else {
+			print STDERR "mr $action: no defined $action command for $rcs repository $topdir$subdir, skipping\n";
+			return SKIPPED;
+		}
 	}
 	else {
 		if (! $nochdir) {
@@ -567,10 +663,10 @@ sub action { #{{{
 			$s=~s/^\Q$topdir$subdir\E\/?//;
 			print "mr $action: $topdir$subdir (in subdir $s)\n";
 		}
-		my $command="set -e; ".$lib.
-			"my_action(){ $config{$topdir}{$subdir}{$action}\n }; my_action ".
+		$command="set -e; ".$lib.
+			"my_action(){ $command\n }; my_action ".
 			join(" ", map { s/\//\/\//g; s/"/\"/g; '"'.$_.'"' } @ARGV);
-		print STDERR "mr $action: running >>$command<<\n" if $verbose;
+		print "mr $action: running >>$command<<\n" if $verbose;
 		my $ret=system($command);
 		if ($ret != 0) {
 			if (($? & 127) == 2) {
@@ -775,6 +871,12 @@ sub loadconfig { #{{{
 				chomp $value;
 			}
 
+			if ($parameter eq "include") {
+				print "mr: including output of \"$value\"\n" if $verbose;
+				unshift @lines, `$value`;
+				next;
+			}
+
 			if (! defined $section) {
 				die "$f line $.: parameter ($parameter) not in section\n";
 			}
@@ -792,7 +894,12 @@ sub loadconfig { #{{{
 			}
 			else {
 				$config{$dir}{$section}{$parameter}=$value;
-				$knownactions{$parameter}=1;
+				if ($parameter =~ /.*_(.*)/) {
+					$knownactions{$1}=1;
+				}
+				else {
+					$knownactions{$parameter}=1;
+				}
 				if ($parameter eq 'chain' &&
 				    length $dir && $section ne "DEFAULT" &&
 				    -e $dir.$section."/.mrconfig") {
@@ -935,6 +1042,12 @@ lib =
 		echo "mr: $@" >&2
 		exit 1
 	}
+	warning() {
+		echo "mr (warning): $@" >&2
+	}
+	info() {
+		echo "mr: $@" >&2
+	}
 	hours_since() {
 		if [ -z "$1" ] || [ -z "$2" ]; then
 			error "mr: usage: hours_since action num"
@@ -957,138 +1070,98 @@ lib =
 		fi
 	}
 
-update =
-	if [ -d "$MR_REPO"/.svn ]; then
-		svn update "$@"
-	elif [ -d "$MR_REPO"/.git ]; then
-		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"/.hg ]; then
-		hg pull "$@" && hg update "$@"
-	elif [ -d "$MR_REPO"/_darcs ]; then
-		darcs pull -a "$@"
-	else
-		error "unknown repo type"
-	fi
-status =
-	if [ -d "$MR_REPO"/.svn ]; then
-		svn status "$@"
-	elif [ -d "$MR_REPO"/.git ]; then
-		git status "$@" || true
-	elif [ -d "$MR_REPO"/.bzr ]; then
-		bzr status "$@"
-	elif [ -d "$MR_REPO"/CVS ]; then
-		cvs status "$@"
-	elif [ -d "$MR_REPO"/.hg ]; then
-		hg status "$@"
-	elif [ -d "$MR_REPO"/_darcs ]; then
-		darcs whatsnew -ls "$@"
-	else
-		error "unknown repo type"
-	fi
-commit =
-	if [ -d "$MR_REPO"/.svn ]; then
-		svn commit "$@"
-	elif [ -d "$MR_REPO"/.git ]; then
-		git commit -a "$@" && git push --all
-	elif [ -d "$MR_REPO"/.bzr ]; then
-		bzr commit "$@" && bzr push
-	elif [ -d "$MR_REPO"/CVS ]; then
-		cvs commit "$@"
-	elif [ -d "$MR_REPO"/.hg ]; then
-		hg commit -m "$@" && hg push
-	elif [ -d "$MR_REPO"/_darcs ]; then
-		darcs commit -a -m "$@" && darcs push -a
-	else
-		error "unknown repo type"
+svn_test = test -d "$MR_REPO"/.svn
+git_test = test -d "$MR_REPO"/.git
+bzr_test = test -d "$MR_REPO"/.bzr
+cvs_test = test -d "$MR_REPO"/CVS
+hg_test  = test -d "$MR_REPO"/.hg
+darcs_test = test -d "$MR_REPO"/_darcs
+git_bare_test =
+	test -d "$MR_REPO"/refs/heads && test -d "$MR_REPO"/refs/tags &&
+	test -d "$MR_REPO"/objects && test -f "$MR_REPO"/config &&
+	test "$(GIT_CONFIG="$MR_REPO"/config git-config --get core.bare)" = true
+
+svn_update = svn update "$@"
+git_update = if [ "$@" ]; then git pull "$@"; else git pull -t origin master; fi
+bzr_update = bzr merge "$@"
+cvs_update = cvs update "$@"
+hg_update  = hg pull "$@" && hg update "$@"
+darcs_update = darcs pull -a "$@"
+
+svn_status = svn status "$@"
+git_status = git status "$@" || true
+bzr_status = bzr status "$@"
+cvs_status = cvs status "$@"
+hg_status  = hg status "$@"
+darcs_status = darcs whatsnew -ls "$@"
+
+svn_commit = svn commit "$@"
+git_commit = git commit -a "$@" && git push --all
+bzr_commit = bzr commit "$@" && bzr push
+cvs_commit = cvs commit "$@"
+hg_commit  = hg commit -m "$@" && hg push
+darcs_commit = darcs commit -a -m "$@" && darcs push -a
+
+svn_diff = svn diff "$@"
+git_diff = git diff "$@"
+bzr_diff = bzr diff "$@"
+cvs_diff = cvs diff "$@"
+hg_diff  = hg diff "$@"
+darcs_diff = darcs diff "$@"
+
+svn_log = svn log "$@"
+git_log = git log "$@"
+bzr_log = bzr log "$@"
+cvs_log = cvs log "$@"
+hg_log  = hg log "$@"
+darcs_log = darcs changes "$@"
+git_bare_log = git log "$@"
+
+svn_register =
+	url=$(LANG=C svn info . | grep -i ^URL: | cut -d ' ' -f 2)
+	if [ -z "$url" ]; then
+		error "cannot determine svn url"
 	fi
-diff =
-	if [ -d "$MR_REPO"/.svn ]; then
-		svn diff "$@"
-	elif [ -d "$MR_REPO"/.git ]; then
-		git diff "$@"
-	elif [ -d "$MR_REPO"/.bzr ]; then
-		bzr diff "$@"
-	elif [ -d "$MR_REPO"/CVS ]; then
-		cvs diff "$@"
-	elif [ -d "$MR_REPO"/.hg ]; then
-		hg diff "$@"
-	elif [ -d "$MR_REPO"/_darcs ]; then
-		darcs diff "$@"
-	else
-		error "unknown repo type"
+	echo "Registering svn url: $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="svn co '$url' '$MR_REPO'"
+git_register = 
+	url="$(LANG=C git-config --get remote.origin.url)" || true
+	if [ -z "$url" ]; then
+		error "cannot determine git url"
 	fi
-log =
-	if [ -d "$MR_REPO"/.svn ]; then
-		svn log"$@"
-	elif [ -d "$MR_REPO"/.git ]; then
-		git log "$@"
-	elif [ -d "$MR_REPO"/.bzr ]; then
-		bzr log "$@"
-	elif [ -d "$MR_REPO"/CVS ]; then
-		cvs log "$@"
-	elif [ -d "$MR_REPO"/.hg ]; then
-		hg log "$@"
-	elif [ -d "$MR_REPO"/_darcs ]; then
-		darcs changes "$@"
-	else
-		error "unknown repo type"
+	echo "Registering git url: $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="git clone '$url' '$MR_REPO'"
+bzr_register =
+	url=$(cat .bzr/branch/parent)
+	if [ -z "$url" ]; then
+		error "cannot determine bzr url"
 	fi
-register =
-	if [ -n "$1" ]; then
-		cd "$1"
-	fi
-	basedir="$(basename $(pwd))"
-	if [ -d .svn ]; then
-		url=$(LANG=C svn info . | grep -i ^URL: | cut -d ' ' -f 2)
-		if [ -z "$url" ]; then
-			error "cannot determine svn url"
-		fi
-		echo "Registering svn url: $url in $MR_CONFIG"
-		mr -c "$MR_CONFIG" config "$(pwd)" checkout="svn co $url $basedir"
-	elif [ -d .git ]; then
-		url=$(LANG=C git-config --get remote.origin.url)
-		if [ -z "$url" ]; then
-			error "cannot determine git url"
-		fi
-		echo "Registering git url: $url in $MR_CONFIG"
-		mr -c "$MR_CONFIG" config "$(pwd)" checkout="git clone $url $basedir"
-	elif [ -d .bzr ]; then
-		url=$(cat .bzr/branch/parent)
-		if [ -z "$url" ]; then
-			error "cannot determine bzr url"
+	echo "Registering bzr url: $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="bzr clone '$url' '$MR_REPO'"
+cvs_register =
+	repo=$(cat CVS/Repository)
+	root=$(cat CVS/Root)
+	if [ -z "$root" ]; then
+		error "cannot determine cvs root"
 		fi
-		echo "Registering bzr url: $url in $MR_CONFIG"
-		mr -c "$MR_CONFIG" config "$(pwd)" checkout="bzr clone $url $basedir"
-	elif [ -d CVS ]; then
-		repo=$(cat CVS/Repository)
-		root=$(cat CVS/Root)
-		if [ -z "$root" ]; then
-			error "cannot determine cvs root"
-		fi
-		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"
-	elif [ -d _darcs ]; then
-		url=$(cat _darcs/prefs/defaultrepo)
-		echo "Registering darcs repository $url in $MR_CONFIG"
-		mr -c "$MR_CONFIG" config "$(pwd)" \
-			checkout="darcs get $url $basedir"
-	else
-		error "unable to register this repo type"
+	echo "Registering cvs repository $repo at root $root"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="cvs -d '$root' co -d '$MR_REPO' '$repo'"
+hg_register = 
+	url=$(hg showconfig paths.default)
+	echo "Registering mercurial repo url: $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="hg clone '$url' '$MR_REPO'"
+darcs_register = 
+	url=$(cat _darcs/prefs/defaultrepo)
+	echo "Registering darcs repository $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="darcs get '$url'p '$MR_REPO'"
+git_bare_register = 
+	url="$(LANG=C GIT_CONFIG=config git-config --get remote.origin.url)" || true
+	if [ -z "$url" ]; then
+		error "cannot determine git url"
 	fi
+	echo "Registering git url: $url in $MR_CONFIG"
+	mr -c "$MR_CONFIG" config "`pwd`" checkout="git clone --bare '$url' '$MR_REPO'"
+
 help =
 	if [ ! -e "$MR_PATH" ]; then
 		error "cannot find program path"
@@ -1101,3 +1174,5 @@ 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