File Coverage

blib/lib/Shipwright/Backend/SVK.pm
Criterion Covered Total %
statement 24 130 18.4
branch 0 58 0.0
condition 0 14 0.0
subroutine 8 19 42.1
pod 4 4 100.0
total 36 225 16.0


line stmt bran cond sub pod time code
1             package Shipwright::Backend::SVK;
2              
3 3     3   684 use warnings;
  3         4  
  3         87  
4 3     3   11 use strict;
  3         3  
  3         82  
5 3     3   10 use File::Spec::Functions qw/catfile/;
  3         3  
  3         125  
6 3     3   11 use Shipwright::Util;
  3         2  
  3         237  
7 3     3   1035 use File::Copy::Recursive qw/rcopy/;
  3         9811  
  3         199  
8 3     3   18 use File::Path qw/remove_tree/;
  3         3  
  3         170  
9              
10             our %REQUIRE_OPTIONS = ( import => [qw/source/] );
11              
12 3     3   12 use base qw/Shipwright::Backend::Base/;
  3         2  
  3         2341  
13              
14             =head1 NAME
15              
16             Shipwright::Backend::SVK - SVK repository backend
17              
18             =head1 SYNOPSIS
19              
20             shipwright create -r svk:/depot/shipwright/my_proj
21              
22             =head1 DESCRIPTION
23              
24             This module implements an L based backend
25             for Shipwright L.
26              
27             =head1 ENVIRONMENT VARIABLES
28              
29             =over 4
30              
31             =item SHIPWRIGHT_SVK - path of F command, default value is F.
32              
33             =back
34              
35             L can be used as well.
36              
37             =head1 METHODS
38              
39             =over 4
40              
41             =item build
42              
43             =cut
44              
45             sub build {
46 4     4 1 4 my $self = shift;
47 4         17 $self->strip_repository;
48 4         19 $self->SUPER::build(@_);
49             }
50              
51             =item initialize
52              
53             initialize a project.
54              
55             =cut
56              
57             sub initialize {
58 0     0 1   my $self = shift;
59 0           my $dir = $self->SUPER::initialize(@_);
60              
61 0           $self->delete; # clean repository in case it exists
62 0           $self->import(
63             source => $dir,
64             _initialize => 1,
65             comment => 'created project',
66             );
67 0           $self->_initialize_local_dir;
68             }
69              
70             sub _svnroot {
71 0     0     my $self = shift;
72 0 0         return $self->{svnroot} if $self->{svnroot};
73 0           my $depotmap = run_cmd( [ $ENV{'SHIPWRIGHT_SVK'} => depotmap => '--list' ] );
74 0           $depotmap =~ s{\A.*?^(?=/)}{}sm;
75 0           while ($depotmap =~ /^(\S*)\s+(.*?)$/gm) {
76 0           my ($depot, $svnroot) = ($1, $2);
77 0 0         if ($self->repository =~ /^$depot(.*)/) {
78 0           return $self->{svnroot} = "file://$svnroot/$1";
79             }
80             }
81 0           confess_or_die "Can't find determine underlying SVN repository for ". $self->repository;
82             }
83              
84             # a cmd generating factory
85             sub _cmd {
86 0     0     my $self = shift;
87 0           my $type = shift;
88 0           my %args = @_;
89 0   0       $args{path} ||= '';
90 0   0       $args{comment} ||= '';
91              
92 0           for ( @{ $REQUIRE_OPTIONS{$type} } ) {
  0            
93 0 0         confess_or_die "$type need option $_" unless $args{$_};
94             }
95              
96 0           my @cmd;
97              
98 0 0         if ( $type eq 'checkout' ) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
99 0 0         if ( $args{detach} ) {
100 0           @cmd = [ $ENV{'SHIPWRIGHT_SVK'}, 'checkout', '-d', $args{target} ];
101             }
102             else {
103 0           @cmd = [
104             $ENV{'SHIPWRIGHT_SVK'}, 'checkout',
105             $self->repository . $args{path}, $args{target}
106             ];
107             }
108             }
109             elsif ( $type eq 'export' ) {
110 0           @cmd = (
111             [
112             $ENV{'SHIPWRIGHT_SVN'}, 'export',
113             $self->_svnroot . $args{path}, $args{target}
114             ],
115             );
116             }
117             elsif ( $type eq 'list' ) {
118 0           @cmd = [ $ENV{'SHIPWRIGHT_SVN'}, 'list', $self->_svnroot . $args{path} ];
119             }
120             elsif ( $type eq 'import' ) {
121 0 0         if ( $args{_initialize} ) {
    0          
122 0   0       @cmd = [
123             $ENV{'SHIPWRIGHT_SVK'}, 'import', $args{source},
124             $self->repository . ( $args{path} || '' ),
125             '-m', $args{comment},
126             ];
127             }
128             elsif ( $args{_extra_tests} ) {
129 0           @cmd = [
130             $ENV{'SHIPWRIGHT_SVK'}, 'import',
131             $args{source}, $self->repository . '/t/extra',
132             '-m', $args{comment},
133             ];
134             }
135             else {
136 0           my ( $path, $source );
137 0 0         if ( $args{build_script} ) {
138 0           $path = "/scripts/$args{name}";
139 0           $source = $args{build_script};
140             }
141             else {
142 0 0         $path =
143             $self->has_branch_support
144             ? "/sources/$args{name}/$args{as}"
145             : "/dists/$args{name}";
146 0           $source = $args{source};
147             }
148              
149 0 0         if ( $self->info( path => $path ) ) {
150             @cmd = (
151             sub {
152 0     0     $self->_sync_local_dir( $path );
153 0           remove_tree( $self->local_dir . $path );
154 0           rcopy( $source, $self->local_dir . $path, );
155             },
156             [
157 0           $ENV{'SHIPWRIGHT_SVK'}, 'commit',
158             '--import', $self->local_dir . $path,
159             '-m', $args{comment}
160             ],
161             );
162             }
163             else {
164 0           @cmd = [
165             $ENV{'SHIPWRIGHT_SVK'}, 'import',
166             $source, $self->repository . $path,
167             '-m', $args{comment},
168             ];
169             }
170             }
171              
172             }
173             elsif ( $type eq 'commit' ) {
174 0 0         @cmd = [
175             $ENV{'SHIPWRIGHT_SVK'},
176             'commit',
177             (
178             $args{import}
179             ? '--import'
180             : ()
181             ),
182             '-m',
183             $args{comment},
184             $args{path}
185             ];
186             }
187             elsif ( $type eq 'delete' ) {
188 0           @cmd = [
189             $ENV{'SHIPWRIGHT_SVK'}, 'delete',
190             '-m', 'delete repository',
191             $self->repository . $args{path},
192             ];
193             }
194             elsif ( $type eq 'move' ) {
195 0           @cmd = [
196             $ENV{'SHIPWRIGHT_SVK'},
197             'move',
198             '-m',
199             "move $args{path} to $args{new_path}",
200             $self->repository . $args{path},
201             $self->repository . $args{new_path}
202             ];
203             }
204             elsif ( $type eq 'info' ) {
205 0           @cmd = [ $ENV{'SHIPWRIGHT_SVK'}, 'info', $self->repository . $args{path} ];
206             }
207             elsif ( $type eq 'cat' ) {
208 0           @cmd = [ $ENV{'SHIPWRIGHT_SVN'}, 'cat', $self->_svnroot . $args{path} ];
209             }
210             else {
211 0           confess_or_die "invalid command: $type";
212             }
213              
214 0           return @cmd;
215             }
216              
217             sub _yml {
218 0     0     my $self = shift;
219 0           my $path = shift;
220 0           my $yml = shift;
221              
222 0           my $file = catfile( $self->local_dir . $path );
223              
224 0 0         if ($yml) {
225 0 0         if ( $path =~ /scripts/ ) {
226 0           $self->_sync_local_dir('/scripts');
227             }
228             else {
229 0           $self->_sync_local_dir($path);
230             }
231 0           dump_yaml_file( $file, $yml );
232 0           $self->commit( path => $file, comment => "updated $path" );
233             }
234             else {
235 0           my ($out) = run_cmd(
236             [ $ENV{'SHIPWRIGHT_SVN'}, 'cat', $self->_svnroot . $path ] );
237 0           return load_yaml($out);
238             }
239             }
240              
241             =item info
242              
243             a wrapper around svk's info command.
244              
245             =cut
246              
247             sub info {
248 0     0 1   my $self = shift;
249 0           my ( $info, $err ) = $self->SUPER::info(@_);
250              
251 0 0         if (wantarray) {
252 0           return $info, $err;
253             }
254             else {
255 0 0         return if $info =~ /not exist|not a checkout path/;
256 0           return $info;
257             }
258             }
259              
260             =item check_repository
261              
262             check if the given repository is valid.
263              
264             =cut
265              
266             sub check_repository {
267 0     0 1   my $self = shift;
268 0           my %args = @_;
269              
270 0 0         if ( $args{action} eq 'create' ) {
271              
272 0           my $repo = $self->repository;
273 0           my ( $info, $err ) = $self->info;
274 0 0         if ($err) {
275 0           $err =~ s{\s+$}{ };
276 0           $self->log->fatal( $err, "maybe root of $repo does not exist?" );
277 0           return;
278             }
279              
280 0 0 0       return 1
      0        
281             if $args{force} || $info =~ /not exist/ || $info =~ /Revision: 0/;
282              
283 0           $self->log->fatal("$repo has commits already");
284 0           return;
285             }
286             else {
287 0           return $self->SUPER::check_repository(@_);
288             }
289 0           return;
290             }
291              
292             sub _update_file {
293 0     0     my $self = shift;
294 0           my $path = shift;
295 0           my $latest = shift;
296              
297 0           my $file = $self->local_dir . $path;
298 0           $self->_sync_local_dir( $path );
299              
300 0 0         rcopy( $latest, $file ) or confess_or_die "can't copy $latest to $file: $!";
301 0           $self->commit(
302             path => $file,
303             comment => "updated $path",
304             );
305             }
306              
307             sub _update_dir {
308 0     0     my $self = shift;
309 0           my $path = shift;
310 0           my $latest = shift;
311              
312 0           $self->_sync_local_dir( $path );
313 0           my $dir = $self->local_dir . $path;
314 0           remove_tree( $dir );
315 0 0         rcopy( $latest, $dir ) or confess_or_die "can't copy $latest to $dir: $!";
316 0           $self->commit(
317             path => $dir,
318             comment => "updated $path",
319             import => 1,
320             );
321             }
322              
323             sub _initialize_local_dir {
324 0     0     my $self = shift;
325             # the 0 is very important, or it may results in recursion
326 0           my $target = $self->local_dir( 0 );
327 0 0         remove_tree( $target ) if -e $target;
328              
329 0           run_cmd(
330             [ $ENV{'SHIPWRIGHT_SVK'}, 'checkout', $self->repository, $target ] );
331 0           return $target;
332             }
333              
334             sub _sync_local_dir {
335 0     0     my $self = shift;
336 0   0       my $path = shift || '';
337              
338 0           run_cmd(
339             [ $ENV{'SHIPWRIGHT_SVK'}, 'update', $self->local_dir . $path ] );
340             }
341              
342             =back
343              
344             =cut
345              
346             1;
347              
348             __END__