@matheusbsbs / matheus-bagliano / commits / dff589ef94
Fork 0

git-svn: convert SVN 1.5+ / svnmerge.py svn:mergeinfo props to parents

This feature is long overdue; convert SVN's merge representation to git's as revisions are imported. This works by converting the list of revisions in each line of the svn:mergeinfo into git revision ranges, and then checking the latest of each of these revision ranges for A) being new and B) now being completely merged. Signed-off-by: Sam Vilain <sam.vilain@catalyst.net.nz> Acked-by: Eric Wong <normalperson@yhbt.net>

Sam Vilain committed Oct 20, 2009 at 15:42 UTC dff589ef949e97cbec5363b105ba27f6e85594fb
2 files changed +114
git-svn.perl
+93
@@ -2918,6 +2918,93 @@ sub find_extra_svk_parents {
2918 }
2919 }
2920
2921 +# note: this function should only be called if the various dirprops
2922 +# have actually changed
2923 +sub find_extra_svn_parents {
2924 + my ($self, $ed, $mergeinfo, $parents) = @_;
2925 + # aha! svk:merge property changed...
2926 +
2927 + # We first search for merged tips which are not in our
2928 + # history. Then, we figure out which git revisions are in
2929 + # that tip, but not this revision. If all of those revisions
2930 + # are now marked as merge, we can add the tip as a parent.
2931 + my @merges = split "\n", $mergeinfo;
2932 + my @merge_tips;
2933 + my @merged_commit_ranges;
2934 + my $url = $self->rewrite_root || $self->{url};
2935 + for my $merge ( @merges ) {
2936 + my ($source, $revs) = split ":", $merge;
2937 + my $path = $source;
2938 + $path =~ s{^/}{};
2939 + my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
2940 + if ( !$gs ) {
2941 + warn "Couldn't find revmap for $url$source\n";
2942 + next;
2943 + }
2944 + my @ranges = split ",", $revs;
2945 + my ($tip, $tip_commit);
2946 + # find the tip
2947 + for my $range ( @ranges ) {
2948 + my ($bottom, $top) = split "-", $range;
2949 + $top ||= $bottom;
2950 + my $bottom_commit =
2951 + $gs->rev_map_get($bottom, $self->ra_uuid) ||
2952 + $gs->rev_map_get($bottom+1, $self->ra_uuid);
2953 + my $top_commit =
2954 + $gs->rev_map_get($top, $self->ra_uuid);
2955 +
2956 + unless ($top_commit and $bottom_commit) {
2957 + warn "W:unknown path/rev in svn:mergeinfo "
2958 + ."dirprop: $source:$range\n";
2959 + next;
2960 + }
2961 +
2962 + push @merged_commit_ranges,
2963 + "$bottom_commit..$top_commit";
2964 +
2965 + if ( !defined $tip or $top > $tip ) {
2966 + $tip = $top;
2967 + $tip_commit = $top_commit;
2968 + }
2969 + }
2970 + unless (!$tip_commit or
2971 + grep { $_ eq $tip_commit } @$parents ) {
2972 + push @merge_tips, $tip_commit;
2973 + } else {
2974 + push @merge_tips, undef;
2975 + }
2976 + }
2977 + for my $merge_tip ( @merge_tips ) {
2978 + my $spec = shift @merges;
2979 + next unless $merge_tip;
2980 + my @cmd = ('rev-list', "-1", $merge_tip,
2981 + "--not", @$parents );
2982 + my ($msg_fh, $ctx) = command_output_pipe(@cmd);
2983 + my $new;
2984 + while ( <$msg_fh> ) {
2985 + $new=1;last;
2986 + }
2987 + command_close_pipe($msg_fh, $ctx);
2988 + if ( $new ) {
2989 + push @cmd, @merged_commit_ranges;
2990 + my ($msg_fh, $ctx) = command_output_pipe(@cmd);
2991 + my $unmerged;
2992 + while ( <$msg_fh> ) {
2993 + $unmerged=1;last;
2994 + }
2995 + command_close_pipe($msg_fh, $ctx);
2996 + if ( $unmerged ) {
2997 + warn "W:svn cherry-pick ignored ($spec)\n";
2998 + } else {
2999 + warn
3000 + "Found merge parent (svn:mergeinfo prop): ",
3001 + $merge_tip, "\n";
3002 + push @$parents, $merge_tip;
3003 + }
3004 + }
3005 + }
3006 +}
3007 +
3008 sub make_log_entry {
3009 my ($self, $rev, $parents, $ed) = @_;
3010 my $untracked = $self->get_untracked($ed);
@@ -2930,6 +3017,12 @@ sub make_log_entry {
3017 $self->find_extra_svk_parents
3018 ($ed, $props->{"svk:merge"}, \@parents);
3019 }
3020 + if ( $props->{"svn:mergeinfo"} ) {
3021 + $self->find_extra_svn_parents
3022 + ($ed,
3023 + $props->{"svn:mergeinfo"},
3024 + \@parents);
3025 + }
3026 }
3027
3028 open my $un, '>>', "$self->{dir}/unhandled.log" or croak $!;
t/t9151-svn-mergeinfo.sh new
+21
@@ -0,0 +1,21 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2007, 2009 Sam Vilain
4 +#
5 +
6 +test_description='git-svn svn mergeinfo properties'
7 +
8 +. ./lib-git-svn.sh
9 +
10 +test_expect_success 'load svn dump' "
11 + svnadmin load -q '$rawsvnrepo' < '../t9151/svn-mergeinfo.dump' &&
12 + git svn init --minimize-url -R svnmerge \
13 + -T trunk -b branches '$svnrepo' &&
14 + git svn fetch --all
15 + "
16 +
17 +test_expect_success 'svn merges were represented coming in' "
18 + [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
19 + "
20 +
21 +test_done