SVK
view release on metacpan or search on metacpan
lib/SVK/Path/Checkout.pm view on Meta::CPAN
__PACKAGE__->mk_shared_accessors(qw(xd));
__PACKAGE__->mk_clonable_accessors(qw(report source copath_anchor copath_target));
__PACKAGE__->mk_accessors(qw(_pool _inspector));
use Class::Autouse qw(SVK::Editor::XD SVK::Root::Checkout);
use autouse 'SVK::Util' => qw( get_anchor catfile abs2rel get_encoder to_native );
=head1 NAME
SVK::Path::Checkout - SVK path class associating a checkout
=head1 SYNOPSIS
See below
=head1 DESCRIPTION
The class represents a node in svk depot, associated with a checkout
copy.
=cut
sub real_new {
my $class = shift;
my $self = $class->SUPER::real_new(@_);
unless (ref $self->report) {
$self->report($self->_to_pclass($self->report))
if defined $self->report && length $self->report;
}
return $self;
}
sub root {
my $self = shift;
my $root = SVK::Root::Checkout->new({ path => $self });
# XXX: It might not always be the case that we hold svk::path object
# when using the root.
use Scalar::Util 'weaken';
weaken $root->{path};
return $root;
}
sub _mkpath {
my ($root, $path) = @_;
my @path = ();
for my $dir (File::Spec::Unix->splitdir($path)) {
push @path, $dir;
next unless length $dir;
my $cur = File::Spec::Unix->catdir(@path);
$root->make_dir($cur)
unless $root->check_path($cur);
}
}
sub create_xd_root {
my $self = shift;
my $copath = $self->copath($self->copath_target);
my (undef, $coroot) = $self->xd->{checkout}->get($copath, 1);
Carp::cluck $copath.YAML::Syck::Dump($self->xd->{checkout}) unless $coroot;
my @paths = $self->xd->{checkout}->find($coroot, {revision => qr'.*'});
my $tmp = $self->_to_pclass($copath)->relative($coroot)->as_foreign('Unix')->absolute('/');
$tmp = '' if $tmp eq '/';
my $coroot_path = $self->path;
$coroot_path =~ s/\Q$tmp\E$// or return $self->source->root;
$coroot_path = '/' unless length $coroot_path;
my $base_root = $self->source->root;
return $base_root if $#paths <= 0;
my $pool = SVN::Pool->new;
my ($root, $base_rev);
for (@paths) {
$pool->clear;
my $cinfo = $self->xd->{checkout}->get($_);
my $path = abs2rel($_, $coroot => $coroot_path, '/');
unless ($root) {
$root = $base_root->txn_root($self->pool);;
if ($base_root->revision_root_revision == 0) {
# for interrupted checkout, the anchor will be at rev 0
_mkpath($root, $path);
$base_rev = 0;
}
else {
$base_rev = $base_root->node_created_rev($path, $pool);
}
next;
}
my $parent = Path::Class::File->new_foreign('Unix', $path)->parent;
if ($base_rev ==0 && !$root->check_path("$parent", $pool)) {
_mkpath($root, "$parent");
}
next if $cinfo->{revision} == $root->node_created_rev("$parent", $pool);
my ($fromroot, $frompath) = $base_root->get_revision_root($path, $cinfo->{revision}, $pool);
$root->delete($path, $pool)
if eval { $root->check_path ($path, $pool) != $SVN::Node::none };
unless ($cinfo->{'.deleted'}) {
if ($frompath eq $path) {
SVN::Fs::revision_link( $fromroot->root,
$root->root, $path, $pool );
}
else {
SVN::Fs::copy( $fromroot->root, $frompath,
$root->root, $path, $pool );
}
}
}
return $root;
}
=head2 copath
Return the checkout path of the target, optionally with additional
path component.
=cut
my $_copath_catsplit = $^O eq 'MSWin32' ? \&catfile :
sub { defined $_[0] && length $_[0] ? "$_[0]/$_[1]" : "$_[1]" };
sub copath {
my $self = shift;
my $copath = ref($self) ? $self->copath_anchor : shift;
my $paths = shift;
return $copath unless defined $paths && length $paths;
return $_copath_catsplit->($copath, $paths);
}
sub report { __PACKAGE__->make_accessor('report')->(@_) }
sub report_copath {
my ($self, $copath) = @_;
my $report = length($self->report) ? $self->report : undef;
my $rel = abs2rel( $copath, $self->copath_anchor => $report );
# XXX: abs2rel from F::S already does this. tweak S::U abs2rel
# and usage properly
( run in 1.378 second using v1.01-cache-2.11-cpan-5a3173703d6 )