X-Git-Url: https://git.madduck.net/code/myrepos.git/blobdiff_plain/c0d1030f9d352386676b91bab6fe6dab13a497d7..e28e10c4aed7a93ca1ec3f889a1580832efe1ab2:/mr diff --git a/mr b/mr index e89d01a..8408c61 100755 --- a/mr +++ b/mr @@ -41,7 +41,7 @@ B [options] remember action [params ...] 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 and fossil repositories, and support for other version +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 @@ -405,7 +405,7 @@ Unlike all other parameters, this parameter does not need to be placed within a section. B 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/* @@ -467,13 +467,6 @@ can be constructed accumulatively. The name of the version control system is itself determined by running each defined "VCS_test" action, until one succeeds. -=item VCS_dir_test - -This is a more optimised way to test for the version control system. -Each "VCS_dir_test" action is run once, and can output lines consisting -of the name of a VCS, and a directory to look for in the top of a repo -to detect that VCS. - =back =head1 UNTRUSTED MRCONFIG FILES @@ -546,6 +539,7 @@ my $jobs=1; my $trust_all=0; my $directory=getcwd(); +my $HOME_MR_CONFIG = "$ENV{HOME}/.mrconfig"; $ENV{MR_CONFIG}=find_mrconfig(); # globals :-( @@ -593,17 +587,22 @@ sub runsh { $runner->($shellcode); } -sub runshpipe { - runsh @_, sub { - my $sh=shift; - my $ret=`$sh`; - chomp $ret; - return $ret; - }; +my %perl_cache; +sub perl { + my $id=shift; + my $s=shift; + if ($s =~ m/^perl:\s+(.*)/s) { + return $perl_cache{$1} if exists $perl_cache{$1}; + my $sub=eval "sub {$1}"; + if (! defined $sub) { + print STDERR "mr: bad perl code in $id: $@\n"; + } + return $perl_cache{$1} = $sub; + } + return undef; } my %vcs; -my %vcs_dir_test; sub vcs_test { my ($action, $dir, $topdir, $subdir) = @_; @@ -612,53 +611,46 @@ sub vcs_test { } my $test=""; - my $dir_test=""; + my %perltest; foreach my $vcs_test ( sort { length $a <=> length $b || $a cmp $b } grep { /_test$/ } keys %{$config{$topdir}{$subdir}}) { - if ($vcs_test =~ /(.*)_dir_test/) { - my $vcs=$1; - if (! defined $vcs_dir_test{$vcs}) { - $dir_test.=$config{$topdir}{$subdir}{$vcs_test}."\n"; - } - next; + my ($vcs)=$vcs_test =~ /(.*)_test/; + my $p=perl($vcs_test, $config{$topdir}{$subdir}{$vcs_test}); + if (defined $p) { + $perltest{$vcs}=$p; } - my $vcs=$vcs_test =~ /(.*)_test/; - $test="my_$vcs_test() {\n$config{$topdir}{$subdir}{$vcs_test}\n}\n".$test; - $test.="if my_$vcs_test; then echo $vcs; fi\n"; - } - - if (length $dir_test) { - runsh "vcs dir test", $topdir, $subdir, $dir_test, [], sub { - my $sh=shift; - foreach my $line (`$sh`) { - chomp $line; - my ($vcs, $dir)=split(" ", $line); - $vcs_dir_test{$vcs}=$dir; - } + else { + $test="my_$vcs_test() {\n$config{$topdir}{$subdir}{$vcs_test}\n}\n".$test; + $test.="if my_$vcs_test; then echo $vcs; fi\n"; } } - foreach my $vcs (keys %vcs_dir_test) { - if (-d "$ENV{MR_REPO}/$vcs_dir_test{$vcs}") { - return $vcs{$dir}=$vcs; + my @vcs; + foreach my $vcs (keys %perltest) { + if ($perltest{$vcs}->()) { + push @vcs, $vcs; } } - my $vcs=runshpipe "vcs test", $topdir, $subdir, $test, []; - if ($vcs=~/\n/s) { - $vcs=~s/\n/, /g; - print STDERR "mr $action: found multiple possible repository types ($vcs) for ".fulldir($topdir, $subdir)."\n"; + push @vcs, split(/\n/, + runsh("vcs test", $topdir, $subdir, $test, [], sub { + my $sh=shift; + my $ret=`$sh`; + return $ret; + })) if length $test; + if (@vcs > 1) { + print STDERR "mr $action: found multiple possible repository types (@vcs) for ".fulldir($topdir, $subdir)."\n"; return undef; } - if (! length $vcs) { + if (! @vcs) { return $vcs{$dir}=undef; } else { - return $vcs{$dir}=$vcs; + return $vcs{$dir}=$vcs[0]; } } @@ -692,6 +684,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'); @@ -733,6 +726,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; @@ -836,7 +830,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; } @@ -1102,14 +1102,14 @@ sub is_trusted_config { my $config=shift; # must be abs_pathed already # We always trust ~/.mrconfig. - return 1 if $config eq abs_path("$ENV{HOME}/.mrconfig"); + return 1 if $config eq abs_path($HOME_MR_CONFIG); return 1 if $trust_all; my $trustfile=$ENV{HOME}."/.mrtrust"; if (! %trusted) { - $trusted{"$ENV{HOME}/.mrconfig"}=1; + $trusted{$HOME_MR_CONFIG}=1; if (open (TRUST, "<", $trustfile)) { while () { chomp; @@ -1292,15 +1292,14 @@ sub loadconfig { }; my $trusterror = sub { my $msg=shift; - my ($err, $file, $lineno, $url)=@_; if (defined $bootstrap_url) { - die "mr: $err in untrusted $bootstrap_url line $lineno\n". + die "mr: $msg in untrusted $bootstrap_url line $lineno\n". "(To trust this url, --trust-all can be used; but please use caution;\n". "this can allow arbitrary code execution!)\n"; } else { - die "mr: $err in untrusted $file line $lineno\n". + die "mr: $msg in untrusted $f line $lineno\n". "(To trust this file, list it in ~/.mrtrust.)\n"; } }; @@ -1732,7 +1731,7 @@ sub find_mrconfig { } $dir=~s/\/[^\/]*$//; } - return "$ENV{HOME}/.mrconfig"; + return $HOME_MR_CONFIG; } sub getopts { @@ -1802,7 +1801,7 @@ sub main { init(); startingconfig(); - loadconfig("$ENV{HOME}/.mrconfig"); + loadconfig($HOME_MR_CONFIG); loadconfig($ENV{MR_CONFIG}); #use Data::Dumper; print Dumper(\%config); @@ -1866,17 +1865,22 @@ lib = fi } -svn_dir_test = echo svn .svn -git_dir_test = echo git .git -bzr_dir_test = echo bzr .bzr -cvs_dir_test = echo cvs CVS -hg_dir_test = echo hg .hg -darcs_dir_test = echo darcs _darcs -fossil_test = test -f "$MR_REPO"/_FOSSIL_ -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_test = perl: -d "$ENV{MR_REPO}/.svn" +git_test = perl: -d "$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" +darcs_test = perl: -d "$ENV{MR_REPO}/_darcs" +fossil_test = perl: -f "$ENV{MR_REPO}/_FOSSIL_" +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 "$@" git_update = git pull "$@" @@ -1890,6 +1894,8 @@ cvs_update = cvs 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 "$@" svn_status = svn status "$@" git_status = git status -s "$@" || true @@ -1898,6 +1904,8 @@ cvs_status = cvs status "$@" hg_status = hg status "$@" darcs_status = darcs whatsnew -ls "$@" || true fossil_status = fossil changes "$@" +vcsh_status = cd $(vcsh run "$MR_REPO" git config --get core.worktree); vcsh run "$MR_REPO" git status -s "$@" || true +veracity_status = vv status "$@" svn_commit = svn commit "$@" git_commit = git commit -a "$@" && git push --all @@ -1911,6 +1919,8 @@ cvs_commit = cvs commit "$@" hg_commit = hg commit -m "$@" && hg push darcs_commit = darcs record -a -m "$@" && 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 git_record = git commit -a "$@" bzr_record = @@ -1922,6 +1932,8 @@ bzr_record = hg_record = hg commit -m "$@" darcs_record = darcs record -a -m "$@" fossil_record = fossil commit "$@" +vcsh_record = vcsh run "$MR_REPO" git commit -a "$@" +veracity_record = vv commit -m "@" svn_push = : git_push = git push "$@" @@ -1930,6 +1942,8 @@ 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 "$@" @@ -1938,6 +1952,8 @@ cvs_diff = cvs 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 "$@" git_log = git log "$@" @@ -1947,6 +1963,8 @@ 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 "$@" run = "$@" @@ -1994,11 +2012,23 @@ 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'` echo "Registering fossil repository $url in $MR_CONFIG" mr -c "$MR_CONFIG" config "`pwd`" checkout="mkdir -p '$MR_REPO' && cd '$MR_REPO' && fossil open '$repo'" +veracity_register = + url=`vv config | grep sync_targets | sed -e 's/sync_targets:*.//g' -e 's/ //g'` + repo=`vv repo info | grep repository | sed -e 's/Current repository:*.//g' -e 's/ //g'` + echo "Registering veracity repository $url in $MR_CONFIG" + mr -c "$MR_CONFIG" config "`pwd`" checkout="mkdir -p '$MR_REPO' && cd '$MR_REPO' && vv checkout '$repo'" svn_trusted_checkout = svn co $url $repo svn_alt_trusted_checkout = svn checkout $url $repo @@ -2008,7 +2038,9 @@ 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 help =