[svk-commit] r2693 - in trunk: . lib/SVK/Command lib/SVK/Editor lib/SVK/Mirror/Backend t/mirror
nobody at bestpractical.com
nobody at bestpractical.com
Fri Feb 8 04:10:41 EST 2008
Author: clkao
Date: Fri Feb 8 04:10:40 2008
New Revision: 2693
Added:
trunk/lib/SVK/Editor/FilterProp.pm
trunk/t/mirror/sync-rebase-delta.t
trunk/t/mirror/sync-rebase-multi.t
trunk/t/mirror/sync-rebase.t
Modified:
trunk/ (props changed)
trunk/MANIFEST
trunk/lib/SVK/Command/Sync.pm
trunk/lib/SVK/Editor/Composite.pm
trunk/lib/SVK/Mirror.pm
trunk/lib/SVK/Mirror/Backend/SVNRa.pm
trunk/lib/SVK/Mirror/Backend/SVNRaPipe.pm
Log:
Support mirroring source that the anchor or parent was
renamed.
r4412 at mtl: clkao | 2008-02-07 21:23:23 +0800
- Create branch sync-rebase
r4413 at mtl: clkao | 2008-02-08 01:21:17 +0800
first cut of sync following anchor copy support.
r4414 at mtl: clkao | 2008-02-08 02:41:01 +0800
make follow-anchor-copy not defualt.
r4415 at mtl: clkao | 2008-02-08 04:29:38 +0800
rebase - deal with additional changes on the revision of rebase.
r4420 at mtl: clkao | 2008-02-08 14:43:31 +0800
filterprop editor.
r4421 at mtl: clkao | 2008-02-08 14:44:17 +0800
in composite editor, use exists rather than defined to
see if anchor_baton is given.
r4422 at mtl: clkao | 2008-02-08 14:48:06 +0800
new tests.
r4423 at mtl: clkao | 2008-02-08 16:43:14 +0800
refactor _sync_edge_changeset.
r4424 at mtl: clkao | 2008-02-08 17:03:46 +0800
make mutliple rebase and rebase at parent dir work.
Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST (original)
+++ trunk/MANIFEST Fri Feb 8 04:10:40 2008
@@ -76,6 +76,7 @@
lib/SVK/Editor/Delay.pm
lib/SVK/Editor/Diff.pm
lib/SVK/Editor/Dynamic.pm
+lib/SVK/Editor/FilterProp.pm
lib/SVK/Editor/InteractiveCommitter.pm
lib/SVK/Editor/InteractiveStatus.pm
lib/SVK/Editor/MapRev.pm
@@ -307,6 +308,9 @@
t/mirror/sync-empty.t
t/mirror/sync-escape.t
t/mirror/sync-failed-hook.t
+t/mirror/sync-rebase-delta.t
+t/mirror/sync-rebase-mutli.t
+t/mirror/sync-rebase.t
t/mirror/sync-replaced-nocopy.t
t/mirror/sync-replaced.t
t/mirror/sync-replicate.t
Modified: trunk/lib/SVK/Command/Sync.pm
==============================================================================
--- trunk/lib/SVK/Command/Sync.pm (original)
+++ trunk/lib/SVK/Command/Sync.pm Fri Feb 8 04:10:40 2008
@@ -59,6 +59,7 @@
sub options {
('s|skipto=s' => 'skip_to',
'a|all' => 'sync_all',
+ 'follow-anchor-copy' => 'follow_anchor_copy',
't|torev=s' => 'torev');
}
@@ -87,7 +88,7 @@
$logger->error(loc( "%1 does not contain a valid depotname",
$orig_arg ));
next;
- }
+ }
my @tempnewarg = grep { SVK::Path->_to_pclass( "/$path", 'Unix' )->subsumes($_) }
$depot->mirror->entries;
@@ -104,6 +105,9 @@
my $error;
for my $m (@mirrors) {
+ # XXX: in svk::mirrorcatalog, mirror objects are cached. we
+ # might want per-instance options applied when using ->get.
+ $m->follow_anchor_copy(1) if $self->{follow_anchor_copy};
my $run_sync = sub {
$m->sync_snapshot($self->{skip_to}) if $self->{skip_to};
$m->run( $self->{torev} );
Modified: trunk/lib/SVK/Editor/Composite.pm
==============================================================================
--- trunk/lib/SVK/Editor/Composite.pm (original)
+++ trunk/lib/SVK/Editor/Composite.pm Fri Feb 8 04:10:40 2008
@@ -53,6 +53,8 @@
use SVK::Version; our $VERSION = $SVK::VERSION;
use base 'SVK::Editor';
+__PACKAGE__->mk_accessors(qw(master_editor));
+
=head1 NAME
SVK::Editor::Composite - composite editor
@@ -75,11 +77,14 @@
$func =~ s/^.*:://;
return if $func =~ m/^[A-Z]/;
- if ($func =~ m/^(?:add|open|delete)/) {
+ if ($func eq 'open_root') {
+ }
+ elsif ($func =~ m/^(?:add|open|delete)/) {
return $self->{target_baton}
if defined $self->{target} && $arg[0] eq $self->{target};
$arg[0] = length $arg[0] ?
- "$self->{anchor}/$arg[0]" : $self->{anchor};
+ "$self->{anchor}/$arg[0]" : $self->{anchor}
+ if defined $self->{anchor};
}
elsif ($func =~ m/^close_(?:file|directory)/) {
if (defined $arg[0]) {
@@ -90,14 +95,16 @@
}
}
- $self->{master_editor}->$func(@arg);
+ $self->master_editor->$func(@arg);
}
sub set_target_revision {}
sub open_root {
- my ($self, $base_revision) = @_;
- return $self->{anchor_baton};
+ my $self = shift;
+ return $self->{anchor_baton} if exists $self->{anchor_baton};
+
+ return $self->master_editor->open_root(@_)
}
sub close_edit {}
Added: trunk/lib/SVK/Editor/FilterProp.pm
==============================================================================
--- (empty file)
+++ trunk/lib/SVK/Editor/FilterProp.pm Fri Feb 8 04:10:40 2008
@@ -0,0 +1,74 @@
+# BEGIN BPS TAGGED BLOCK {{{
+# COPYRIGHT:
+#
+# This software is Copyright (c) 2003-2006 Best Practical Solutions, LLC
+# <clkao at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of either:
+#
+# a) Version 2 of the GNU General Public License. You should have
+# received a copy of the GNU General Public License along with this
+# program. If not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 or visit
+# their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
+#
+# b) Version 1 of Perl's "Artistic License". You should have received
+# a copy of the Artistic License with this package, in the file
+# named "ARTISTIC". The license is also available at
+# http://opensource.org/licenses/artistic-license.php.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of the
+# GNU General Public License and is only of importance to you if you
+# choose to contribute your changes and enhancements to the community
+# by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with SVK,
+# to Best Practical Solutions, LLC, you confirm that you are the
+# copyright holder for those contributions and you grant Best Practical
+# Solutions, LLC a nonexclusive, worldwide, irrevocable, royalty-free,
+# perpetual, license to use, copy, create derivative works based on
+# those contributions, and sublicense and distribute those contributions
+# and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+package SVK::Editor::FilterProp;
+use strict;
+use warnings;
+
+use base 'SVK::Editor::ByPass';
+
+__PACKAGE__->mk_accessors(qw(cb_prop));
+
+sub AUTOLOAD {
+ my ($self, @arg) = @_;
+ my $func = our $AUTOLOAD;
+ $func =~ s/^.*:://;
+ return if $func =~ m/^[A-Z]+$/;
+
+ if ($func =~ m/^change.*prop/) {
+ $self->cb_prop->(@arg[1,2]) or return;
+ warn "==> $arg[1]";
+ }
+
+ $func = "SUPER::$func";
+ $self->$func(@arg);
+}
+
+1;
Modified: trunk/lib/SVK/Mirror.pm
==============================================================================
--- trunk/lib/SVK/Mirror.pm (original)
+++ trunk/lib/SVK/Mirror.pm Fri Feb 8 04:10:40 2008
@@ -61,7 +61,7 @@
use base 'Class::Accessor::Fast';
-__PACKAGE__->mk_accessors(qw(depot path server_uuid source_uuid pool url _backend _locked));
+__PACKAGE__->mk_accessors(qw(depot path server_uuid source_uuid pool url _backend _locked follow_anchor_copy));
*repos = sub { Carp::cluck unless $_[0]->depot; shift->depot->repos };
Modified: trunk/lib/SVK/Mirror/Backend/SVNRa.pm
==============================================================================
--- trunk/lib/SVK/Mirror/Backend/SVNRa.pm (original)
+++ trunk/lib/SVK/Mirror/Backend/SVNRa.pm Fri Feb 8 04:10:40 2008
@@ -60,6 +60,8 @@
use SVK::Editor::MapRev;
use SVK::Util 'IS_WIN32';
use SVK::Logger;
+use SVK::Editor::FilterProp;
+use SVK::Editor::Composite;
use Class::Autouse qw(SVK::Editor::SubTree SVK::Editor::CopyHandler SVK::Editor::Translate);
@@ -94,7 +96,7 @@
sub new {
my ( $class, $args ) = @_;
unless ( defined $args->{use_pipeline} ) {
- $args->{use_pipeline} = IS_WIN32 ? 0 : 1;
+ $args->{use_pipeline} = 0;#IS_WIN32 ? 0 : 1;
}
return $class->SUPER::new($args);
}
@@ -452,7 +454,7 @@
=cut
sub traverse_new_changesets {
- my ($self, $code, $torev) = @_;
+ my ($self, $code, $torev, $cross, $want_paths) = @_;
$self->refresh;
my $from = ($self->fromrev || 0)+1;
my $to = defined $torev ? $torev : -1;
@@ -462,11 +464,11 @@
return if $from > $to;
$logger->info( "Retrieving log information from $from to $to");
eval {
- $ra->get_log([''], $from, $to, 0,
- 0, 1,
+ $ra->get_log([''], $from, $to, 0,
+ $want_paths, !$cross,
sub {
my ($paths, $rev, $author, $date, $msg, $pool) = @_;
- $code->($rev, { author => $author, date => $date, message => $msg });
+ $code->($rev, { author => $author, date => $date, message => $msg }, $paths);
});
};
$self->_ra_finished($ra);
@@ -478,7 +480,7 @@
=cut
sub sync_changeset {
- my ( $self, $changeset, $metadata, $ra, $extra_prop, $callback ) = @_;
+ my ( $self, $changeset, $metadata, $extra_prop, $callback, $delta_generator, $translate_from ) = @_;
my $t = $self->mirror->get_svkpath;
my ( $editor, undef, %opt ) = $t->get_editor(
ignore_mirror => 1,
@@ -497,9 +499,9 @@
}
$self->_revmap_prop( $opt{txn}, $changeset );
- $editor = $self->_get_sync_editor($editor, $changeset);
- $ra->replay( $changeset, 0, 1, $editor );
- $self->_after_replay($ra, $editor);
+ $editor = $self->_get_sync_editor($editor, $changeset, $translate_from);
+
+ $delta_generator->( $editor, $opt{txn});
return;
@@ -525,7 +527,7 @@
}
sub _get_sync_editor {
- my ($self, $oeditor, $changeset) = @_;
+ my ($self, $oeditor, $changeset, $translate_from) = @_;
my $editor = SVK::Editor::CopyHandler->new(
_editor => $oeditor,
@@ -533,7 +535,8 @@
my ( undef, $path, $rev, $current_path, $pb ) = @_;
return ( $path, $rev ) if $rev == -1;
my $source_path = $self->source_path;
- $path =~ s/^\Q$self->{source_path}//;
+ my $copy_prefix = $translate_from || $self->source_path;
+ $path =~ s/^\Q$copy_prefix//;
my $lrev = $self->find_rev_from_changeset($rev, 1);
if ($lrev == -1) {
# vivify the copy that we don't have
@@ -567,8 +570,8 @@
# ra->replay gives us editor calls based on repos root not
# base uri, so we need to get the correct subtree.
my $baton;
- if ( length $self->source_path ) {
- my $anchor = substr( $self->source_path, 1 );
+ if ( $translate_from || length $self->source_path ) {
+ my $anchor = substr( $translate_from || $self->source_path, 1 );
$baton = $editor->open_root(-1); # XXX: should use $t->revision
$editor = SVK::Editor::SubTree->new(
{ master_editor => $editor,
@@ -577,6 +580,7 @@
}
);
}
+
return $editor;
}
@@ -594,30 +598,134 @@
my ( $self, $torev, $callback, $fake_last ) = @_;
$self->mirror->with_lock(
'mirror',
- sub { $self->_mirror_changesets( $torev, $callback, $fake_last ) } );
+ sub { $self->refresh;
+ $self->_mirror_changesets( $torev, $callback, $fake_last ) } );
+}
+
+sub _sync_edge_changeset {
+ my ($self, $revdata, $callback, $translate_from) = @_;
+
+ my $paths = $revdata->[2];
+ unless ($paths) {
+ my $ra = $self->_new_ra;
+
+ $ra->get_log([''], $revdata->[0], $revdata->[0], 0,
+ 1, 1, sub { $paths = shift; } );
+ $self->_ra_finished($ra);
+ }
+
+ my ($entry, $old_path, $old_rev) = $self->_find_edge_entry( $paths, $translate_from || $self->source_path ) or return;
+
+ $self->_mirror_changesets( $revdata->[0], $callback, 0, $old_path );
+
+ my $ra = $self->_new_ra;
+ $ra->reparent( $self->source_root . $entry->copyfrom_path );
+
+ $self->sync_changeset
+ ( $revdata->[0], $revdata->[1], {},
+ $callback,
+ sub {
+ my ($editor, $txn) = @_;
+ $editor = $editor->master_editor;
+ $editor = SVK::Editor::Composite->new( { master_editor => $editor } );
+ $editor = SVK::Editor::FilterProp->new
+ ( { cb_prop => sub { return $_[0] !~ m/^svn:(wc|entry)/; },
+ _editor => [ $editor ] } );
+ my $report = $ra->do_diff($revdata->[0], '', 1, 1, $self->source_root.$self->source_path, $editor);
+ $report->set_path('', $entry->copyfrom_rev, 0, undef );
+ $report->finish_report;
+ if ( %{$txn->root->paths_changed} ) {
+ $editor->master_editor->close_edit;
+ }
+ }) ;
+
+}
+
+sub _find_edge_entry {
+ my ($self, $paths, $translate_from) = @_;
+
+ for (reverse sort keys %$paths) {
+ if (Path::Class::Dir->new_foreign("Unix", $_)
+ ->subsumes($translate_from)) {
+ my $entry = $paths->{$_};
+ if ($entry->action eq 'A' && $entry->copyfrom_path) {
+ return ($entry,
+ SVK::Util::abs2rel($translate_from, $_ => $entry->copyfrom_path),
+ $entry->copyfrom_rev);
+ }
+ }
+ }
+ return;
}
sub _mirror_changesets {
- my ( $self, $torev, $callback, $fake_last ) = @_;
- $self->refresh;
+ my ( $self, $torev, $callback, $fake_last, $translate_from ) = @_;
my @revs;
- $self->traverse_new_changesets( sub { push @revs, [@_] unless $fake_last && $torev && $_[0] == $torev}, $torev );
+ my $cross = $translate_from ? 1 : 0;
+ $self->traverse_new_changesets( sub { push @revs, [@_] unless $fake_last && $torev && $_[0] == $torev}, $torev, $cross, $cross );
+
+ # the last revision belongs to our caller, so don't sync it.
+ pop @revs if $cross;
+
return unless @revs;
+ if ($cross) {
+ # if we are in cross mode, our @revs might already contain
+ # renames that we need to segment with different
+ # translate_from
+ my $tmp_translate_from = $translate_from;
+ my (@batch, @newrev);
+ for (reverse @revs) {
+ my $paths = $_->[-1];
+ my ($entry, $old_path, $oldrev) = $self->_find_edge_entry($paths, $tmp_translate_from || $self->source_path);
+ unless ($entry) {
+ unshift @newrev, $_;
+ next;
+ }
+
+ unshift @batch, [\@newrev, $_, $old_path];
+ @newrev = ();
+ $tmp_translate_from = $old_path;
+ }
+ for (@batch) {
+ my ($revs, $edge, $t) = @$_;
+ $self->_sync_changesets($callback, $revs, $t);
+ $self->_sync_edge_changeset($edge, $callback, $_);
+ }
+
+ }
+ # get the first revision and see if it's renamed from somewhere else
+
+ if ($self->mirror->follow_anchor_copy && !$cross) {
+ $self->_sync_edge_changeset(shift @revs, $callback, $translate_from);
+ }
+
+ $self->_sync_changesets($callback, \@revs, $translate_from);
+
+}
+sub _sync_changesets {
+ my ($self, $callback, $revs, $translate_from) = @_;
# prepare generator for pipelined ra
my @gen;
# XXX: this is so wrong
my $revprop = $self->mirror->depot->mirror->revprop;
+
my $ra = $self->_new_ra;
+
+ $ra->reparent( $translate_from
+ ? $self->source_root . $translate_from
+ : $self->mirror->url)
+ if $translate_from;
+
if ( $self->use_pipeline ) {
- for (@revs) {
+ for (@$revs) {
push @gen, [ 'rev_proplist', $_->[0] ] if $revprop;
push @gen, [ 'replay', $_->[0], 0, 1, 'EDITOR' ];
}
$ra = SVK::Mirror::Backend::SVNRaPipe->new( $ra, sub { shift @gen } );
}
my $pool = SVN::Pool->new_default;
- for (@revs) {
+ for (@$revs) {
$pool->clear;
my ( $changeset, $metadata ) = @$_;
my $extra_prop = {};
@@ -628,8 +736,12 @@
if exists $prop->{$_};
}
}
- $self->sync_changeset( $changeset, $metadata, $ra, $extra_prop,
- $callback );
+ $self->sync_changeset( $changeset, $metadata, $extra_prop,
+ $callback, sub {
+ my $editor = shift;
+ $ra->replay( $changeset, 0, 1, $editor );
+ $self->_after_replay($ra, $editor);
+ }, $translate_from );
}
$self->_ra_finished($ra);
}
Modified: trunk/lib/SVK/Mirror/Backend/SVNRaPipe.pm
==============================================================================
--- trunk/lib/SVK/Mirror/Backend/SVNRaPipe.pm (original)
+++ trunk/lib/SVK/Mirror/Backend/SVNRaPipe.pm Fri Feb 8 04:10:40 2008
@@ -241,6 +241,14 @@
return $data->[0];
}
+sub reparent {
+ my $self = shift;
+ $self->ensure_client_cmd('reparent', @_);
+ # read synchronous msg
+ my $data = thaw( ${$self->read_msg} );
+ die 'inconsistent response' unless $data->[1] eq 'reparent';
+ return $data->[0];
+}
sub replay {
my $self = shift;
Added: trunk/t/mirror/sync-rebase-delta.t
==============================================================================
--- (empty file)
+++ trunk/t/mirror/sync-rebase-delta.t Fri Feb 8 04:10:40 2008
@@ -0,0 +1,52 @@
+#!/usr/bin/perl -w
+use strict;
+use Test::More;
+use SVK::Test;
+eval { require SVN::Mirror; 1 } or plan skip_all => 'require SVN::Mirror';
+plan tests => 5;
+
+my ($xd, $svk) = build_test('test');
+
+our $output;
+
+$svk->mkdir(-pm => 'init', '/test/foo/proj/trunk');
+$svk->mkdir(-pm => 'init', '/test/foo/proj/branches');
+my $tree = create_basic_tree ($xd, '/test/foo/proj/trunk');
+
+$svk->cp('-m' => 'branch', '/test/foo/proj/trunk' => '/test/foo/proj/branches/branchA');
+
+my ($copath, $corpath) = get_copath ('sync-rebase-delta');
+
+$svk->checkout ('/test/', $copath);
+$svk->mv("$copath/foo/proj" => "$copath/proj");
+$svk->mkdir("$copath/proj/lalala");
+# XXX: after the commit there are stalled sticky entries in checkout
+# DH, please check.
+is_output($svk, 'ci', [-m => 'mv but with some modification', $copath],
+ [ "Committed revision 6." ]);
+
+$svk->cp(-m => 'branch2', '/test/proj/trunk' => '/test/proj/branches/branchB');
+
+my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/proj', 1);
+my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
+
+
+$svk->mi('//mirror/proj', $uri);
+
+is_output($svk, 'sync', ['--follow-anchor-copy','//mirror/proj'],
+ ["Syncing $uri",
+ 'Retrieving log information from 1 to 7',
+ 'Retrieving log information from 1 to 6',
+ 'Committed revision 2 from revision 1.',
+ 'Committed revision 3 from revision 2.',
+ 'Committed revision 4 from revision 3.',
+ 'Committed revision 5 from revision 4.',
+ 'Committed revision 6 from revision 5.',
+ 'Committed revision 7 from revision 6.',
+ 'Committed revision 8 from revision 7.']);
+
+is_output($svk, 'ls', ['//mirror/proj'],
+ ['branches/', 'lalala/', 'trunk/'] );
+is_ancestor($svk, "//mirror/proj/branches/branchA", '/mirror/proj/trunk', 5);
+is_ancestor($svk, "//mirror/proj/branches/branchB", '/mirror/proj/trunk', 5);
+
Added: trunk/t/mirror/sync-rebase-multi.t
==============================================================================
--- (empty file)
+++ trunk/t/mirror/sync-rebase-multi.t Fri Feb 8 04:10:40 2008
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+use strict;
+use Test::More;
+use SVK::Test;
+eval { require SVN::Mirror; 1 } or plan skip_all => 'require SVN::Mirror';
+plan tests => 4;
+
+my ($xd, $svk) = build_test('test');
+
+our $output;
+
+$svk->mkdir(-pm => 'init', '/test/foo/bar/proj/trunk');
+$svk->mkdir(-pm => 'init', '/test/foo/bar/proj/branches');
+my $tree = create_basic_tree ($xd, '/test/foo/bar/proj/trunk');
+
+$svk->cp('-m' => 'branch', '/test/foo/bar/proj/trunk' => '/test/foo/bar/proj/branches/branchA');
+
+my ($copath, $corpath) = get_copath ('sync-rebase-delta');
+
+$svk->mv(-m => 'move it', '/test/foo' => '/test/blah');
+
+$svk->cp(-m => 'branch2', '/test/blah/bar/proj/trunk' => '/test/blah/bar/proj/branches/branchB');
+
+$svk->mv(-m => 'move it', '/test/blah/bar/proj' => '/test/proj');
+
+$svk->cp(-m => 'branch3', '/test/proj/trunk' => '/test/proj/branches/branchC');
+
+my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/proj', 1);
+my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
+
+
+$svk->mi('//mirror/proj', $uri);
+
+is_output($svk, 'sync', ['--follow-anchor-copy','//mirror/proj'],
+ ["Syncing $uri",
+ 'Retrieving log information from 1 to 9',
+ 'Retrieving log information from 1 to 8',
+ 'Committed revision 2 from revision 1.',
+ 'Committed revision 3 from revision 2.',
+ 'Committed revision 4 from revision 3.',
+ 'Committed revision 5 from revision 4.',
+ 'Committed revision 6 from revision 5.',
+ 'Committed revision 7 from revision 7.',
+ 'Committed revision 8 from revision 9.']);
+
+is_ancestor($svk, "//mirror/proj/branches/branchA", '/mirror/proj/trunk', 5);
+is_ancestor($svk, "//mirror/proj/branches/branchB", '/mirror/proj/trunk', 5);
+is_ancestor($svk, "//mirror/proj/branches/branchC", '/mirror/proj/trunk', 5);
+
Added: trunk/t/mirror/sync-rebase.t
==============================================================================
--- (empty file)
+++ trunk/t/mirror/sync-rebase.t Fri Feb 8 04:10:40 2008
@@ -0,0 +1,42 @@
+#!/usr/bin/perl -w
+use strict;
+use Test::More;
+use SVK::Test;
+eval { require SVN::Mirror; 1 } or plan skip_all => 'require SVN::Mirror';
+plan tests => 3;
+
+my ($xd, $svk) = build_test('test');
+
+our $output;
+
+$svk->mkdir(-pm => 'init', '/test/foo/proj/trunk');
+$svk->mkdir(-pm => 'init', '/test/foo/proj/branches');
+my $tree = create_basic_tree ($xd, '/test/foo/proj/trunk');
+
+$svk->cp('-m' => 'branch', '/test/foo/proj/trunk' => '/test/foo/proj/branches/branchA');
+
+$svk->mv(-m => 'relocate proj base', '/test/foo/proj' => '/test/proj');
+
+$svk->cp(-m => 'branch2', '/test/proj/trunk' => '/test/proj/branches/branchB');
+
+my ($srepospath, $spath, $srepos) = $xd->find_repos ('/test/proj', 1);
+my $uri = uri($srepospath.($spath eq '/' ? '' : $spath));
+
+
+$svk->mi('//mirror/proj', $uri);
+
+is_output($svk, 'sync', ['--follow-anchor-copy','//mirror/proj'],
+ ["Syncing $uri",
+ 'Retrieving log information from 1 to 7',
+ 'Retrieving log information from 1 to 6',
+ 'Committed revision 2 from revision 1.',
+ 'Committed revision 3 from revision 2.',
+ 'Committed revision 4 from revision 3.',
+ 'Committed revision 5 from revision 4.',
+ 'Committed revision 6 from revision 5.',
+ 'Committed revision 7 from revision 7.']);
+
+
+is_ancestor($svk, "//mirror/proj/branches/branchA", '/mirror/proj/trunk', 5);
+is_ancestor($svk, "//mirror/proj/branches/branchB", '/mirror/proj/trunk', 5);
+
More information about the svk-commit
mailing list