SVK

 view release on metacpan or  search on metacpan

lib/SVK/Path.pm  view on Meta::CPAN

	  } );
}

=head2 $self->seek_to($revision)

Return the C<SVK::Path> object that C<$self> is at C<$revision>.  Note
that we don't have forward tracing, so if <$revision is greater than
C<$self->revision>, a C<SVK::Path> at <$revision> will be returned.
In other words, assuming C<foo@N> for C<-r N foo@M> when N > M.

=cut

sub seek_to {
    my ($self, $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;
    }

    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');
push @{__PACKAGE__->_clonable_accessors}, 'path_anchor';

sub path_target { $_[0]->{targets}[0] || '' }

use Data::Dumper;
sub dump { warn Dumper($_[0]) }

sub prev {
    my ($self) = shift;
    my $prev = $self->as_depotpath($self->revision-1);

    eval { $prev->normalize; 1 } or return ;

    return $prev;
}

=head1 as_url($local_only, [ $path, $rev ])

Returns (url, revision) pair.

=cut

sub as_url {
    my ($self, $local_only) = @_;
    my ($path, $rev) = ($_[2] || $self->path_anchor, $_[3] || $self->revision);

    if (!$local_only && (my $m = $self->is_mirrored)) {
        my ($m_path, $m_url) = ($m->path, $m->url);
	$path =~ s/^\Q$m_path\E/$m_url/;
	$path =~ s/%/%25/g;
	$path = uri_escape($path);
        if (my $remote_rev = $m->find_remote_rev($rev)) {
            $rev = $remote_rev;



( run in 1.729 second using v1.01-cache-2.11-cpan-71847e10f99 )