File Coverage

blib/lib/Shipwright/Backend/Base.pm
Criterion Covered Total %
statement 136 415 32.7
branch 25 138 18.1
condition 4 49 8.1
subroutine 26 52 50.0
pod 30 30 100.0
total 221 684 32.3


line stmt bran cond sub pod time code
1             package Shipwright::Backend::Base;
2              
3 5     5   867 use warnings;
  5         9  
  5         177  
4 5     5   25 use strict;
  5         9  
  5         178  
5 5     5   25 use File::Spec::Functions qw/catfile catdir splitpath/;
  5         7  
  5         297  
6 5     5   29 use Shipwright::Util;
  5         8  
  5         452  
7 5     5   26 use File::Temp qw/tempdir/;
  5         7  
  5         217  
8 5     5   523 use File::Copy 'copy';
  5         2003  
  5         267  
9 5     5   549 use File::Copy::Recursive qw/rcopy/;
  5         2797  
  5         286  
10 5     5   27 use File::Path qw/make_path remove_tree/;
  5         7  
  5         238  
11 5     5   2843 use List::MoreUtils qw/uniq firstidx/;
  5         4770  
  5         378  
12 5     5   2716 use Module::Info;
  5         18059  
  5         50  
13              
14             our %REQUIRE_OPTIONS = ( import => [qw/source/] );
15              
16 5     5   252 use base qw/Shipwright::Base/;
  5         8  
  5         21479  
17             __PACKAGE__->mk_accessors(qw/repository log/);
18              
19             =head1 NAME
20              
21             Shipwright::Backend::Base - Base Backend Class
22              
23             =head1 DESCRIPTION
24              
25             Base Backend Class
26              
27             =head1 METHODS
28              
29             =over
30              
31             =item new
32              
33             the constructor
34              
35             =cut
36              
37             sub new {
38 12     12 1 23 my $proto = shift;
39 12   33     104 my $self = bless {@_}, ref $proto || $proto;
40 12         46 return $self->build(@_);
41             }
42              
43             =item build
44              
45             =cut
46              
47             sub build {
48 12     12 1 15 my $self = shift;
49 12         83 $self->log( Log::Log4perl->get_logger( ref $self ) );
50 12         1900 return $self;
51             }
52              
53             sub _subclass_method {
54 0     0   0 my $method = ( caller(0) )[3];
55 0         0 confess_or_die "your should subclass $method\n";
56             }
57              
58             =item initialize
59              
60             initialize a project
61             you should subclass this method, and call this to get the dir with content initialized
62              
63             =cut
64              
65             sub initialize {
66 2     2 1 4 my $self = shift;
67 2         13 my $dir =
68             tempdir( 'shipwright_backend_base_XXXXXX', CLEANUP => 1, TMPDIR => 1 );
69              
70 2 50       1079 rcopy( share_root(), $dir )
71             or confess_or_die "copy share_root failed: $!";
72              
73 2         18877 $self->_install_yaml_tiny($dir);
74 2         1986 $self->_install_clean_inc($dir);
75 2         1376 $self->_install_module_build($dir);
76 2         30 $self->_install_file_compare($dir);
77 2         1919 $self->_install_file_copy_recursive($dir);
78 2         1874 $self->_install_file_path($dir);
79              
80             # set proper permissions for yml under /shipwright/
81 2         1779 my $sw_dir = catdir( $dir, 'shipwright' );
82 2         7 my $sw_dh;
83 2 50       93 opendir $sw_dh, $sw_dir or die "can't opendir $sw_dir: $!";
84 2         65 for my $yml ( grep { /.yml$/ } readdir $sw_dh ) {
  20         47  
85 16         303 chmod 0644, catfile( $dir, 'shipwright', $yml ); ## no critic
86             }
87 2         36 closedir $sw_dh;
88              
89 2         48 chmod 0644, catfile( $dir, 't', 'test' );
90              
91 2         17 return $dir;
92             }
93              
94             sub _install_module_build {
95 2     2   7 my $self = shift;
96 2         5 my $dir = shift;
97 2         13 my $module_build_path = catdir( $dir, 'inc', 'Module', );
98 2         466 make_path( catdir( $module_build_path, 'Build' ) );
99 2 50       18 copy( Module::Info->new_from_module('Module::Build')->file,
100             $module_build_path ) or confess_or_die "copy Module/Build.pm failed: $!";
101 2 50       1252 rcopy(
102             catdir(
103             Module::Info->new_from_module('Module::Build')->inc_dir, 'Module',
104             'Build'
105             ),
106             catdir( $module_build_path, 'Build' )
107             )
108             or confess_or_die "copy Module/Build failed: $!";
109              
110             # Module::Build needs Module::Metadata, Perl::OSType
111 2 50       30189 if ( Module::Info->new_from_module('Perl::OSType') ) {
112 2         1094 make_path( catdir( $dir, 'inc', 'Perl' ) );
113 2 50       14 copy( Module::Info->new_from_module('Perl::OSType')->file,
114             catdir( $dir, 'inc', 'Perl' ) )
115             or confess_or_die "copy Perl/OSType.pm failed: $!";
116             }
117              
118             # Module::Metadata 1.02 requires version 0.87+, which isn't in perl core yet
119             # we can't simply copy version.pm to inc because it's not plain perl.
120             # so here we do a maybe dangerous thing, hack Module::Metadata to not require
121             # version 0.87+
122             # so is Module::Build
123 2         1323 my @files;
124 2 50       94 if ( -e catfile( $dir, 'inc', 'Module', 'Build', 'Version.pm' ) ) {
125 0         0 push @files, catfile( $dir, 'inc', 'Module', 'Build', 'Version.pm' );
126             }
127              
128 2 50       18 if ( Module::Info->new_from_module('Module::Metadata') ) {
129 2 50       575 copy( Module::Info->new_from_module('Module::Metadata')->file,
130             catdir( $dir, 'inc', 'Module' ) )
131             or confess_or_die "copy Module/Metadata.pm failed: $!";
132 2         1329 push @files, catfile( $dir, 'inc', 'Module', 'Metadata.pm' );
133             }
134              
135 2         10 for my $file ( @files ) {
136 2 50       78 open my $fh, '<', $file or die $!;
137 2         12 local $/;
138 2         75 my $content = <$fh>;
139 2 50       60 if ( $content =~ s!use version[^'"]+?(['"]?\s*;)!use version $1;! ) {
140 2 50       42 chmod 0755, $file unless -w $file;
141 2 50       158 open $fh, '>', $file or die $!;
142 2         134 print $fh $content;
143 2         58 close $fh;
144             }
145             }
146             }
147              
148             sub _install_yaml_tiny {
149 2     2   6 my $self = shift;
150 2         5 my $dir = shift;
151              
152 2         12 my $yaml_tiny_path = catdir( $dir, 'inc', 'YAML' );
153 2         572 make_path( $yaml_tiny_path );
154 2 50       25 rcopy( Module::Info->new_from_module('YAML::Tiny')->file, $yaml_tiny_path )
155             or confess_or_die "copy YAML/Tiny.pm failed: $!";
156             }
157              
158             sub _install_clean_inc {
159 2     2   4 my $self = shift;
160 2         5 my $dir = shift;
161 2         9 my $util_inc_path = catdir( $dir, 'inc', 'Shipwright', 'Util' );
162 2         410 make_path( $util_inc_path );
163 2         6 for my $mod ( qw/CleanINC PatchModuleBuild/ ) {
164 4 50       1322 rcopy( Module::Info->new_from_module("Shipwright::Util::$mod")->file,
165             $util_inc_path )
166             or confess_or_die "copy $mod failed: $!";
167             }
168             }
169              
170             sub _install_file_compare {
171 2     2   7 my $self = shift;
172 2         5 my $dir = shift;
173              
174 2         11 my $path = catdir( $dir, 'inc', 'File' );
175 2         318 make_path( $path );
176 2 50       19 rcopy( Module::Info->new_from_module('File::Compare')->file, $path )
177             or confess_or_die "copy File/Compare.pm failed: $!";
178             }
179              
180             sub _install_file_copy_recursive {
181 2     2   7 my $self = shift;
182 2         5 my $dir = shift;
183              
184 2         14 my $path = catdir( $dir, 'inc', 'File', 'Copy' );
185 2         293 make_path( $path );
186 2 50       18 rcopy( Module::Info->new_from_module('File::Copy::Recursive')->file, $path )
187             or confess_or_die "copy File/Copy/Recursive.pm failed: $!";
188             }
189              
190             sub _install_file_path {
191 2     2   5 my $self = shift;
192 2         6 my $dir = shift;
193              
194 2         11 my $path = catdir( $dir, 'inc', 'File' );
195 2 50       13 rcopy( Module::Info->new_from_module('File::Path')->file, $path )
196             or confess_or_die "copy File/Path.pm failed: $!";
197             }
198              
199             =item import
200              
201             import a dist.
202              
203             =cut
204              
205             sub import {
206 2     2   20 my $self = shift;
207 2 50       29 return unless ref $self; # get rid of class->import
208 0         0 my %args = @_;
209 0         0 my $name = ( splitpath( $args{source} ) )[-1];
210              
211 0 0       0 if ( $self->has_branch_support ) {
212 0 0       0 if ( $args{branches} ) {
213 0         0 $args{as} = '';
214             }
215             else {
216 0   0     0 $args{as} ||= 'vendor';
217             }
218             }
219              
220 0 0 0     0 unless ( $args{_initialize} || $args{_extra_tests} ) {
221 0 0       0 if ( $args{_extra_tests} ) {
    0          
222 0 0       0 $self->delete( path => "/t/extra" ) if $args{delete};
223              
224 0         0 $self->log->info( "importing extra tests to " . $self->repository );
225 0         0 for my $cmd ( $self->_cmd( import => %args, name => $name ) ) {
226 0         0 run_cmd($cmd);
227             }
228             }
229             elsif ( $args{build_script} ) {
230 0 0 0     0 if ( $self->info( path => "/scripts/$name" )
231             && not $args{overwrite} )
232             {
233 0         0 $self->log->warn("/scripts/$name exists already");
234             }
235             else {
236 0 0       0 $self->delete( path => "/scripts/$name" ) if $args{delete};
237              
238 0         0 $self->log->info( "importing $args{source}'s scripts to "
239             . $self->repository );
240 0         0 for my $cmd ( $self->_cmd( import => %args, name => $name ) ) {
241 0         0 run_cmd($cmd);
242             }
243 0         0 $self->update_refs;
244              
245             }
246             }
247             else {
248 0 0       0 if ( $self->has_branch_support ) {
249 0 0 0     0 if ( $self->info( path => "/sources/$name/$args{as}" )
250             && not $args{overwrite} )
251             {
252 0         0 $self->log->warn( "sources/$name/$args{as} exists already" );
253             }
254             else {
255 0 0       0 $self->delete( path => "/sources/$name/$args{as}" )
256             if $args{delete};
257 0         0 $self->log->info(
258             "importing $args{source} to " . $self->repository );
259 0         0 $self->_add_to_order($name);
260              
261 0         0 my $version = $self->version;
262 0 0       0 if ( $args{as} ) {
263 0         0 $version->{$name}{$args{as}} = $args{version};
264             }
265             else {
266 0         0 $version->{$name} = $args{version};
267             }
268 0         0 $self->version($version);
269              
270 0         0 my $branches = $self->branches;
271 0 0 0     0 if ( $args{branches} ) {
    0          
272              
273             # mostly this happens when import from another shipwright repo
274 0 0       0 if ( @{ $args{branches} } ) {
  0         0  
275 0         0 $branches->{$name} = $args{branches};
276 0         0 $self->branches($branches);
277             }
278             }
279             elsif (
280             $name !~ /^cpan-/ &&
281             !(
282             $branches->{$name} && grep { $args{as} eq $_ }
283             @{ $branches->{$name} }
284             )
285             )
286             {
287 0 0       0 $branches->{$name} =
288 0         0 [ @{ $branches->{$name} || [] }, $args{as} ];
289 0         0 $self->branches($branches);
290             }
291              
292 0         0 for
293             my $cmd ( $self->_cmd( import => %args, name => $name ) )
294             {
295 0         0 run_cmd($cmd);
296             }
297             }
298             }
299             else {
300 0 0 0     0 if ( $self->info( path => "/dists/$name" )
301             && not $args{overwrite} )
302             {
303 0         0 $self->log->warn( "dists/$name exists already" );
304             }
305             else {
306 0 0       0 $self->delete( path => "/dists/$name" ) if $args{delete};
307 0         0 $self->log->info(
308             "importing $args{source} to " . $self->repository );
309 0         0 $self->_add_to_order($name);
310              
311 0         0 my $version = $self->version;
312 0         0 $version->{$name} = $args{version};
313 0         0 $self->version($version);
314              
315 0         0 for
316             my $cmd ( $self->_cmd( import => %args, name => $name ) )
317             {
318 0         0 run_cmd($cmd);
319             }
320             }
321             }
322             }
323             }
324             else {
325 0         0 for my $cmd ( $self->_cmd( import => %args, name => $name ) ) {
326 0         0 run_cmd($cmd);
327             }
328             }
329             }
330              
331             =item export
332              
333              
334             =cut
335              
336             sub export {
337 0     0 1 0 my $self = shift;
338 0         0 my %args = @_;
339 0   0     0 my $path = $args{path} || '';
340 0         0 $self->log->info(
341             'exporting ' . $self->repository . "/$path to $args{target}" );
342 0         0 for my $cmd ( $self->_cmd( export => %args ) ) {
343 0         0 run_cmd($cmd);
344             }
345             }
346              
347             =item checkout
348              
349             =cut
350              
351             sub checkout {
352 0     0 1 0 my $self = shift;
353 0         0 my %args = @_;
354 0   0     0 my $path = $args{path} || '';
355 0         0 $self->log->info(
356             'exporting ' . $self->repository . "/$path to $args{target}" );
357 0         0 for my $cmd ( $self->_cmd( checkout => %args ) ) {
358 0         0 run_cmd($cmd);
359             }
360             }
361              
362             =item commit
363              
364             A wrapper around svn's commit command.
365              
366             =cut
367              
368             sub commit {
369 0     0 1 0 my $self = shift;
370 0         0 my %args = @_;
371 0         0 $self->log->info( 'committing ' . $args{path} );
372 0         0 for my $cmd ( $self->_cmd( commit => @_ ) ) {
373 0         0 run_cmd( $cmd, 1 );
374             }
375             }
376              
377             sub _add_to_order {
378 0     0   0 my $self = shift;
379 0         0 my $name = shift;
380              
381 0         0 my $order = $self->order;
382              
383 0 0       0 unless ( grep { $name eq $_ } @$order ) {
  0         0  
384 0         0 $self->log->info( "adding $name to order for " . $self->repository );
385 0         0 push @$order, $name;
386 0         0 $self->order($order);
387             }
388             }
389              
390             =item update_order
391              
392             regenerate the dependency order.
393              
394             =cut
395              
396             sub update_order {
397 0     0 1 0 my $self = shift;
398 0         0 my %args = @_;
399              
400 0         0 $self->log->info( "updating order for " . $self->repository );
401              
402 0 0       0 my @dists = @{ $args{for_dists} || [] };
  0         0  
403 0 0       0 unless (@dists) {
404 0         0 @dists = $self->dists;
405             }
406              
407 0         0 s{/$}{} for @dists;
408              
409 0         0 my $require = {};
410              
411 0         0 for (@dists) {
412 0         0 $self->_fill_deps( %args, require => $require, name => $_ );
413             }
414              
415 0         0 require Algorithm::Dependency::Ordered;
416 0         0 require Algorithm::Dependency::Source::HoA;
417              
418 0         0 my $source = Algorithm::Dependency::Source::HoA->new($require);
419 0         0 $source->load();
420 0 0       0 my $dep = Algorithm::Dependency::Ordered->new( source => $source, )
421             or confess_or_die $@;
422 0         0 my $order = $dep->schedule_all();
423              
424 0         0 $self->order($order);
425             }
426              
427             =item graph_deps
428              
429             return a dependency graph in graphviz format
430              
431             =cut
432              
433             sub graph_deps {
434 0     0 1 0 my $self = shift;
435 0         0 my %args = @_;
436              
437 0         0 $self->log->info( "outputting a graphviz order for " . $self->repository );
438              
439 0 0       0 my @dists = @{ $args{for_dists} || [] };
  0         0  
440 0 0       0 unless (@dists) {
441 0         0 @dists = $self->dists;
442             }
443              
444 0         0 s{/$}{} for @dists;
445              
446 0         0 my $require = {};
447              
448 0         0 for my $distname (@dists) {
449 0         0 $self->_fill_deps( %args, require => $require, name => $distname );
450             }
451              
452 0         0 my $out = 'digraph g {
453             graph [ overlap = scale, rankdir= LR ];
454             node [ fontsize = "18", shape = record, fontsize = 18 ];
455             ';
456              
457 0         0 for my $dist (@dists) {
458 0         0 $out .= qq{ "$dist" [shape = record, fontsize = 18, label = "$dist" ];\n};
459 0         0 for my $dep ( @{ $require->{$dist} } ) {
  0         0  
460 0         0 $out .= qq{"$dist" -> "$dep";\n};
461             }
462             }
463 0         0 $out .= "\n};";
464 0         0 return $out;
465             }
466              
467             sub _fill_deps {
468 0     0   0 my $self = shift;
469 0         0 my %args = @_;
470 0         0 my $require = $args{require};
471 0         0 my $name = $args{name};
472              
473 0 0       0 return if $require->{$name};
474 0   0     0 my $req = $self->requires( name => $name ) || {};
475              
476 0 0       0 if ( $req->{requires} ) {
477 0         0 for (qw/requires recommends build_requires test_requires/) {
478 0 0       0 push @{ $require->{$name} }, keys %{ $req->{$_} }
  0         0  
  0         0  
479             unless $args{"skip_$_"};
480             }
481             }
482             else {
483              
484             #for back compatbility
485 0         0 push @{ $require->{$name} }, keys %$req;
  0         0  
486             }
487 0         0 @{ $require->{$name} } = uniq @{ $require->{$name} };
  0         0  
  0         0  
488              
489 0         0 for my $dep ( @{ $require->{$name} } ) {
  0         0  
490 0 0       0 next if $require->{$dep};
491 0         0 $self->_fill_deps( %args, name => $dep );
492             }
493             }
494              
495             sub _yml {
496 0     0   0 my $self = shift;
497 0         0 my $path = shift;
498 0         0 my $yml = shift;
499              
500 0         0 my $file = catfile( $self->repository, $path );
501 0 0       0 if ($yml) {
502              
503 0         0 dump_yaml_file( $file, $yml );
504             }
505             else {
506 0         0 load_yaml_file($file);
507             }
508             }
509              
510             =item order
511              
512             get or set the dependency order.
513              
514             =cut
515              
516             sub order {
517 0     0 1 0 my $self = shift;
518 0         0 my $order = shift;
519 0         0 my $path = '/shipwright/order.yml';
520 0         0 return $self->_yml( $path, $order );
521             }
522              
523             =item map
524              
525             get or set the map.
526              
527             =cut
528              
529             sub map {
530 0     0 1 0 my $self = shift;
531 0         0 my $map = shift;
532              
533 0         0 my $path = '/shipwright/map.yml';
534 0         0 return $self->_yml( $path, $map );
535             }
536              
537             =item source
538              
539             get or set the sources map.
540              
541             =cut
542              
543             sub source {
544 0     0 1 0 my $self = shift;
545 0         0 my $source = shift;
546 0         0 my $path = '/shipwright/source.yml';
547 0         0 return $self->_yml( $path, $source );
548             }
549              
550             =item flags
551              
552             get or set flags.
553              
554             =cut
555              
556             sub flags {
557 5     5 1 43678 my $self = shift;
558 5         10 my $flags = shift;
559              
560 5         8 my $path = '/shipwright/flags.yml';
561 5         22 return $self->_yml( $path, $flags );
562             }
563              
564             =item version
565              
566             get or set version.
567              
568             =cut
569              
570             sub version {
571 0     0 1 0 my $self = shift;
572 0         0 my $version = shift;
573              
574 0         0 my $path = '/shipwright/version.yml';
575 0         0 return $self->_yml( $path, $version );
576             }
577              
578             =item branches
579              
580             get or set branches.
581              
582             =cut
583              
584             sub branches {
585 0     0 1 0 my $self = shift;
586 0         0 my $branches = shift;
587              
588 0 0       0 if ( $self->has_branch_support ) {
589 0         0 my $path = '/shipwright/branches.yml';
590 0         0 return $self->_yml( $path, $branches );
591             }
592              
593             # no branches support in 1.x
594 0         0 return;
595             }
596              
597             =item ktf
598              
599             get or set known failure conditions.
600              
601             =cut
602              
603             sub ktf {
604 0     0 1 0 my $self = shift;
605 0         0 my $ktf = shift;
606 0         0 my $path = '/shipwright/known_test_failures.yml';
607              
608 0         0 return $self->_yml( $path, $ktf );
609             }
610              
611             =item refs
612              
613             get or set refs
614              
615             =cut
616              
617             sub refs {
618 0     0 1 0 my $self = shift;
619 0         0 my $refs = shift;
620 0         0 my $path = '/shipwright/refs.yml';
621              
622 0         0 return $self->_yml( $path, $refs );
623             }
624              
625             =item delete
626              
627              
628             =cut
629              
630             sub delete {
631 2     2 1 5 my $self = shift;
632 2         7 my %args = @_;
633 2   50     46 my $path = $args{path} || '';
634 2 50       13 if ( $self->info( path => $path ) ) {
635 2         28 $self->log->info( "deleting " . $self->repository . $path );
636 2         27 for my $cmd ( $self->_cmd( delete => path => $path ) ) {
637 2         7 run_cmd( $cmd, 1 );
638             }
639             }
640             }
641              
642             =item list
643              
644              
645             =cut
646              
647             sub list {
648 0     0 1 0 my $self = shift;
649 0         0 my %args = @_;
650 0   0     0 my $path = $args{path} || '';
651 0 0       0 if ( $self->info( path => $path ) ) {
652 0         0 my $out = run_cmd( $self->_cmd( list => path => $path ) );
653 0         0 return $out;
654             }
655             }
656              
657             =item dists
658              
659              
660             =cut
661              
662             sub dists {
663 0     0 1 0 my $self = shift;
664 0         0 my %args = @_;
665 0         0 my $out = $self->list( path => '/scripts' );
666 0         0 return split /\s+/, $out;
667             }
668              
669             =item move
670              
671             =cut
672              
673             sub move {
674 0     0 1 0 my $self = shift;
675 0         0 my %args = @_;
676 0   0     0 my $path = $args{path} || '';
677 0   0     0 my $new_path = $args{new_path} || '';
678 0 0       0 if ( $self->info( path => $path ) ) {
679 0         0 $self->log->info(
680             "moving " . $self->repository . "/$path to /$new_path" );
681 0         0 for my $cmd (
682             $self->_cmd(
683             move => path => $path,
684             new_path => $new_path,
685             )
686             )
687             {
688 0         0 run_cmd($cmd);
689             }
690             }
691             }
692              
693             =item info
694              
695             =cut
696              
697             sub info {
698 4     4 1 8 my $self = shift;
699 4         9 my %args = @_;
700 4   100     26 my $path = $args{path} || '';
701              
702 4         16 my ( $info, $err ) =
703             run_cmd( $self->_cmd( info => path => $path ), 1 );
704 4 50       21 $self->log->warn($err) if $err;
705              
706 4 50       15 if (wantarray) {
707 4         14 return $info, $err;
708             }
709             else {
710 0         0 return $info;
711             }
712             }
713              
714             =item requires
715              
716             return the hashref of require.yml for a dist.
717              
718             =cut
719              
720             sub requires {
721 0     0 1 0 my $self = shift;
722 0         0 my %args = @_;
723 0         0 my $name = $args{name};
724              
725 0         0 return $self->_yml( "/scripts/$name/require.yml" );
726             }
727              
728             =item check_repository
729              
730             Check if the given repository is valid.
731              
732             =cut
733              
734             sub check_repository {
735 2     2 1 1 my $self = shift;
736 2         5 my %args = @_;
737              
738 2 50       4 if ( $args{action} eq 'create' ) {
739 0         0 return 1;
740             }
741             else {
742              
743             # every valid shipwright repo has '/shipwright' subdir;
744 2         7 my $info = $self->info( path => '/shipwright' );
745              
746 2 100       9 return 1 if $info;
747             }
748 1         6 return;
749             }
750              
751             =item update
752              
753             you should subclass this method, and run this to get the file path with latest version
754              
755             =cut
756              
757             sub update {
758 0     0 1 0 my $self = shift;
759 0         0 my %args = @_;
760              
761 0 0       0 confess_or_die "need path option" unless $args{path};
762              
763 0 0       0 if ( $args{path} =~ m{/$} ) {
764             # it's a directory
765 0 0 0     0 if ( $args{path} eq '/inc/' && ! $args{source} ) {
    0          
766 0         0 my $dir = tempdir(
767             'shipwright_backend_base_XXXXXX',
768             CLEANUP => 1,
769             TMPDIR => 1,
770             );
771 0         0 $self->_install_yaml_tiny($dir);
772 0         0 $self->_install_clean_inc($dir);
773 0         0 $self->_install_module_build($dir);
774 0         0 $self->_update_dir( '/inc/', catdir($dir, 'inc') );
775             }
776             elsif ( $args{source} ) {
777 0         0 $self->_update_dir( $args{path}, $args{source} );
778             }
779             }
780             else {
781              
782 0 0       0 confess_or_die "$args{path} seems not shipwright's own file"
783             unless -e catfile( share_root(), $args{path} );
784              
785 0         0 return $self->_update_file( $args{path},
786             catfile( share_root(), $args{path} ) );
787             }
788             }
789              
790             =item test_script
791              
792             get or set test_script for a project, i.e. /t/test
793              
794             =cut
795              
796             sub test_script {
797 0     0 1 0 my $self = shift;
798 0         0 my %args = @_;
799              
800 0 0       0 if ( $args{source} ) {
801 0         0 $self->_update_file( '/t/test', $args{source} );
802             }
803             else {
804 0         0 return $self->cat( path => '/t/test' );
805             }
806             }
807              
808             =item trim
809              
810             trim dists
811              
812             =cut
813              
814             sub trim {
815 0     0 1 0 my $self = shift;
816 0         0 my %args = @_;
817 0         0 my @names_to_trim;
818              
819 0 0       0 if ( ref $args{name} ) {
820 0         0 @names_to_trim = @{ $args{name} };
  0         0  
821             }
822             else {
823 0         0 @names_to_trim = $args{name};
824             }
825              
826 0         0 my $order = $self->order;
827 0         0 my $map = $self->map;
828 0   0     0 my $version = $self->version || {};
829 0   0     0 my $source = $self->source || {};
830 0   0     0 my $flags = $self->flags || {};
831              
832 0         0 for my $name (@names_to_trim) {
833 0 0       0 if ( $self->has_branch_support ) {
834 0         0 $self->delete( path => "/sources/$name" );
835             }
836             else {
837 0         0 $self->delete( path => "/sources/$name" );
838             }
839 0         0 $self->delete( path => "/scripts/$name" );
840              
841             # clean order.yml
842 0         0 @$order = grep { $_ ne $name } @$order;
  0         0  
843              
844             # clean map.yml
845 0         0 for ( keys %$map ) {
846 0 0       0 delete $map->{$_} if $map->{$_} eq $name;
847             }
848              
849             # clean version.yml, source.yml and flags.yml
850              
851 0         0 for my $hashref ( $source, $flags, $version ) {
852 0         0 for ( keys %$hashref ) {
853 0 0       0 if ( $_ eq $name ) {
854 0         0 delete $hashref->{$_};
855 0         0 last;
856             }
857             }
858             }
859              
860             }
861 0         0 $self->version($version);
862 0         0 $self->map($map);
863 0         0 $self->source($source);
864 0         0 $self->flags($flags);
865 0         0 $self->order($order);
866 0         0 $self->update_refs;
867             }
868              
869             =item update_refs
870              
871             update refs.
872              
873             we need update this after import and trim
874              
875             =cut
876              
877             sub update_refs {
878 0     0 1 0 my $self = shift;
879 0         0 my $order = $self->order;
880 0         0 my $refs = {};
881              
882 0         0 for my $name (@$order) {
883              
884             # initialize here, in case we don't have $name entry in $refs
885 0   0     0 $refs->{$name} ||= 0;
886              
887 0   0     0 my $req = $self->requires( name => $name ) || {};
888              
889 0         0 my @deps;
890 0 0       0 if ( $req->{requires} ) {
891 0         0 @deps = (
892 0         0 keys %{ $req->{requires} },
893 0         0 keys %{ $req->{recommends} },
894 0         0 keys %{ $req->{build_requires} },
895 0         0 keys %{ $req->{test_requires} }
896             );
897             }
898             else {
899              
900             #for back compatbility
901 0         0 @deps = keys %$req;
902             }
903              
904 0         0 @deps = uniq @deps;
905              
906 0         0 for (@deps) {
907 0         0 $refs->{$_}++;
908             }
909             }
910              
911 0         0 $self->refs($refs);
912             }
913              
914             =item has_branch_support
915              
916             return true if has branch support
917              
918             =cut
919              
920             sub has_branch_support {
921 0     0 1 0 my $self = shift;
922 0 0       0 return 1 if $self->info( path => '/shipwright/branches.yml' );
923 0         0 return;
924             }
925              
926             *_initialize_local_dir = *_cmd = *_update_file = *_update_dir =
927             *_subclass_method;
928              
929             =item local_dir
930              
931             for vcs backend, we made a local checkout/clone version, which will live here
932              
933             =cut
934              
935             sub local_dir {
936 0     0 1 0 my $self = shift;
937 0         0 my $need_init = shift;
938 0         0 my $base_dir =
939             catdir( shipwright_user_root(), 'backends' );
940 0 0       0 make_path( $base_dir ) unless -e $base_dir;
941 0         0 my $repo = $self->repository;
942 0         0 $repo =~ s/:/-/g;
943 0         0 $repo =~ s![/\\]!_!g;
944 0         0 my $target = catdir( $base_dir, $repo );
945 0         0 return $target;
946              
947             }
948              
949             =item strip_repository
950              
951             =cut
952              
953             sub strip_repository {
954 11     11 1 15 my $self = shift;
955 11         45 my $repo = $self->repository;
956 11         73 $repo =~ s/^[a-z+]+://;
957 11         34 $self->repository($repo);
958 11         27 return;
959             }
960              
961             =back
962              
963             =cut
964              
965             1;
966             __END__