X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/1f9664072eba6ade88350eb595e67520993b8fd9..e4b24259cc55b2b8a840b194b7df3c4ed99ba579:/mr?ds=sidebyside

diff --git a/mr b/mr
index 58ebceb..5025e6e 100755
--- a/mr
+++ b/mr
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-mr - a Multiple Repository management tool
+mr - a tool to manage all your version control repos
 
 =head1 SYNOPSIS
 
@@ -16,12 +16,16 @@ B<mr> [options] commit [-m "message"]
 
 B<mr> [options] record [-m "message"]
 
+B<mr> [options] fetch
+
 B<mr> [options] push
 
 B<mr> [options] diff
 
 B<mr> [options] log
 
+B<mr> [options] grep pattern
+
 B<mr> [options] run command [param ...]
 
 B<mr> [options] bootstrap url [directory]
@@ -38,11 +42,11 @@ B<mr> [options] remember 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
-repository. It supports any combination of subversion, git, cvs, mercurial,
-bzr, darcs, fossil and veracity repositories, and support for other version
-control systems can easily be added.
+B<mr> is a tool to manage all your version control repos. 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, fossil and veracity repositories, and support
+for other version 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
@@ -73,7 +77,8 @@ If a repository isn't checked out yet, it will first check it out.
 =item status
 
 Displays a status report for each repository, showing what
-uncommitted changes are present in the repository.
+uncommitted changes are present in the repository. For distributed version
+control systems, also shows unpushed local branches.
 
 =item commit (or ci)
 
@@ -91,6 +96,12 @@ remote repository. Only supported for distributed version control systems.
 
 The optional -m parameter allows specifying a commit message.
 
+=item fetch
+
+Fetches from each repository's remote repository, but does not
+update the working copy. Only supported for some distributed version
+control systems.
+
 =item push
 
 Pushes committed local changes to the remote repository. A no-op for
@@ -104,6 +115,11 @@ Show a diff of uncommitted changes.
 
 Show the commit log.
 
+=item grep pattern
+
+Searches for a pattern in each repository using the grep subcommand. Uses
+ack-grep on VCS that do not have their own.
+
 =item run command [param ...]
 
 Runs the specified command in each repository.
@@ -116,8 +132,10 @@ These commands are also available:
 
 =item bootstrap url [directory]
 
-Causes mr to download the url, and use it as a .mrconfig file
-to checkout the repositories listed in it, into the specified directory.
+Causes mr to download the url, and use it as a .mrconfig file to checkout
+the repositories listed in it, into the specified directory.
+
+To use scp to download, the url may have the form ssh://[user@]host:file
 
 The directory will be created if it does not exist. If no directory is
 specified, the current directory will be used.
@@ -405,7 +423,7 @@ Unlike all other parameters, this parameter does not need to be placed
 within a section.
 
 B<mr> ships several libraries that can be included to add support for
-additional version control type things (unison, git-svn, vcsh, git-fake-bare,
+additional version control type things (unison, git-svn, git-fake-bare,
 git-subtree). To include them all, you could use:
 
   include = cat /usr/share/mr/*
@@ -684,6 +702,7 @@ sub fulldir {
 sub action {
 	my ($action, $dir, $topdir, $subdir, $force_checkout) = @_;
 	my $fulldir=fulldir($topdir, $subdir);
+	my $checkout_dir;
 
 	$ENV{MR_CONFIG}=$configfiles{$topdir};
 	my $is_checkout=($action eq 'checkout');
@@ -725,6 +744,7 @@ sub action {
 	}
 
 	if ($is_checkout) {
+		$checkout_dir=$dir;
 		if (! $force_checkout) {
 			if (-d $dir) {
 				print "mr $action: $dir already exists, skipping checkout\n" if $verbose;
@@ -828,7 +848,13 @@ sub action {
 			my $ret=hook("post_$action", $topdir, $subdir);
 			return $ret if $ret != OK;
 			
-			if (($is_checkout || $is_update)) {
+			if ($is_checkout || $is_update) {
+				if ($is_checkout && ! $no_chdir) {
+					if (! chdir($checkout_dir)) {
+				                print STDERR "mr $action: failed to chdir to $checkout_dir: $!\n";
+						return FAILED;
+					}
+				}
 				my $ret=hook("fixups", $topdir, $subdir);
 				return $ret if $ret != OK;
 			}
@@ -1653,11 +1679,18 @@ sub bootstrap {
 	eval q{use File::Temp};
 	die $@ if $@;
 	my $tmpconfig=File::Temp->new();
-	my @curlargs = ("curl", "-A", "mr", "-L", "-s", $url, "-o", $tmpconfig);
-	push(@curlargs, "-k") if $insecure;
-	my $curlstatus = system(@curlargs);
-	die "mr bootstrap: invalid SSL certificate for $url (consider -k)\n" if $curlstatus >> 8 == 60;
-	die "mr bootstrap: download of $url failed\n" if $curlstatus != 0;
+	my @downloader;
+	if ($url =~ m!^ssh://(.*)!) {
+		@downloader = ("scp", $1, $tmpconfig);
+	}
+	else {
+		@downloader = ("curl", "-A", "mr", "-L", "-s", $url, "-o", $tmpconfig);
+		push(@downloader, "-k") if $insecure;
+	}
+	my $status = system(@downloader);
+	die "mr bootstrap: invalid SSL certificate for $url (consider -k)\n"
+		if $downloader[0] eq 'curl' && $status >> 8 == 60;
+	die "mr bootstrap: download of $url failed\n" if $status != 0;
 
 	if (! -e $dir) {
 		system("mkdir", "-p", $dir);
@@ -1858,7 +1891,7 @@ lib =
 	}
 
 svn_test = perl: -d "$ENV{MR_REPO}/.svn"
-git_test = perl: -d "$ENV{MR_REPO}/.git"
+git_test = perl: -e "$ENV{MR_REPO}/.git"
 bzr_test = perl: -d "$ENV{MR_REPO}/.bzr"
 cvs_test = perl: -d "$ENV{MR_REPO}/CVS"
 hg_test  = perl: -d "$ENV{MR_REPO}/.hg"
@@ -1868,6 +1901,10 @@ git_bare_test = perl:
 	-d "$ENV{MR_REPO}/refs/heads" && -d "$ENV{MR_REPO}/refs/tags" &&
 	-d "$ENV{MR_REPO}/objects" && -f "$ENV{MR_REPO}/config" &&
 	`GIT_CONFIG="$ENV{MR_REPO}"/config git config --get core.bare` =~ /true/
+vcsh_test = perl:
+	-d "$ENV{MR_REPO}/refs/heads" && -d "$ENV{MR_REPO}/refs/tags" &&
+	-d "$ENV{MR_REPO}/objects" && -f "$ENV{MR_REPO}/config" &&
+	`GIT_CONFIG="$ENV{MR_REPO}"/config git config --get vcsh.vcsh` =~ /true/
 veracity_test  = perl: -d "$ENV{MR_REPO}/.sgdrawer"
 
 svn_update = svn update "$@"
@@ -1878,19 +1915,26 @@ bzr_update =
 	else
 		bzr merge --pull "$@"
 	fi
-cvs_update = cvs update "$@"
-hg_update  = hg pull "$@" && hg update "$@"
+cvs_update = cvs -q update "$@"
+hg_update  = hg pull "$@"; hg update "$@"
 darcs_update = darcs pull -a "$@"
 fossil_update = fossil pull "$@"
+vcsh_update = vcsh run "$MR_REPO" git pull "$@"
 veracity_update = vv pull "$@" && vv update "$@"
 
+git_fetch = git fetch --all --prune --tags
+git_svn_fetch = git svn fetch
+darcs_fetch = darcs fetch
+hg_fetch = hg pull
+
 svn_status = svn status "$@"
-git_status = git status -s "$@" || true
-bzr_status = bzr status --short "$@"
-cvs_status = cvs status "$@"
-hg_status  = hg status "$@"
+git_status = git status -s "$@" || true; git --no-pager log --branches --not --remotes --simplify-by-decoration --decorate --oneline || true
+bzr_status = bzr status --short "$@"; bzr missing
+cvs_status = cvs -q status | grep -E '^(File:.*Status:|\?)' | grep -v 'Status: Up-to-date'
+hg_status  = hg status "$@"; hg summary --quiet | grep -v 'parent: 0:'
 darcs_status = darcs whatsnew -ls "$@" || true
 fossil_status = fossil changes "$@"
+vcsh_status = vcsh run "$MR_REPO" git -c status.relativePaths=false status -s "$@" || true
 veracity_status = vv status "$@"
 
 svn_commit = svn commit "$@"
@@ -1902,10 +1946,11 @@ bzr_commit =
 		bzr commit "$@" && bzr push
 	fi
 cvs_commit = cvs commit "$@"
-hg_commit  = hg commit -m "$@" && hg push
-darcs_commit = darcs record -a -m "$@" && darcs push -a
+hg_commit  = hg commit "$@" && hg push
+darcs_commit = darcs record -a "$@" && darcs push -a
 fossil_commit = fossil commit "$@"
-veracity_commit = vv commit -m "@" && vv push
+vcsh_commit = vcsh run "$MR_REPO" git commit -a "$@" && vcsh run "$MR_REPO" git push --all
+veracity_commit = vv commit "$@" && vv push
 
 git_record = git commit -a "$@"
 bzr_record =
@@ -1914,10 +1959,11 @@ bzr_record =
 	else
 		bzr commit "$@"
 	fi
-hg_record  = hg commit -m "$@"
-darcs_record = darcs record -a -m "$@"
+hg_record  = hg commit "$@"
+darcs_record = darcs record -a "$@"
 fossil_record = fossil commit "$@"
-veracity_record = vv commit -m "@"
+vcsh_record = vcsh run "$MR_REPO" git commit -a "$@"
+veracity_record = vv commit "$@"
 
 svn_push = :
 git_push = git push "$@"
@@ -1926,15 +1972,17 @@ cvs_push = :
 hg_push = hg push "$@"
 darcs_push = darcs push -a "$@"
 fossil_push = fossil push "$@"
+vcsh_push = vcsh run "$MR_REPO" git push "$@"
 veracity_push = vv push "$@"
 
 svn_diff = svn diff "$@"
 git_diff = git diff "$@"
 bzr_diff = bzr diff "$@"
-cvs_diff = cvs diff "$@"
+cvs_diff = cvs -q diff "$@"
 hg_diff  = hg diff "$@"
 darcs_diff = darcs diff -u "$@"
 fossil_diff = fossil diff "$@"
+vcsh_diff = vcsh run "$MR_REPO" git diff "$@"
 veracity_diff = vv diff "$@"
 
 svn_log = svn log "$@"
@@ -1945,8 +1993,16 @@ hg_log  = hg log "$@"
 darcs_log = darcs changes "$@"
 git_bare_log = git log "$@"
 fossil_log = fossil timeline "$@"
+vcsh_log = vcsh run "$MR_REPO" git log "$@"
 veracity_log = vv log "$@"
 
+hg_grep = hg grep "$@"
+cvs_grep = ack-grep "$@"
+svn_grep = ack-grep "$@"
+git_svn_grep = git grep "$@"
+git_grep = git grep "$@"
+bzr_grep = ack-grep "$@"
+
 run = "$@"
 
 svn_register =
@@ -1964,7 +2020,7 @@ git_register =
 	echo "Registering git url: $url in $MR_CONFIG"
 	mr -c "$MR_CONFIG" config "`pwd`" checkout="git clone '$url' '$MR_REPO'"
 bzr_register =
-	url="`LC_ALL=C bzr info . | egrep -i 'checkout of branch|parent branch' | awk '{print $NF}'`"
+	url="`LC_ALL=C bzr info . | egrep -i 'checkout of branch|parent branch' | awk '{print $NF}' | head -n 1`"
 	if [ -z "$url" ]; then
 		error "cannot determine bzr url"
 	fi
@@ -1993,6 +2049,13 @@ git_bare_register =
 	fi
 	echo "Registering git url: $url in $MR_CONFIG"
 	mr -c "$MR_CONFIG" config "`pwd`" checkout="git clone --bare '$url' '$MR_REPO'"
+vcsh_register =
+	url="`LC_ALL=C vcsh run "$MR_REPO" 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="vcsh clone '$url' '$MR_REPO'"
 fossil_register =
 	url=`fossil remote-url`
 	repo=`fossil info | grep repository | sed -e 's/repository:*.//g' -e 's/ //g'`
@@ -2012,6 +2075,7 @@ bzr_trusted_checkout = bzr checkout|clone|branch|get $url $repo
 hg_trusted_checkout = hg clone $url $repo
 darcs_trusted_checkout = darcs get $url $repo
 git_bare_trusted_checkout = git clone --bare $url $repo
+vcsh_trusted_checkout = vcsh run "$MR_REPO" git clone $url $repo
 # fossil: messy to do
 veracity_trusted_checkout = vv clone $url $repo
 
@@ -2025,7 +2089,7 @@ help =
 		SHOWMANFILE="man"
 		;;
 		*)
-		SHOWMANFILE="man -l"
+		SHOWMANFILE="man"
 		;;
 	esac
 	if [ ! -e "$MR_PATH" ]; then