Skip to content

Commit c102f4c

Browse files
jrnEric Wong
authored andcommitted
git-svn: move Git::SVN::Prompt into its own file
git-svn.perl is very long (around 6500 lines) and although it is nicely split into modules, some new readers do not even notice --- it is too distracting to see all this functionality collected in a single file. Splitting it into multiple files would make it easier for people to read individual modules straight through and to experiment with components separately. Let's start with Git::SVN::Prompt. For simplicity, we install this as a module in the standard search path, just like the existing Git and Git::I18N modules. In the process, add a manpage explaining its interface and that it is not likely to be useful for other projects to avoid confusion. Signed-off-by: Jonathan Nieder <[email protected]> Signed-off-by: Eric Wong <[email protected]>
1 parent befc5ed commit c102f4c

File tree

3 files changed

+204
-144
lines changed

3 files changed

+204
-144
lines changed

git-svn.perl

Lines changed: 1 addition & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ sub _req_svn {
8080
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
8181
use IPC::Open3;
8282
use Git;
83+
use Git::SVN::Prompt qw//;
8384
use Memoize; # core since 5.8.0, Jul 2002
8485

8586
BEGIN {
@@ -4327,150 +4328,6 @@ sub remove_username {
43274328
$_[0] =~ s{^([^:]*://)[^@]+@}{$1};
43284329
}
43294330

4330-
package Git::SVN::Prompt;
4331-
use strict;
4332-
use warnings;
4333-
require SVN::Core;
4334-
use vars qw/$_no_auth_cache $_username/;
4335-
4336-
sub simple {
4337-
my ($cred, $realm, $default_username, $may_save, $pool) = @_;
4338-
$may_save = undef if $_no_auth_cache;
4339-
$default_username = $_username if defined $_username;
4340-
if (defined $default_username && length $default_username) {
4341-
if (defined $realm && length $realm) {
4342-
print STDERR "Authentication realm: $realm\n";
4343-
STDERR->flush;
4344-
}
4345-
$cred->username($default_username);
4346-
} else {
4347-
username($cred, $realm, $may_save, $pool);
4348-
}
4349-
$cred->password(_read_password("Password for '" .
4350-
$cred->username . "': ", $realm));
4351-
$cred->may_save($may_save);
4352-
$SVN::_Core::SVN_NO_ERROR;
4353-
}
4354-
4355-
sub ssl_server_trust {
4356-
my ($cred, $realm, $failures, $cert_info, $may_save, $pool) = @_;
4357-
$may_save = undef if $_no_auth_cache;
4358-
print STDERR "Error validating server certificate for '$realm':\n";
4359-
{
4360-
no warnings 'once';
4361-
# All variables SVN::Auth::SSL::* are used only once,
4362-
# so we're shutting up Perl warnings about this.
4363-
if ($failures & $SVN::Auth::SSL::UNKNOWNCA) {
4364-
print STDERR " - The certificate is not issued ",
4365-
"by a trusted authority. Use the\n",
4366-
" fingerprint to validate ",
4367-
"the certificate manually!\n";
4368-
}
4369-
if ($failures & $SVN::Auth::SSL::CNMISMATCH) {
4370-
print STDERR " - The certificate hostname ",
4371-
"does not match.\n";
4372-
}
4373-
if ($failures & $SVN::Auth::SSL::NOTYETVALID) {
4374-
print STDERR " - The certificate is not yet valid.\n";
4375-
}
4376-
if ($failures & $SVN::Auth::SSL::EXPIRED) {
4377-
print STDERR " - The certificate has expired.\n";
4378-
}
4379-
if ($failures & $SVN::Auth::SSL::OTHER) {
4380-
print STDERR " - The certificate has ",
4381-
"an unknown error.\n";
4382-
}
4383-
} # no warnings 'once'
4384-
printf STDERR
4385-
"Certificate information:\n".
4386-
" - Hostname: %s\n".
4387-
" - Valid: from %s until %s\n".
4388-
" - Issuer: %s\n".
4389-
" - Fingerprint: %s\n",
4390-
map $cert_info->$_, qw(hostname valid_from valid_until
4391-
issuer_dname fingerprint);
4392-
my $choice;
4393-
prompt:
4394-
print STDERR $may_save ?
4395-
"(R)eject, accept (t)emporarily or accept (p)ermanently? " :
4396-
"(R)eject or accept (t)emporarily? ";
4397-
STDERR->flush;
4398-
$choice = lc(substr(<STDIN> || 'R', 0, 1));
4399-
if ($choice =~ /^t$/i) {
4400-
$cred->may_save(undef);
4401-
} elsif ($choice =~ /^r$/i) {
4402-
return -1;
4403-
} elsif ($may_save && $choice =~ /^p$/i) {
4404-
$cred->may_save($may_save);
4405-
} else {
4406-
goto prompt;
4407-
}
4408-
$cred->accepted_failures($failures);
4409-
$SVN::_Core::SVN_NO_ERROR;
4410-
}
4411-
4412-
sub ssl_client_cert {
4413-
my ($cred, $realm, $may_save, $pool) = @_;
4414-
$may_save = undef if $_no_auth_cache;
4415-
print STDERR "Client certificate filename: ";
4416-
STDERR->flush;
4417-
chomp(my $filename = <STDIN>);
4418-
$cred->cert_file($filename);
4419-
$cred->may_save($may_save);
4420-
$SVN::_Core::SVN_NO_ERROR;
4421-
}
4422-
4423-
sub ssl_client_cert_pw {
4424-
my ($cred, $realm, $may_save, $pool) = @_;
4425-
$may_save = undef if $_no_auth_cache;
4426-
$cred->password(_read_password("Password: ", $realm));
4427-
$cred->may_save($may_save);
4428-
$SVN::_Core::SVN_NO_ERROR;
4429-
}
4430-
4431-
sub username {
4432-
my ($cred, $realm, $may_save, $pool) = @_;
4433-
$may_save = undef if $_no_auth_cache;
4434-
if (defined $realm && length $realm) {
4435-
print STDERR "Authentication realm: $realm\n";
4436-
}
4437-
my $username;
4438-
if (defined $_username) {
4439-
$username = $_username;
4440-
} else {
4441-
print STDERR "Username: ";
4442-
STDERR->flush;
4443-
chomp($username = <STDIN>);
4444-
}
4445-
$cred->username($username);
4446-
$cred->may_save($may_save);
4447-
$SVN::_Core::SVN_NO_ERROR;
4448-
}
4449-
4450-
sub _read_password {
4451-
my ($prompt, $realm) = @_;
4452-
my $password = '';
4453-
if (exists $ENV{GIT_ASKPASS}) {
4454-
open(PH, "-|", $ENV{GIT_ASKPASS}, $prompt);
4455-
$password = <PH>;
4456-
$password =~ s/[\012\015]//; # \n\r
4457-
close(PH);
4458-
} else {
4459-
print STDERR $prompt;
4460-
STDERR->flush;
4461-
require Term::ReadKey;
4462-
Term::ReadKey::ReadMode('noecho');
4463-
while (defined(my $key = Term::ReadKey::ReadKey(0))) {
4464-
last if $key =~ /[\012\015]/; # \n\r
4465-
$password .= $key;
4466-
}
4467-
Term::ReadKey::ReadMode('restore');
4468-
print STDERR "\n";
4469-
STDERR->flush;
4470-
}
4471-
$password;
4472-
}
4473-
44744331
package SVN::Git::Fetcher;
44754332
use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename
44764333
@deleted_gpath %added_placeholder $repo_id/;

perl/Git/SVN/Prompt.pm

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package Git::SVN::Prompt;
2+
use strict;
3+
use warnings;
4+
require SVN::Core;
5+
use vars qw/$_no_auth_cache $_username/;
6+
7+
sub simple {
8+
my ($cred, $realm, $default_username, $may_save, $pool) = @_;
9+
$may_save = undef if $_no_auth_cache;
10+
$default_username = $_username if defined $_username;
11+
if (defined $default_username && length $default_username) {
12+
if (defined $realm && length $realm) {
13+
print STDERR "Authentication realm: $realm\n";
14+
STDERR->flush;
15+
}
16+
$cred->username($default_username);
17+
} else {
18+
username($cred, $realm, $may_save, $pool);
19+
}
20+
$cred->password(_read_password("Password for '" .
21+
$cred->username . "': ", $realm));
22+
$cred->may_save($may_save);
23+
$SVN::_Core::SVN_NO_ERROR;
24+
}
25+
26+
sub ssl_server_trust {
27+
my ($cred, $realm, $failures, $cert_info, $may_save, $pool) = @_;
28+
$may_save = undef if $_no_auth_cache;
29+
print STDERR "Error validating server certificate for '$realm':\n";
30+
{
31+
no warnings 'once';
32+
# All variables SVN::Auth::SSL::* are used only once,
33+
# so we're shutting up Perl warnings about this.
34+
if ($failures & $SVN::Auth::SSL::UNKNOWNCA) {
35+
print STDERR " - The certificate is not issued ",
36+
"by a trusted authority. Use the\n",
37+
" fingerprint to validate ",
38+
"the certificate manually!\n";
39+
}
40+
if ($failures & $SVN::Auth::SSL::CNMISMATCH) {
41+
print STDERR " - The certificate hostname ",
42+
"does not match.\n";
43+
}
44+
if ($failures & $SVN::Auth::SSL::NOTYETVALID) {
45+
print STDERR " - The certificate is not yet valid.\n";
46+
}
47+
if ($failures & $SVN::Auth::SSL::EXPIRED) {
48+
print STDERR " - The certificate has expired.\n";
49+
}
50+
if ($failures & $SVN::Auth::SSL::OTHER) {
51+
print STDERR " - The certificate has ",
52+
"an unknown error.\n";
53+
}
54+
} # no warnings 'once'
55+
printf STDERR
56+
"Certificate information:\n".
57+
" - Hostname: %s\n".
58+
" - Valid: from %s until %s\n".
59+
" - Issuer: %s\n".
60+
" - Fingerprint: %s\n",
61+
map $cert_info->$_, qw(hostname valid_from valid_until
62+
issuer_dname fingerprint);
63+
my $choice;
64+
prompt:
65+
print STDERR $may_save ?
66+
"(R)eject, accept (t)emporarily or accept (p)ermanently? " :
67+
"(R)eject or accept (t)emporarily? ";
68+
STDERR->flush;
69+
$choice = lc(substr(<STDIN> || 'R', 0, 1));
70+
if ($choice =~ /^t$/i) {
71+
$cred->may_save(undef);
72+
} elsif ($choice =~ /^r$/i) {
73+
return -1;
74+
} elsif ($may_save && $choice =~ /^p$/i) {
75+
$cred->may_save($may_save);
76+
} else {
77+
goto prompt;
78+
}
79+
$cred->accepted_failures($failures);
80+
$SVN::_Core::SVN_NO_ERROR;
81+
}
82+
83+
sub ssl_client_cert {
84+
my ($cred, $realm, $may_save, $pool) = @_;
85+
$may_save = undef if $_no_auth_cache;
86+
print STDERR "Client certificate filename: ";
87+
STDERR->flush;
88+
chomp(my $filename = <STDIN>);
89+
$cred->cert_file($filename);
90+
$cred->may_save($may_save);
91+
$SVN::_Core::SVN_NO_ERROR;
92+
}
93+
94+
sub ssl_client_cert_pw {
95+
my ($cred, $realm, $may_save, $pool) = @_;
96+
$may_save = undef if $_no_auth_cache;
97+
$cred->password(_read_password("Password: ", $realm));
98+
$cred->may_save($may_save);
99+
$SVN::_Core::SVN_NO_ERROR;
100+
}
101+
102+
sub username {
103+
my ($cred, $realm, $may_save, $pool) = @_;
104+
$may_save = undef if $_no_auth_cache;
105+
if (defined $realm && length $realm) {
106+
print STDERR "Authentication realm: $realm\n";
107+
}
108+
my $username;
109+
if (defined $_username) {
110+
$username = $_username;
111+
} else {
112+
print STDERR "Username: ";
113+
STDERR->flush;
114+
chomp($username = <STDIN>);
115+
}
116+
$cred->username($username);
117+
$cred->may_save($may_save);
118+
$SVN::_Core::SVN_NO_ERROR;
119+
}
120+
121+
sub _read_password {
122+
my ($prompt, $realm) = @_;
123+
my $password = '';
124+
if (exists $ENV{GIT_ASKPASS}) {
125+
open(PH, "-|", $ENV{GIT_ASKPASS}, $prompt);
126+
$password = <PH>;
127+
$password =~ s/[\012\015]//; # \n\r
128+
close(PH);
129+
} else {
130+
print STDERR $prompt;
131+
STDERR->flush;
132+
require Term::ReadKey;
133+
Term::ReadKey::ReadMode('noecho');
134+
while (defined(my $key = Term::ReadKey::ReadKey(0))) {
135+
last if $key =~ /[\012\015]/; # \n\r
136+
$password .= $key;
137+
}
138+
Term::ReadKey::ReadMode('restore');
139+
print STDERR "\n";
140+
STDERR->flush;
141+
}
142+
$password;
143+
}
144+
145+
1;
146+
__END__
147+
148+
Git::SVN::Prompt - authentication callbacks for git-svn
149+
150+
=head1 SYNOPSIS
151+
152+
use Git::SVN::Prompt qw(simple ssl_client_cert ssl_client_cert_pw
153+
ssl_server_trust username);
154+
use SVN::Client ();
155+
156+
my $cached_simple = SVN::Client::get_simple_provider();
157+
my $git_simple = SVN::Client::get_simple_prompt_provider(\&simple, 2);
158+
my $cached_ssl = SVN::Client::get_ssl_server_trust_file_provider();
159+
my $git_ssl = SVN::Client::get_ssl_server_trust_prompt_provider(
160+
\&ssl_server_trust);
161+
my $cached_cert = SVN::Client::get_ssl_client_cert_file_provider();
162+
my $git_cert = SVN::Client::get_ssl_client_cert_prompt_provider(
163+
\&ssl_client_cert, 2);
164+
my $cached_cert_pw = SVN::Client::get_ssl_client_cert_pw_file_provider();
165+
my $git_cert_pw = SVN::Client::get_ssl_client_cert_pw_prompt_provider(
166+
\&ssl_client_cert_pw, 2);
167+
my $cached_username = SVN::Client::get_username_provider();
168+
my $git_username = SVN::Client::get_username_prompt_provider(
169+
\&username, 2);
170+
171+
my $ctx = new SVN::Client(
172+
auth => [
173+
$cached_simple, $git_simple,
174+
$cached_ssl, $git_ssl,
175+
$cached_cert, $git_cert,
176+
$cached_cert_pw, $git_cert_pw,
177+
$cached_username, $git_username
178+
]);
179+
180+
=head1 DESCRIPTION
181+
182+
This module is an implementation detail of the "git svn" command.
183+
It implements git-svn's authentication policy. Do not use it unless
184+
you are developing git-svn.
185+
186+
The interface will change as git-svn evolves.
187+
188+
=head1 DEPENDENCIES
189+
190+
L<SVN::Core>.
191+
192+
=head1 SEE ALSO
193+
194+
L<SVN::Client>.
195+
196+
=head1 INCOMPATIBILITIES
197+
198+
None reported.
199+
200+
=head1 BUGS
201+
202+
None.

perl/Makefile.PL

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ MAKE_FRAG
2727
my %pm = (
2828
'Git.pm' => '$(INST_LIBDIR)/Git.pm',
2929
'Git/I18N.pm' => '$(INST_LIBDIR)/Git/I18N.pm',
30+
'Git/SVN/Prompt.pm' => '$(INST_LIBDIR)/Git/SVN/Prompt.pm',
3031
);
3132

3233
# We come with our own bundled Error.pm. It's not in the set of default

0 commit comments

Comments
 (0)