diff options
Diffstat (limited to 'git-svn.perl')
-rwxr-xr-x | git-svn.perl | 108 |
1 files changed, 61 insertions, 47 deletions
diff --git a/git-svn.perl b/git-svn.perl index 42906767a1..51979f9639 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -38,14 +38,16 @@ use IPC::Open3; use Git; BEGIN { - my $s; + # import functions from Git into our packages, en masse + no strict 'refs'; foreach (qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe/) { - $s .= "*SVN::Git::Editor::$_ = *SVN::Git::Fetcher::$_ = ". - "*Git::SVN::Migration::$_ = ". - "*Git::SVN::Log::$_ = *Git::SVN::$_ = *$_ = *Git::$_; "; + for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher + Git::SVN::Migration Git::SVN::Log Git::SVN), + __PACKAGE__) { + *{"${package}::$_"} = \&{"Git::$_"}; + } } - eval $s; } my ($SVN); @@ -590,8 +592,7 @@ sub post_fetch_checkout { my $index = $ENV{GIT_INDEX_FILE} || "$ENV{GIT_DIR}/index"; return if -f $index; - chomp(my $bare = `git config --bool --get core.bare`); - return if $bare eq 'true'; + return if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false'; return if command_oneline(qw/rev-parse --is-inside-git-dir/) eq 'true'; command_noisy(qw/read-tree -m -u -v HEAD HEAD/); print STDERR "Checked out HEAD:\n ", @@ -781,12 +782,12 @@ sub read_repo_config { sub extract_metadata { my $id = shift or return (undef, undef, undef); - my ($url, $rev, $uuid) = ($id =~ /^git-svn-id:\s(\S+?)\@(\d+) + my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+) \s([a-f\d\-]+)$/x); if (!defined $rev || !$uuid || !$url) { # some of the original repositories I made had # identifiers like this: - ($rev, $uuid) = ($id =~/^git-svn-id:\s(\d+)\@([a-f\d\-]+)/); + ($rev, $uuid) = ($id =~/^\s*git-svn-id:\s(\d+)\@([a-f\d\-]+)/); } return ($url, $rev, $uuid); } @@ -798,20 +799,29 @@ sub cmt_metadata { sub working_head_info { my ($head, $refs) = @_; - my ($fh, $ctx) = command_output_pipe('rev-list', $head); - while (my $hash = <$fh>) { - chomp($hash); - my ($url, $rev, $uuid) = cmt_metadata($hash); + my ($fh, $ctx) = command_output_pipe('log', $head); + my $hash; + my %max; + while (<$fh>) { + if ( m{^commit ($::sha1)$} ) { + unshift @$refs, $hash if $hash and $refs; + $hash = $1; + next; + } + next unless s{^\s*(git-svn-id:)}{$1}; + my ($url, $rev, $uuid) = extract_metadata($_); if (defined $url && defined $rev) { + next if $max{$url} and $max{$url} < $rev; if (my $gs = Git::SVN->find_by_url($url)) { my $c = $gs->rev_db_get($rev); if ($c && $c eq $hash) { close $fh; # break the pipe return ($url, $rev, $uuid, $gs); + } else { + $max{$url} ||= $gs->rev_db_max; } } } - unshift @$refs, $hash if $refs; } command_close_pipe($fh, $ctx); (undef, undef, undef, undef); @@ -895,26 +905,26 @@ BEGIN { # some options are read globally, but can be overridden locally # per [svn-remote "..."] section. Command-line options will *NOT* # override options set in an [svn-remote "..."] section - my $e; - foreach (qw/follow_parent no_metadata use_svm_props - use_svnsync_props/) { - my $key = $_; + no strict 'refs'; + for my $option (qw/follow_parent no_metadata use_svm_props + use_svnsync_props/) { + my $key = $option; $key =~ tr/_//d; - $e .= "sub $_ { - my (\$self) = \@_; - return \$self->{-$_} if exists \$self->{-$_}; - my \$k = \"svn-remote.\$self->{repo_id}\.$key\"; - eval { command_oneline(qw/config --get/, \$k) }; - if (\$@) { - \$self->{-$_} = \$Git::SVN::_$_; + my $prop = "-$option"; + *$option = sub { + my ($self) = @_; + return $self->{$prop} if exists $self->{$prop}; + my $k = "svn-remote.$self->{repo_id}.$key"; + eval { command_oneline(qw/config --get/, $k) }; + if ($@) { + $self->{$prop} = ${"Git::SVN::_$option"}; } else { - my \$v = command_oneline(qw/config --bool/,\$k); - \$self->{-$_} = \$v eq 'false' ? 0 : 1; + my $v = command_oneline(qw/config --bool/,$k); + $self->{$prop} = $v eq 'false' ? 0 : 1; } - return \$self->{-$_} }\n"; + return $self->{$prop}; + } } - $e .= "1;\n"; - eval $e or die $@; } my %LOCKFILES; @@ -2018,16 +2028,19 @@ sub rebuild { return; } print "Rebuilding $db_path ...\n"; - my ($rev_list, $ctx) = command_output_pipe("rev-list", $self->refname); + my ($log, $ctx) = command_output_pipe("log", $self->refname); my $latest; my $full_url = $self->full_url; remove_username($full_url); my $svn_uuid; - while (<$rev_list>) { - chomp; - my $c = $_; - die "Non-SHA1: $c\n" unless $c =~ /^$::sha1$/o; - my ($url, $rev, $uuid) = ::cmt_metadata($c); + my $c; + while (<$log>) { + if ( m{^commit ($::sha1)$} ) { + $c = $1; + next; + } + next unless s{^\s*(git-svn-id:)}{$1}; + my ($url, $rev, $uuid) = ::extract_metadata($_); remove_username($url); # ignore merges (from set-tree) @@ -2045,7 +2058,7 @@ sub rebuild { $self->rev_db_set($rev, $c); print "r$rev = $c\n"; } - command_close_pipe($rev_list, $ctx); + command_close_pipe($log, $ctx); print "Done rebuilding $db_path\n"; } @@ -2953,17 +2966,17 @@ my ($can_do_switch, %ignored_err, $RA); BEGIN { # enforce temporary pool usage for some simple functions - my $e; - foreach (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) { - $e .= "sub $_ { - my \$self = shift; - my \$pool = SVN::Pool->new; - my \@ret = \$self->SUPER::$_(\@_,\$pool); - \$pool->clear; - wantarray ? \@ret : \$ret[0]; }\n"; + no strict 'refs'; + for my $f (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) { + my $SUPER = "SUPER::$f"; + *$f = sub { + my $self = shift; + my $pool = SVN::Pool->new; + my @ret = $self->$SUPER(@_,$pool); + $pool->clear; + wantarray ? @ret : $ret[0]; + }; } - - eval "$e; 1;" or die $@; } sub new { @@ -2977,6 +2990,7 @@ sub new { SVN::Client::get_ssl_server_trust_file_provider(), SVN::Client::get_simple_prompt_provider( \&Git::SVN::Prompt::simple, 2), + SVN::Client::get_ssl_client_cert_file_provider(), SVN::Client::get_ssl_client_cert_prompt_provider( \&Git::SVN::Prompt::ssl_client_cert, 2), SVN::Client::get_ssl_client_cert_pw_prompt_provider( |