Skip to content

Commit afd7f1e

Browse files
Frédéric HeitzmannEric Wong
authored andcommitted
git svn dcommit: new option --interactive.
Allow the user to check the patch set before it is commited to SVN. It is then possible to accept/discard one patch, accept all, or quit. This interactive mode is similar with 'git send email' behaviour. However, 'git svn dcommit' returns as soon as one patch is discarded. Part of the code was taken from git-send-email.perl (see 'ask' function) Tests several combinations of potential answers to 'git svn dcommit --interactive'. For each of them, test whether patches were commited to SVN or not. Thanks-to Eric Wong <normalperson@yhbt.net> for the initial idea. Acked-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Frédéric Heitzmann <frederic.heitzmann@gmail.com>
1 parent 2883969 commit afd7f1e

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

Documentation/git-svn.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ svn:mergeinfo property in the SVN repository when possible. Currently, this can
234234
only be done when dcommitting non-fast-forward merges where all parents but the
235235
first have already been pushed into SVN.
236236

237+
--interactive;;
238+
Ask the user to confirm that a patch set should actually be sent to SVN.
239+
For each patch, one may answer "yes" (accept this patch), "no" (discard this
240+
patch), "all" (accept all patches), or "quit".
241+
+
242+
'git svn dcommit' returns immediately if answer if "no" or "quit", without
243+
commiting anything to SVN.
244+
237245
'branch'::
238246
Create a branch in the SVN repository.
239247

git-svn.perl

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ BEGIN
8787
$_version, $_fetch_all, $_no_rebase, $_fetch_parent,
8888
$_merge, $_strategy, $_dry_run, $_local,
8989
$_prefix, $_no_checkout, $_url, $_verbose,
90-
$_git_format, $_commit_url, $_tag, $_merge_info);
90+
$_git_format, $_commit_url, $_tag, $_merge_info, $_interactive);
9191
$Git::SVN::_follow_parent = 1;
9292
$SVN::Git::Fetcher::_placeholder_filename = ".gitignore";
9393
$_q ||= 0;
@@ -163,6 +163,7 @@ BEGIN
163163
'revision|r=i' => \$_revision,
164164
'no-rebase' => \$_no_rebase,
165165
'mergeinfo=s' => \$_merge_info,
166+
'interactive|i' => \$_interactive,
166167
%cmt_opts, %fc_opts } ],
167168
branch => [ \&cmd_branch,
168169
'Create a branch in the SVN repository',
@@ -256,6 +257,27 @@ BEGIN
256257
{} ],
257258
);
258259

260+
use Term::ReadLine;
261+
package FakeTerm;
262+
sub new {
263+
my ($class, $reason) = @_;
264+
return bless \$reason, shift;
265+
}
266+
sub readline {
267+
my $self = shift;
268+
die "Cannot use readline on FakeTerm: $$self";
269+
}
270+
package main;
271+
272+
my $term = eval {
273+
$ENV{"GIT_SVN_NOTTY"}
274+
? new Term::ReadLine 'git-svn', \*STDIN, \*STDOUT
275+
: new Term::ReadLine 'git-svn';
276+
};
277+
if ($@) {
278+
$term = new FakeTerm "$@: going non-interactive";
279+
}
280+
259281
my $cmd;
260282
for (my $i = 0; $i < @ARGV; $i++) {
261283
if (defined $cmd{$ARGV[$i]}) {
@@ -366,6 +388,36 @@ sub version {
366388
exit 0;
367389
}
368390
391+
sub ask {
392+
my ($prompt, %arg) = @_;
393+
my $valid_re = $arg{valid_re};
394+
my $default = $arg{default};
395+
my $resp;
396+
my $i = 0;
397+
398+
if ( !( defined($term->IN)
399+
&& defined( fileno($term->IN) )
400+
&& defined( $term->OUT )
401+
&& defined( fileno($term->OUT) ) ) ){
402+
return defined($default) ? $default : undef;
403+
}
404+
405+
while ($i++ < 10) {
406+
$resp = $term->readline($prompt);
407+
if (!defined $resp) { # EOF
408+
print "\n";
409+
return defined $default ? $default : undef;
410+
}
411+
if ($resp eq '' and defined $default) {
412+
return $default;
413+
}
414+
if (!defined $valid_re or $resp =~ /$valid_re/) {
415+
return $resp;
416+
}
417+
}
418+
return undef;
419+
}
420+
369421
sub do_git_init_db {
370422
unless (-d $ENV{GIT_DIR}) {
371423
my @init_db = ('init');
@@ -746,6 +798,27 @@ sub cmd_dcommit {
746798
"If these changes depend on each other, re-running ",
747799
"without --no-rebase may be required."
748800
}
801+
802+
if (defined $_interactive){
803+
my $ask_default = "y";
804+
foreach my $d (@$linear_refs){
805+
my ($fh, $ctx) = command_output_pipe(qw(show --summary), "$d");
806+
while (<$fh>){
807+
print $_;
808+
}
809+
command_close_pipe($fh, $ctx);
810+
$_ = ask("Commit this patch to SVN? ([y]es (default)|[n]o|[q]uit|[a]ll): ",
811+
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
812+
default => $ask_default);
813+
die "Commit this patch reply required" unless defined $_;
814+
if (/^[nq]/i) {
815+
exit(0);
816+
} elsif (/^a/i) {
817+
last;
818+
}
819+
}
820+
}
821+
749822
my $expect_url = $url;
750823

751824
my $push_merge_info = eval {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2011 Frédéric Heitzmann
4+
5+
test_description='git svn dcommit --interactive series'
6+
. ./lib-git-svn.sh
7+
8+
test_expect_success 'initialize repo' '
9+
svn_cmd mkdir -m"mkdir test-interactive" "$svnrepo/test-interactive" &&
10+
git svn clone "$svnrepo/test-interactive" test-interactive &&
11+
cd test-interactive &&
12+
touch foo && git add foo && git commit -m"foo: first commit" &&
13+
git svn dcommit
14+
'
15+
16+
test_expect_success 'answers: y [\n] yes' '
17+
(
18+
echo "change #1" >> foo && git commit -a -m"change #1" &&
19+
echo "change #2" >> foo && git commit -a -m"change #2" &&
20+
echo "change #3" >> foo && git commit -a -m"change #3" &&
21+
( echo "y
22+
23+
y" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) &&
24+
test $(git rev-parse HEAD) = $(git rev-parse remotes/git-svn)
25+
)
26+
'
27+
28+
test_expect_success 'answers: yes yes no' '
29+
(
30+
echo "change #1" >> foo && git commit -a -m"change #1" &&
31+
echo "change #2" >> foo && git commit -a -m"change #2" &&
32+
echo "change #3" >> foo && git commit -a -m"change #3" &&
33+
( echo "yes
34+
yes
35+
no" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) &&
36+
test $(git rev-parse HEAD^^^) = $(git rev-parse remotes/git-svn) &&
37+
git reset --hard remotes/git-svn
38+
)
39+
'
40+
41+
test_expect_success 'answers: yes quit' '
42+
(
43+
echo "change #1" >> foo && git commit -a -m"change #1" &&
44+
echo "change #2" >> foo && git commit -a -m"change #2" &&
45+
echo "change #3" >> foo && git commit -a -m"change #3" &&
46+
( echo "yes
47+
quit" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) &&
48+
test $(git rev-parse HEAD^^^) = $(git rev-parse remotes/git-svn) &&
49+
git reset --hard remotes/git-svn
50+
)
51+
'
52+
53+
test_expect_success 'answers: all' '
54+
(
55+
echo "change #1" >> foo && git commit -a -m"change #1" &&
56+
echo "change #2" >> foo && git commit -a -m"change #2" &&
57+
echo "change #3" >> foo && git commit -a -m"change #3" &&
58+
( echo "all" | GIT_SVN_NOTTY=1 git svn dcommit --interactive ) &&
59+
test $(git rev-parse HEAD) = $(git rev-parse remotes/git-svn) &&
60+
git reset --hard remotes/git-svn
61+
)
62+
'
63+
64+
test_done

0 commit comments

Comments
 (0)