diff options
author | Junio C Hamano <gitster@pobox.com> | 2007-07-02 01:46:22 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-07-02 01:46:22 -0700 |
commit | 1fd81efad0d65afba91f8fb27b40a6345bfb50de (patch) | |
tree | b061c0e043619ba3469f23b7c73cbbc43cb62dc1 /git-svn.perl | |
parent | 7425dcc95e11c20dc4663d7a376dc9ba0424d843 (diff) | |
parent | 733a65aa5d33196fac708ebd12a98a1060cbf3c2 (diff) | |
download | git-1fd81efad0d65afba91f8fb27b40a6345bfb50de.tar.gz git-1fd81efad0d65afba91f8fb27b40a6345bfb50de.tar.xz |
Merge branch 'ew/svn'
* ew/svn:
git-svn: allow dcommit to retain local merge information
Diffstat (limited to 'git-svn.perl')
-rwxr-xr-x | git-svn.perl | 72 |
1 files changed, 63 insertions, 9 deletions
diff --git a/git-svn.perl b/git-svn.perl index 03d5e2d97..51979f963 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -374,16 +374,9 @@ sub cmd_dcommit { die "Unable to determine upstream SVN information from ", "$head history\n"; } - my $c = $refs[-1]; my $last_rev; - foreach my $d (@refs) { - if (!verify_ref("$d~1")) { - fatal "Commit $d\n", - "has no parent commit, and therefore ", - "nothing to diff against.\n", - "You should be working from a repository ", - "originally created by git-svn\n"; - } + my ($linear_refs, $parents) = linearize_history($gs, \@refs); + foreach my $d (@$linear_refs) { unless (defined $last_rev) { (undef, $last_rev, undef) = cmt_metadata("$d~1"); unless (defined $last_rev) { @@ -405,6 +398,9 @@ sub cmd_dcommit { svn_path => ''); if (!SVN::Git::Editor->new(\%ed_opts)->apply_diff) { print "No changes\n$d~1 == $d\n"; + } elsif ($parents->{$d} && @{$parents->{$d}}) { + $gs->{inject_parents_dcommit}->{$last_rev} = + $parents->{$d}; } } } @@ -831,6 +827,59 @@ sub working_head_info { (undef, undef, undef, undef); } +sub read_commit_parents { + my ($parents, $c) = @_; + my ($fh, $ctx) = command_output_pipe(qw/cat-file commit/, $c); + while (<$fh>) { + chomp; + last if ''; + /^parent ($sha1)/ or next; + push @{$parents->{$c}}, $1; + } + close $fh; # break the pipe +} + +sub linearize_history { + my ($gs, $refs) = @_; + my %parents; + foreach my $c (@$refs) { + read_commit_parents(\%parents, $c); + } + + my @linear_refs; + my %skip = (); + my $last_svn_commit = $gs->last_commit; + foreach my $c (reverse @$refs) { + next if $c eq $last_svn_commit; + last if $skip{$c}; + + unshift @linear_refs, $c; + $skip{$c} = 1; + + # we only want the first parent to diff against for linear + # history, we save the rest to inject when we finalize the + # svn commit + my $fp_a = verify_ref("$c~1"); + my $fp_b = shift @{$parents{$c}} if $parents{$c}; + if (!$fp_a || !$fp_b) { + die "Commit $c\n", + "has no parent commit, and therefore ", + "nothing to diff against.\n", + "You should be working from a repository ", + "originally created by git-svn\n"; + } + if ($fp_a ne $fp_b) { + die "$c~1 = $fp_a, however parsing commit $c ", + "revealed that:\n$c~1 = $fp_b\nBUG!\n"; + } + + foreach my $p (@{$parents{$c}}) { + $skip{$p} = 1; + } + } + (\@linear_refs, \%parents); +} + package Git::SVN; use strict; use warnings; @@ -1551,6 +1600,11 @@ sub get_commit_parents { if (my $cur = ::verify_ref($self->refname.'^0')) { push @tmp, $cur; } + if (my $ipd = $self->{inject_parents_dcommit}) { + if (my $commit = delete $ipd->{$log_entry->{revision}}) { + push @tmp, @$commit; + } + } push @tmp, $_ foreach (@{$log_entry->{parents}}, @tmp); while (my $p = shift @tmp) { next if $seen{$p}; |