[svk-commit] r2994 - branches/seek_deleted_to/lib/SVK

nobody at bestpractical.com nobody at bestpractical.com
Tue Jul 15 20:28:16 EDT 2008


Author: ruz
Date: Tue Jul 15 20:27:42 2008
New Revision: 2994

Modified:
   branches/seek_deleted_to/lib/SVK/Path.pm

Log:
* add _seek_to_by_anchor in SVK::Path
** seek_to variant that search the path when path not exist,
   but one of its anchors does
** follow copies as seek_to
** descend if a path shows up
** fix failing test

Modified: branches/seek_deleted_to/lib/SVK/Path.pm
==============================================================================
--- branches/seek_deleted_to/lib/SVK/Path.pm	(original)
+++ branches/seek_deleted_to/lib/SVK/Path.pm	Tue Jul 15 20:27:42 2008
@@ -54,7 +54,8 @@
 use SVK::I18N;
 use autouse 'SVK::Util' => qw( get_anchor catfile abs2rel
 			       IS_WIN32 get_depot_anchor
-			       uri_escape );
+			       uri_escape traverse_history );
+
 use Class::Autouse qw(SVK::Editor::Dynamic SVK::Editor::TxnCleanup SVK::Editor::Tee);
 
 use SVN::Delta;
@@ -771,15 +772,76 @@
 sub seek_to {
     my ($self, $revision) = @_;
 
-    if ($revision < $self->revision) {
-	while (my ($toroot, $fromroot, $path) = $self->nearest_copy) {
-	    last if $toroot->revision_root_revision <= $revision;
-	    $self = $self->mclone( path => $path,
-				   revision => $fromroot->revision_root_revision );
-	}
+    return $self->mclone( revision => $revision )
+        if $revision >= $self->revision;
+
+    # if the path not exist then we should trace back history and watch copies
+    # and descedants
+    if ( $self->root->check_path( $self->path ) == $SVN::Node::none ) {
+        # find a parent that exist
+        my $tmp = $self->mclone( path_anchor => $self->path, targets => undef );
+        while ( $tmp->root->check_path( $tmp->path_anchor ) == $SVN::Node::none ) {
+            $tmp->anchorify;
+        }
+        my $res = $tmp->_seek_to_by_anchor( $revision );
+        return $res if $res;
     }
 
-    return $self->mclone( revision => $revision );
+    while (my ($toroot, $fromroot, $path) = $self->nearest_copy) {
+        last if $toroot->revision_root_revision <= $revision;
+        $self = $self->mclone( path => $path,
+                               revision => $fromroot->revision_root_revision );
+    }
+    return $self->mclone( revision => $revision )
+}
+
+sub _seek_to_by_anchor {
+    my ($self, $revision) = @_;
+
+    my $anchor = $self->path_anchor;
+
+    my ($found_at_rev, $switch_to) = (undef, undef);
+    traverse_history (
+        root  => $self->root,
+        path  => $anchor,
+        cross => 1,
+        callback => sub {
+            my ($path, $rev) = @_;
+            if ($path ne $anchor) {
+                $anchor = $self->path_anchor( $path );
+            }
+
+            if ( $self->as_depotpath( $rev )->root->check_path( $self->path ) != $SVN::Node::none ) {
+                $found_at_rev = $rev < $revision? $revision : $rev;
+                return 0;
+            }
+            return 0 if $rev < $revision;
+            
+            my @target = split m{/}, $self->path_target;
+            return 1 if @target < 2;
+
+            my @left = (shift @target);
+            my @right = (@target);
+
+            while ( @right >= 1 ) {
+                my $deanchored = $self->mclone(
+                    path_anchor => $self->path_anchor .'/'. join( '/', @left ),
+                    targets     => [ join '/', @right ],
+                    revision    => $rev,
+                    _root       => undef,
+                );
+                if ( $deanchored->root->check_path( $deanchored->path_anchor ) == $SVN::Node::none ) {
+                    last;
+                }
+                $switch_to = $deanchored;
+                push @left, shift @right;
+            }
+            return $switch_to? 0 : 1;
+        },
+    );
+    return $switch_to->_seek_to_by_anchor( $revision ) if $switch_to;
+    return $self->mclone( path => $self->path, targets => undef, revision => $found_at_rev )->seek_to( $revision )
+        if defined $found_at_rev;
 }
 
 *path_anchor = __PACKAGE__->make_accessor('path');


More information about the svk-commit mailing list