X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=bin%2Frgit;h=1f0b2f0a6d9ac76f6c81096ce66ac6e903098c61;hb=0c3a62e21d624c6076fc69dd2310bea0dd556ab8;hp=101d63470156611295b448ee7562e4272b966304;hpb=ab6f258a18f074ed6f18d29d98ea13b6d708e3a2;p=perl%2Fmodules%2Frgit.git diff --git a/bin/rgit b/bin/rgit index 101d634..1f0b2f0 100755 --- a/bin/rgit +++ b/bin/rgit @@ -4,16 +4,53 @@ use strict; use warnings; use Carp qw/croak/; +use Config qw/%Config/; use Cwd qw/cwd/; use File::Spec::Functions qw/catfile path/; -use List::Util qw/first/; +use App::Rgit::Utils qw/:codes :levels/; use App::Rgit; -our $VERSION = '0.02'; +our $VERSION; +BEGIN { + $VERSION = '0.05'; +} + +my %opts; +my $cmd; + +BEGIN { + @ARGV = grep { + defined $cmd ? $_ + : ( /^-([DIKV]+)$/ ? do { $opts{$_} = 1 for split //, $1; () } + : do { $cmd = $_ unless /^-/; $_ } ) + } @ARGV; + $cmd = ' ' unless defined $cmd; +} + +my $shell; + +BEGIN { + if (-t && $opts{I}) { + if (eval "require Term::ReadKey; 1") { + Term::ReadKey->import; + *policy = \&policy_interactive; + for (grep defined, $ENV{SHELL}, '/bin/sh') { + if (-x $_) { + $shell = $_; + last; + } + } + } else { + warn "You have to install Term::ReadKey to use the interactive mode.\n"; + } + } + *policy = $opts{K} ? \&policy_keep + : \&policy_default + unless defined *policy{CODE}; +} -my $cmd = first { !/^-/ } @ARGV; -$cmd = ' ' unless defined $cmd; +setpgrp 0, 0 if $Config{d_setpgrp}; my $git = $ENV{GIT_EXEC_PATH}; unless (defined $git) { @@ -30,12 +67,64 @@ croak "Couldn't find any valid git executable" unless defined $git; my $root = $ENV{GIT_DIR}; $root = cwd unless defined $root; -exit App::Rgit->new( - git => $git, - root => $root, - cmd => $cmd, - args => \@ARGV -)->run; +my $ar = App::Rgit->new( + git => $git, + root => $root, + cmd => $cmd, + args => \@ARGV, + policy => \&policy, + debug => $opts{D} ? INFO : WARN, +); + +print STDOUT "rgit $VERSION\n" if $opts{V}; + +exit $ar->run; + +sub policy_default { + my ($cmd, $conf, $repo, $status, $signal) = @_; + return NEXT unless $status; + return LAST; +} + +sub policy_keep { NEXT } + +sub policy_interactive { + my ($cmd, $conf, $repo, $status, $signal) = @_; + return NEXT unless $status; + my %codes = ( + 'a' => [ LAST, 'aborting' ], + 'i' => [ NEXT, 'ignoring' ], + 'I' => [ NEXT | SAVE, 'ignoring all' ], + 'r' => [ REDO, 'retrying' ], + ); + my $int = { GetControlChars() }->{INTERRUPT}; + while (1) { + $conf->warn("[a]bort, [i]gnore, [I]gnore all, [r]etry, open [s]hell ?"); + ReadMode(4); + my $key = ReadKey(0); + ReadMode(1); + print STDERR "\n"; + next unless defined $key; + if ($key eq $int) { + $conf->warn("Interrupted, aborting\n"); + return LAST; + } elsif ($key eq 's') { + if (defined $shell) { + $conf->info('Opening shell in ', $repo->work, "\n"); + my $cwd = cwd; + $repo->chdir; + system { $shell } $shell; + chroot $cwd; + } else { + $conf->err("Couldn't find any shell\n"); + } + } elsif (exists $codes{$key}) { + my $code = $codes{$key}; + $conf->info('Okay, ', $code->[1], "\n"); + return $code->[0]; + } + } +} __END__ @@ -45,11 +134,11 @@ rgit - Recursively execute a command on all the git repositories in a directory =head1 VERSION -Version 0.02 +Version 0.05 =head1 SYNOPSIS - rgit [GIT_OPTIONS] COMMAND [COMMAND_ARGS] + rgit [-K|-I|-D|-V] [GIT_OPTIONS] COMMAND [COMMAND_ARGS] =head1 DESCRIPTION @@ -96,11 +185,48 @@ C<^^> with a bare C<^>. =back -There are actually a few commands that are only executed once in the current directory : C, C, C and C. +There are actually a few commands that are only executed once in the current directory : C, C, C, C and C. For any of those, no format substitution is done. You can specify which C executable to use with the C environment variable. +=head1 COMMAND LINE SWITCHES + +C takes its options as the capital switches that comes before the git command. +It's possible to bundle them together. +They are removed from the argument list before calling C. + +=over 4 + +=item * + +C<-K> + +Keep processing on error. +The default policy is to stop whenever an error occured. + +=item * + +C<-I> + +Enables interactive mode when the standard input is a tty. +Requires L to be installed. +This lets you choose interactively what to do when one of the commands returns a non-zero status. + +=item * + +C<-D> + +Outputs diagnostics. + +=item * + +C<-V> + +Outputs the version. + +=back + =head1 EXAMPLES Execute C on all the repositories below the current directory : @@ -117,7 +243,7 @@ Add a remote to all repositories in "/foo/bar" to their bare counterpart in C, L, L, L, L and L. +The core modules L, L, L, L, L, L and L. L.