Skip to content

Commit

Permalink
Merge git://git.bogomips.org/git-svn
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Junio C Hamano committed Oct 27, 2009
2 parents 4096958 + dff589e commit 3c1ca01
Show file tree
Hide file tree
Showing 9 changed files with 1,677 additions and 5 deletions.
149 changes: 146 additions & 3 deletions git-svn.perl
Original file line number Diff line number Diff line change
Expand Up @@ -1765,7 +1765,7 @@ sub read_all_remotes {
my $use_svm_props = eval { command_oneline(qw/config --bool
svn.useSvmProps/) };
$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
my $svn_refspec = qr{\s*(.*?)\s*:\s*(.+?)\s*};
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
if (m!^(.+)\.fetch=$svn_refspec$!) {
my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
Expand Down Expand Up @@ -1979,7 +1979,7 @@ sub find_ref {
my ($ref_id) = @_;
foreach (command(qw/config -l/)) {
next unless m!^svn-remote\.(.+)\.fetch=
\s*/?(.*?)\s*:\s*(.+?)\s*$!x;
\s*(.*?)\s*:\s*(.+?)\s*$!x;
my ($repo_id, $path, $ref) = ($1, $2, $3);
if ($ref eq $ref_id) {
$path = '' if ($path =~ m#^\./?#);
Expand Down Expand Up @@ -2878,14 +2878,157 @@ sub check_author {
$author;
}

sub find_extra_svk_parents {
my ($self, $ed, $tickets, $parents) = @_;
# aha! svk:merge property changed...
my @tickets = split "\n", $tickets;
my @known_parents;
for my $ticket ( @tickets ) {
my ($uuid, $path, $rev) = split /:/, $ticket;
if ( $uuid eq $self->ra_uuid ) {
my $url = $self->rewrite_root || $self->{url};
my $repos_root = $url;
my $branch_from = $path;
$branch_from =~ s{^/}{};
my $gs = $self->other_gs($repos_root."/".$branch_from,
$url,
$branch_from,
$rev,
$self->{ref_id});
if ( my $commit = $gs->rev_map_get($rev, $uuid) ) {
# wahey! we found it, but it might be
# an old one (!)
push @known_parents, $commit;
}
}
}
for my $parent ( @known_parents ) {
my @cmd = ('rev-list', $parent, map { "^$_" } @$parents );
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
my $new;
while ( <$msg_fh> ) {
$new=1;last;
}
command_close_pipe($msg_fh, $ctx);
if ( $new ) {
print STDERR
"Found merge parent (svk:merge ticket): $parent\n";
push @$parents, $parent;
}
}
}

# note: this function should only be called if the various dirprops
# have actually changed
sub find_extra_svn_parents {
my ($self, $ed, $mergeinfo, $parents) = @_;
# aha! svk:merge property changed...

# We first search for merged tips which are not in our
# history. Then, we figure out which git revisions are in
# that tip, but not this revision. If all of those revisions
# are now marked as merge, we can add the tip as a parent.
my @merges = split "\n", $mergeinfo;
my @merge_tips;
my @merged_commit_ranges;
my $url = $self->rewrite_root || $self->{url};
for my $merge ( @merges ) {
my ($source, $revs) = split ":", $merge;
my $path = $source;
$path =~ s{^/}{};
my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
if ( !$gs ) {
warn "Couldn't find revmap for $url$source\n";
next;
}
my @ranges = split ",", $revs;
my ($tip, $tip_commit);
# find the tip
for my $range ( @ranges ) {
my ($bottom, $top) = split "-", $range;
$top ||= $bottom;
my $bottom_commit =
$gs->rev_map_get($bottom, $self->ra_uuid) ||
$gs->rev_map_get($bottom+1, $self->ra_uuid);
my $top_commit =
$gs->rev_map_get($top, $self->ra_uuid);

unless ($top_commit and $bottom_commit) {
warn "W:unknown path/rev in svn:mergeinfo "
."dirprop: $source:$range\n";
next;
}

push @merged_commit_ranges,
"$bottom_commit..$top_commit";

if ( !defined $tip or $top > $tip ) {
$tip = $top;
$tip_commit = $top_commit;
}
}
unless (!$tip_commit or
grep { $_ eq $tip_commit } @$parents ) {
push @merge_tips, $tip_commit;
} else {
push @merge_tips, undef;
}
}
for my $merge_tip ( @merge_tips ) {
my $spec = shift @merges;
next unless $merge_tip;
my @cmd = ('rev-list', "-1", $merge_tip,
"--not", @$parents );
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
my $new;
while ( <$msg_fh> ) {
$new=1;last;
}
command_close_pipe($msg_fh, $ctx);
if ( $new ) {
push @cmd, @merged_commit_ranges;
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
my $unmerged;
while ( <$msg_fh> ) {
$unmerged=1;last;
}
command_close_pipe($msg_fh, $ctx);
if ( $unmerged ) {
warn "W:svn cherry-pick ignored ($spec)\n";
} else {
warn
"Found merge parent (svn:mergeinfo prop): ",
$merge_tip, "\n";
push @$parents, $merge_tip;
}
}
}
}

sub make_log_entry {
my ($self, $rev, $parents, $ed) = @_;
my $untracked = $self->get_untracked($ed);

my @parents = @$parents;
my $ps = $ed->{path_strip} || "";
for my $path ( grep { m/$ps/ } %{$ed->{dir_prop}} ) {
my $props = $ed->{dir_prop}{$path};
if ( $props->{"svk:merge"} ) {
$self->find_extra_svk_parents
($ed, $props->{"svk:merge"}, \@parents);
}
if ( $props->{"svn:mergeinfo"} ) {
$self->find_extra_svn_parents
($ed,
$props->{"svn:mergeinfo"},
\@parents);
}
}

open my $un, '>>', "$self->{dir}/unhandled.log" or croak $!;
print $un "r$rev\n" or croak $!;
print $un $_, "\n" foreach @$untracked;
my %log_entry = ( parents => $parents || [], revision => $rev,
my %log_entry = ( parents => \@parents, revision => $rev,
log => '');

my $headrev;
Expand Down
5 changes: 3 additions & 2 deletions t/lib-git-svn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fi
GIT_DIR=$PWD/.git
GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
SVN_TREE=$GIT_SVN_DIR/svn-tree
PERL=${PERL:-perl}

svn >/dev/null 2>&1
if test $? -ne 1
Expand All @@ -29,7 +30,7 @@ export svnrepo
svnconf=$PWD/svnconf
export svnconf

perl -w -e "
$PERL -w -e "
use SVN::Core;
use SVN::Repos;
\$SVN::Core::VERSION gt '1.1.0' or exit(42);
Expand Down Expand Up @@ -130,7 +131,7 @@ stop_httpd () {
}

convert_to_rev_db () {
perl -w -- - "$@" <<\EOF
$PERL -w -- - "$@" <<\EOF
use strict;
@ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";
Expand Down
23 changes: 23 additions & 0 deletions t/t9150-svk-mergetickets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/sh
#
# Copyright (c) 2007 Sam Vilain
#

test_description='git-svn svk merge tickets'

. ./lib-git-svn.sh

test_expect_success 'load svk depot' "
svnadmin load -q '$rawsvnrepo' < '../t9150/svk-merge.dump' &&
git svn init --minimize-url -R svkmerge \
-T trunk -b branches '$svnrepo' &&
git svn fetch --all
"

uuid=b48289b2-9c08-4d72-af37-0358a40b9c15

test_expect_success 'svk merges were represented coming in' "
[ `git-cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
"

test_done
57 changes: 57 additions & 0 deletions t/t9150/make-svk-dump
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/sh
#
# this script sets up a Subversion repository for Makefile in the
# first ever git merge, as if it were done with svk.
#

set -e

svk depotmap foo ~/.svk/foo
svk co /foo/ foo
cd foo
mkdir trunk
mkdir branches
svk add trunk branches
svk commit -m "Setup trunk and branches"
cd trunk

git cat-file blob 6683463e:Makefile > Makefile
svk add Makefile

svk commit -m "ancestor"
cd ..
svk cp trunk branches/left

svk commit -m "make left branch"
cd branches/left/

git cat-file blob 5873b67e:Makefile > Makefile
svk commit -m "left update 1"

cd ../../trunk
git cat-file blob 75118b13:Makefile > Makefile
svk commit -m "trunk update"

cd ../branches/left
git cat-file blob b5039db6:Makefile > Makefile
svk commit -m "left update 2"

cd ../../trunk
svk sm /foo/branches/left
# in theory we could delete the "left" branch here, but it's not
# required so don't do it, in case people start getting ideas ;)
svk commit -m "merge branch 'left' into 'trunk'"

git cat-file blob b51ad431:Makefile > Makefile

svk diff Makefile && echo "Hey! No differences, magic"

cd ../..

svnadmin dump ~/.svk/foo > svk-merge.dump

svk co -d foo
rm -rf foo
svk depotmap -d /foo/
rm -rf ~/.svk/foo

Loading

0 comments on commit 3c1ca01

Please sign in to comment.