X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=contrib%2Fgit-svn%2Fgit-svn.perl;h=417fcf1feba797e65a289994aadcd0e0f2a450a4;hb=c0d4822268d30b1668e94986a845b8bb5441e8b3;hp=27f1d682c8932fe5df5543b16e8abf9550e4fa5c;hpb=cf7424b021f99fbc5dc1127725e57ca3d48e981c;p=git.git diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl index 27f1d682..417fcf1f 100755 --- a/contrib/git-svn/git-svn.perl +++ b/contrib/git-svn/git-svn.perl @@ -31,6 +31,7 @@ use File::Path qw/mkpath/; use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev pass_through/; use File::Spec qw//; use POSIX qw/strftime/; +use IPC::Open3; use Memoize; memoize('revisions_eq'); @@ -662,17 +663,15 @@ sub show_log { my $pid = open(my $log,'-|'); defined $pid or croak $!; if (!$pid) { - my @rl = (qw/git-log --abbrev-commit --pretty=raw - --default/, "remotes/$GIT_SVN"); - push @rl, '--raw' if $_verbose; - exec(@rl, @args) or croak $!; + exec(git_svn_log_cmd($r_min,$r_max), @args) or croak $!; } setup_pager(); my (@k, $c, $d); + while (<$log>) { if (/^commit ($sha1_short)/o) { my $cmt = $1; - if ($c && defined $c->{r} && $c->{r} != $r_last) { + if ($c && cmt_showable($c) && $c->{r} != $r_last) { $r_last = $c->{r}; process_commit($c, $r_min, $r_max, \@k) or goto out; @@ -691,8 +690,7 @@ sub show_log { } elsif ($d) { push @{$c->{diff}}, $_; } elsif (/^ (git-svn-id:.+)$/) { - my ($url, $rev, $uuid) = extract_metadata($1); - $c->{r} = $rev; + (undef, $c->{r}, undef) = extract_metadata($1); } elsif (s/^ //) { push @{$c->{l}}, $_; } @@ -714,6 +712,52 @@ out: ########################### utility functions ######################### +sub cmt_showable { + my ($c) = @_; + return 1 if defined $c->{r}; + if ($c->{l} && $c->{l}->[-1] eq "...\n" && + $c->{a_raw} =~ /\@([a-f\d\-]+)>$/) { + my @msg = safe_qx(qw/git-cat-file commit/, $c->{c}); + shift @msg while ($msg[0] ne "\n"); + shift @msg; + @{$c->{l}} = grep !/^git-svn-id: /, @msg; + + (undef, $c->{r}, undef) = extract_metadata( + (grep(/^git-svn-id: /, @msg))[-1]); + } + return defined $c->{r}; +} + +sub git_svn_log_cmd { + my ($r_min, $r_max) = @_; + my @cmd = (qw/git-log --abbrev-commit --pretty=raw + --default/, "refs/remotes/$GIT_SVN"); + push @cmd, '--summary' if $_verbose; + return @cmd unless defined $r_max; + if ($r_max == $r_min) { + push @cmd, '--max-count=1'; + if (my $c = revdb_get($REVDB, $r_max)) { + push @cmd, $c; + } + } else { + my ($c_min, $c_max); + $c_max = revdb_get($REVDB, $r_max); + $c_min = revdb_get($REVDB, $r_min); + if ($c_min && $c_max) { + if ($r_max > $r_max) { + push @cmd, "$c_min..$c_max"; + } else { + push @cmd, "$c_max..$c_min"; + } + } elsif ($r_max > $r_min) { + push @cmd, $c_max; + } else { + push @cmd, $c_min; + } + } + return @cmd; +} + sub fetch_child_id { my $id = shift; print "Fetching $id\n"; @@ -2205,6 +2249,7 @@ sub setup_pager { # translated to Perl from pager.c sub get_author_info { my ($dest, $author, $t, $tz) = @_; $author =~ s/(?:^\s*|\s*$)//g; + $dest->{a_raw} = $author; my $_a; if ($_authors) { $_a = $rusers{$author} || undef; @@ -2335,47 +2380,36 @@ sub libsvn_get_file { my $p = $f; return unless ($p =~ s#^\Q$SVN_PATH\E/?##); - my $fd = IO::File->new_tmpfile or croak $!; + my ($hash, $pid, $in, $out); my $pool = SVN::Pool->new; - my ($r, $props) = $SVN->get_file($f, $rev, $fd, $pool); + defined($pid = open3($in, $out, '>&STDERR', + qw/git-hash-object -w --stdin/)) or croak $!; + my ($r, $props) = $SVN->get_file($f, $rev, $in, $pool); + $in->flush == 0 or croak $!; + close $in or croak $!; $pool->clear; - $fd->flush == 0 or croak $!; - seek $fd, 0, 0 or croak $!; - if (my $es = $props->{'svn:eol-style'}) { - my $new_fd = IO::File->new_tmpfile or croak $!; - eol_cp_fd($fd, $new_fd, $es); - close $fd or croak $!; - $fd = $new_fd; - seek $fd, 0, 0 or croak $!; - $fd->flush == 0 or croak $!; - } - my $mode = '100644'; - if (exists $props->{'svn:executable'}) { - $mode = '100755'; - } + chomp($hash = do { local $/; <$out> }); + close $out or croak $!; + waitpid $pid, 0; + $hash =~ /^$sha1$/o or die "not a sha1: $hash\n"; + + my $mode = exists $props->{'svn:executable'} ? '100755' : '100644'; if (exists $props->{'svn:special'}) { $mode = '120000'; - local $/; - my $link = <$fd>; + my $link = `git-cat-file blob $hash`; $link =~ s/^link // or die "svn:special file with contents: <", $link, "> is not understood\n"; - seek $fd, 0, 0 or croak $!; - truncate $fd, 0 or croak $!; - print $fd $link or croak $!; - seek $fd, 0, 0 or croak $!; - $fd->flush == 0 or croak $!; - } - my $pid = open my $ho, '-|'; - defined $pid or croak $!; - if (!$pid) { - open STDIN, '<&', $fd or croak $!; - exec qw/git-hash-object -w --stdin/ or croak $!; + defined($pid = open3($in, $out, '>&STDERR', + qw/git-hash-object -w --stdin/)) or croak $!; + print $in $link; + $in->flush == 0 or croak $!; + close $in or croak $!; + chomp($hash = do { local $/; <$out> }); + close $out or croak $!; + waitpid $pid, 0; + $hash =~ /^$sha1$/o or die "not a sha1: $hash\n"; } - chomp(my $hash = do { local $/; <$ho> }); - close $ho or croak $?; - $hash =~ /^$sha1$/o or die "not a sha1: $hash\n"; print $gui $mode,' ',$hash,"\t",$p,"\0" or croak $!; - close $fd or croak $?; } sub libsvn_log_entry { @@ -2450,7 +2484,7 @@ sub svn_grab_base_rev { close $fh; if (defined $c && length $c) { my ($url, $rev, $uuid) = extract_metadata((grep(/^git-svn-id: /, - safe_qx(qw/git-cat-file commit/, $c)))[0]); + safe_qx(qw/git-cat-file commit/, $c)))[-1]); return ($rev, $c); } return (undef, undef);