X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/d80a044816be0037e3243bf4e4949461d73b1097..19b4e0426d12b36770810e502be86ff2ec1aa6f0:/mr?ds=sidebyside diff --git a/mr b/mr index bdc9ff6..b606736 100755 --- a/mr +++ b/mr @@ -1,8 +1,8 @@ -#!/usr/bin/perl +#!/usr/bin/env perl =head1 NAME -mr - a Multiple Repository management tool +mr - a tool to manage all your version control repos =head1 SYNOPSIS @@ -24,9 +24,11 @@ B [options] diff B [options] log +B [options] grep pattern + B [options] run command [param ...] -B [options] bootstrap url [directory] +B [options] bootstrap src [directory] B [options] register [repository] @@ -40,11 +42,11 @@ B [options] remember action [params ...] =head1 DESCRIPTION -B 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 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 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 @@ -75,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) @@ -112,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. @@ -122,17 +130,34 @@ These commands are also available: =over 4 -=item bootstrap url [directory] +=item bootstrap src [directory] + +Causes mr to retrieve the source C and use it as a .mrconfig file to +checkout the repositories listed in it, into the specified directory. + +B understands several types of sources: + +=over 4 + +=item URL for curl + +C may be an URL understood by B. + +=item copy via ssh + +To use B to download, the C may have the form +C. + +=item local file -Causes mr to download the url, and use it as a .mrconfig file to checkout -the repositories listed in it, into the specified directory. +You can retrieve the config file by other means and pass its B as C. -To use scp to download, the url may have the form ssh://[user@]host:file +=back The directory will be created if it does not exist. If no directory is specified, the current directory will be used. -If the .mrconfig file includes a repository named ".", that +As a special case, if source C includes a repository named ".", that is checked out into the top of the specified directory. =item list (or ls) @@ -518,7 +543,7 @@ Copyright 2007-2011 Joey Hess Licensed under the GNU GPL version 2 or higher. -http://kitenet.net/~joey/code/mr/ +http://myrepos.branchable.com/ =cut @@ -1317,11 +1342,12 @@ sub loadconfig { while (@lines) { $_=$nextline->(); + next if /^\s*\#/ || /^\s*$/; + if (! $trusted && /[[:cntrl:]]/) { $trusterror->("illegal control character"); } - next if /^\s*\#/ || /^\s*$/; if (/^\[([^\]]*)\]\s*$/) { $section=$1; @@ -1660,30 +1686,43 @@ sub register { } sub bootstrap { + eval q{use File::Copy}; + die $@ if $@; + my $url=shift @ARGV; my $dir=shift @ARGV || "."; if (! defined $url || ! length $url) { - die "mr: bootstrap requires url\n"; + die "mr: bootstrap requires source\n"; } - - # Download the config file to a temporary location. + + # Retrieve config file. eval q{use File::Temp}; die $@ if $@; my $tmpconfig=File::Temp->new(); - my @downloader; - if ($url =~ m!^ssh://(.*)!) { - @downloader = ("scp", $1, $tmpconfig); + if ($url =~ m!^[\w\d]+://!) { + # Download the config file to a temporary location. + 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; } else { - @downloader = ("curl", "-A", "mr", "-L", "-s", $url, "-o", $tmpconfig); - push(@downloader, "-k") if $insecure; + # Config file is local. + die "mr bootstrap: cannot read file '$url'" + unless -r $url; + copy($url, $tmpconfig) || die "copy: $!"; } - 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; + # Sanity check on destination directory. if (! -e $dir) { system("mkdir", "-p", $dir); } @@ -1701,8 +1740,6 @@ sub bootstrap { print STDERR "mr bootstrap: .mrconfig file already exists, not overwriting with $url\n"; } else { - eval q{use File::Copy}; - die $@ if $@; move($tmpconfig, ".mrconfig") || die "rename: $!"; } @@ -1920,10 +1957,10 @@ 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 @@ -1938,11 +1975,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 "$@" vcsh_commit = vcsh run "$MR_REPO" git commit -a "$@" && vcsh run "$MR_REPO" git push --all -veracity_commit = vv commit -m "@" && vv push +veracity_commit = vv commit "$@" && vv push git_record = git commit -a "$@" bzr_record = @@ -1951,11 +1988,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 "$@" vcsh_record = vcsh run "$MR_REPO" git commit -a "$@" -veracity_record = vv commit -m "@" +veracity_record = vv commit "$@" svn_push = : git_push = git push "$@" @@ -2081,7 +2118,7 @@ help = SHOWMANFILE="man" ;; *) - SHOWMANFILE="man -l" + SHOWMANFILE="man" ;; esac if [ ! -e "$MR_PATH" ]; then