Skip to content

Commit 3c1ca01

Browse files
committed
Merge git://git.bogomips.org/git-svn
* git://git.bogomips.org/git-svn: git-svn: convert SVN 1.5+ / svnmerge.py svn:mergeinfo props to parents git-svn: add test data for SVN 1.5+ merge, with script. git-svn: convert SVK merge tickets to extra parents git-svn: allow test setup script to support PERL env. var git-svn: add test data for SVK merge, with script. git svn: fix fetch where glob is on the top-level URL
2 parents 4096958 + dff589e commit 3c1ca01

File tree

9 files changed

+1677
-5
lines changed

9 files changed

+1677
-5
lines changed

git-svn.perl

Lines changed: 146 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ sub read_all_remotes {
17651765
my $use_svm_props = eval { command_oneline(qw/config --bool
17661766
svn.useSvmProps/) };
17671767
$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
1768-
my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
1768+
my $svn_refspec = qr{\s*(.*?)\s*:\s*(.+?)\s*};
17691769
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
17701770
if (m!^(.+)\.fetch=$svn_refspec$!) {
17711771
my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
@@ -1979,7 +1979,7 @@ sub find_ref {
19791979
my ($ref_id) = @_;
19801980
foreach (command(qw/config -l/)) {
19811981
next unless m!^svn-remote\.(.+)\.fetch=
1982-
\s*/?(.*?)\s*:\s*(.+?)\s*$!x;
1982+
\s*(.*?)\s*:\s*(.+?)\s*$!x;
19831983
my ($repo_id, $path, $ref) = ($1, $2, $3);
19841984
if ($ref eq $ref_id) {
19851985
$path = '' if ($path =~ m#^\./?#);
@@ -2878,14 +2878,157 @@ sub check_author {
28782878
$author;
28792879
}
28802880

2881+
sub find_extra_svk_parents {
2882+
my ($self, $ed, $tickets, $parents) = @_;
2883+
# aha! svk:merge property changed...
2884+
my @tickets = split "\n", $tickets;
2885+
my @known_parents;
2886+
for my $ticket ( @tickets ) {
2887+
my ($uuid, $path, $rev) = split /:/, $ticket;
2888+
if ( $uuid eq $self->ra_uuid ) {
2889+
my $url = $self->rewrite_root || $self->{url};
2890+
my $repos_root = $url;
2891+
my $branch_from = $path;
2892+
$branch_from =~ s{^/}{};
2893+
my $gs = $self->other_gs($repos_root."/".$branch_from,
2894+
$url,
2895+
$branch_from,
2896+
$rev,
2897+
$self->{ref_id});
2898+
if ( my $commit = $gs->rev_map_get($rev, $uuid) ) {
2899+
# wahey! we found it, but it might be
2900+
# an old one (!)
2901+
push @known_parents, $commit;
2902+
}
2903+
}
2904+
}
2905+
for my $parent ( @known_parents ) {
2906+
my @cmd = ('rev-list', $parent, map { "^$_" } @$parents );
2907+
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
2908+
my $new;
2909+
while ( <$msg_fh> ) {
2910+
$new=1;last;
2911+
}
2912+
command_close_pipe($msg_fh, $ctx);
2913+
if ( $new ) {
2914+
print STDERR
2915+
"Found merge parent (svk:merge ticket): $parent\n";
2916+
push @$parents, $parent;
2917+
}
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+
28813008
sub make_log_entry {
28823009
my ($self, $rev, $parents, $ed) = @_;
28833010
my $untracked = $self->get_untracked($ed);
28843011

3012+
my @parents = @$parents;
3013+
my $ps = $ed->{path_strip} || "";
3014+
for my $path ( grep { m/$ps/ } %{$ed->{dir_prop}} ) {
3015+
my $props = $ed->{dir_prop}{$path};
3016+
if ( $props->{"svk:merge"} ) {
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+
28853028
open my $un, '>>', "$self->{dir}/unhandled.log" or croak $!;
28863029
print $un "r$rev\n" or croak $!;
28873030
print $un $_, "\n" foreach @$untracked;
2888-
my %log_entry = ( parents => $parents || [], revision => $rev,
3031+
my %log_entry = ( parents => \@parents, revision => $rev,
28893032
log => '');
28903033

28913034
my $headrev;

t/lib-git-svn.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ fi
1616
GIT_DIR=$PWD/.git
1717
GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
1818
SVN_TREE=$GIT_SVN_DIR/svn-tree
19+
PERL=${PERL:-perl}
1920

2021
svn >/dev/null 2>&1
2122
if test $? -ne 1
@@ -29,7 +30,7 @@ export svnrepo
2930
svnconf=$PWD/svnconf
3031
export svnconf
3132

32-
perl -w -e "
33+
$PERL -w -e "
3334
use SVN::Core;
3435
use SVN::Repos;
3536
\$SVN::Core::VERSION gt '1.1.0' or exit(42);
@@ -130,7 +131,7 @@ stop_httpd () {
130131
}
131132

132133
convert_to_rev_db () {
133-
perl -w -- - "$@" <<\EOF
134+
$PERL -w -- - "$@" <<\EOF
134135
use strict;
135136
@ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
136137
open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";

t/t9150-svk-mergetickets.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2007 Sam Vilain
4+
#
5+
6+
test_description='git-svn svk merge tickets'
7+
8+
. ./lib-git-svn.sh
9+
10+
test_expect_success 'load svk depot' "
11+
svnadmin load -q '$rawsvnrepo' < '../t9150/svk-merge.dump' &&
12+
git svn init --minimize-url -R svkmerge \
13+
-T trunk -b branches '$svnrepo' &&
14+
git svn fetch --all
15+
"
16+
17+
uuid=b48289b2-9c08-4d72-af37-0358a40b9c15
18+
19+
test_expect_success 'svk merges were represented coming in' "
20+
[ `git-cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
21+
"
22+
23+
test_done

t/t9150/make-svk-dump

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/sh
2+
#
3+
# this script sets up a Subversion repository for Makefile in the
4+
# first ever git merge, as if it were done with svk.
5+
#
6+
7+
set -e
8+
9+
svk depotmap foo ~/.svk/foo
10+
svk co /foo/ foo
11+
cd foo
12+
mkdir trunk
13+
mkdir branches
14+
svk add trunk branches
15+
svk commit -m "Setup trunk and branches"
16+
cd trunk
17+
18+
git cat-file blob 6683463e:Makefile > Makefile
19+
svk add Makefile
20+
21+
svk commit -m "ancestor"
22+
cd ..
23+
svk cp trunk branches/left
24+
25+
svk commit -m "make left branch"
26+
cd branches/left/
27+
28+
git cat-file blob 5873b67e:Makefile > Makefile
29+
svk commit -m "left update 1"
30+
31+
cd ../../trunk
32+
git cat-file blob 75118b13:Makefile > Makefile
33+
svk commit -m "trunk update"
34+
35+
cd ../branches/left
36+
git cat-file blob b5039db6:Makefile > Makefile
37+
svk commit -m "left update 2"
38+
39+
cd ../../trunk
40+
svk sm /foo/branches/left
41+
# in theory we could delete the "left" branch here, but it's not
42+
# required so don't do it, in case people start getting ideas ;)
43+
svk commit -m "merge branch 'left' into 'trunk'"
44+
45+
git cat-file blob b51ad431:Makefile > Makefile
46+
47+
svk diff Makefile && echo "Hey! No differences, magic"
48+
49+
cd ../..
50+
51+
svnadmin dump ~/.svk/foo > svk-merge.dump
52+
53+
svk co -d foo
54+
rm -rf foo
55+
svk depotmap -d /foo/
56+
rm -rf ~/.svk/foo
57+

0 commit comments

Comments
 (0)