File Coverage

blib/lib/Bio/Gonzales/Project.pm
Criterion Covered Total %
statement 90 134 67.1
branch 12 48 25.0
condition 4 19 21.0
subroutine 28 36 77.7
pod 1 7 14.2
total 135 244 55.3


line stmt bran cond sub pod time code
1             package Bio::Gonzales::Project;
2              
3 13     13   19732 use Mouse;
  13         383634  
  13         76  
4              
5 13     13   5962 use warnings;
  13         26  
  13         338  
6 13     13   78 use strict;
  13         14  
  13         261  
7 13     13   66 use Carp;
  13         50  
  13         869  
8 13     13   8510 use FindBin;
  13         15597  
  13         565  
9 13     13   92 use File::Spec;
  13         26  
  13         289  
10 13     13   65 use Scalar::Util qw/readonly/;
  13         26  
  13         735  
11 13     13   7266 use Bio::Gonzales::Util::File qw/slurpc/;
  13         38  
  13         1170  
12 13     13   5898 use Bio::Gonzales::Util::Cerial;
  13         38  
  13         1070  
13 13     13   7522 use Bio::Gonzales::Util::Development::File;
  13         39  
  13         703  
14 13     13   8105 use Data::Rmap qw/rmap_scalar rmap_to :types/;
  13         18355  
  13         2889  
15 13     13   7644 use Bio::Gonzales::Util::Log;
  13         39  
  13         619  
16             use Data::Printer {
17 13         142 indent => 2,
18             colored => '0',
19             use_prototypes => 0,
20             rc_file => '',
21 13     13   17798 };
  13         479186  
22              
23 13     13   17188 use POSIX;
  13         39  
  13         117  
24              
25 13     13   26690 use 5.010;
  13         52  
26              
27             our $VERSION = '0.083'; # VERSION
28              
29             has '_config_key_cache' => ( is => 'rw', default => sub { {} } );
30             has '_nfi_cache' => ( is => 'rw', default => sub { {} } );
31             has 'analysis_version' => ( is => 'rw', builder => '_build_analysis_version' );
32             has '_substitute_conf' => ( is => 'rw', lazy_build => 1 );
33             has 'config' => ( is => 'rw', lazy_build => 1 );
34             has 'merge_av_config' => ( is => 'rw', default => 1 );
35             has 'log' => ( is => 'rw', builder => '_build_log' );
36             has 'config_file' => ( is => 'rw', default => 'gonz.conf.yml' );
37             has 'analysis_name' => ( is => 'rw', lazy_build => 1 );
38              
39             sub _build_analysis_name {
40 1     1   4 my ($self) = @_;
41              
42 1         67 return ( File::Spec->splitdir( File::Spec->rel2abs('.') ) )[-1];
43             }
44              
45             sub _build_analysis_version {
46 1     1   3 my ($self) = @_;
47              
48 1         3 my $av;
49 1 50       6 if ( $ENV{ANALYSIS_VERSION} ) {
    0          
50 1         3 $av = $ENV{ANALYSIS_VERSION};
51             } elsif ( -f 'av' ) {
52 0         0 $av = ( slurpc('av') )[0];
53             } else {
54 0         0 carp "using current dir as output dir";
55 0         0 $av = '.';
56             }
57 1         4 return _prepare_av($av);
58             }
59              
60             sub _build__substitute_conf {
61 1     1   14 my ($self) = @_;
62              
63             my %subs = (
64 1     1   15 an => sub { return $self->analysis_name },
65 1     1   7 av => sub { return $self->analysis_version },
66 0     0   0 path_to => sub { return $self->path_to(@_) },
67 1     1   12 data => sub { return $self->path_to('data') },
68 1         18 );
69              
70 1         7 my $subsre = join "|", keys %subs;
71              
72             return sub {
73 6 50   6   17 return unless defined $_[0];
74             # boolean values in YAML::XS are readonly. Take care of this.
75 6 50       18 return $_[0] if(readonly($_[0]));
76              
77 6         14 $_[0] =~ s{ ^ ~ ( [^/]* ) }
78             { $1
79 1 50 33     9 ? (getpwnam($1))[7]
80             : ( $ENV{HOME} || (getpwuid($>))[7] )
81             }ex;
82 6 50       81  
  3         21  
83 6         36 $_[0] =~ s{__($subsre)(?:\((.+?)\))?__}{ $subs{ $1 }->( $2 ? split( /,/, $2 ) : () ) }eg;
84             return $_[0];
85 1         8 }
86             }
87              
88 1     1   4 sub _build_log {
89             my ($self) = @_;
90 1         6  
91             return Bio::Gonzales::Util::Log->new(
92             path => $self->_nfi('gonz.log'),
93             level => 'info',
94             namespace => $FindBin::Script
95             );
96             }
97              
98 1     1   17 sub _build_config {
99             my ($self) = @_;
100 1         3  
101 1         4 my $conf;
102 1         7 my $conf_f = $self->config_file;
103             my $sub = $self->_substitute_conf;
104 1 50       19  
105 1         6 if ( -f $conf_f ) {
106 1   50     10 $conf = yslurp($conf_f);
107             $conf //= {};
108 1 50       5  
109             confess "configuration file >> $conf_f << is not a hash/dictionary structure"
110 1         10 if ( ref $conf ne 'HASH' );
111 1     6   29 $self->log->info("reading >> $conf_f <<");
  6         388  
112             rmap_to { $sub->($_) } VALUE, $conf;
113             }
114 1         43  
115 1 50 33     46 my $av_conf_f = join( ".", $self->analysis_version, "conf", "yml" );
      33        
116             if ( $self->merge_av_config && $av_conf_f !~ /^\./ && -f $av_conf_f ) {
117 0         0  
118 0 0       0 my $av_conf = yslurp($av_conf_f);
119             confess "configuration file >> $av_conf_f << is not a hash/dictionary structure"
120             if ( ref $av_conf ne 'HASH' );
121 0         0  
122 0     0   0 $self->log->info("reading >> $av_conf_f <<");
  0         0  
123             rmap_to { $sub->($_) } VALUE, $conf;
124 0         0  
125             $conf = { %$conf, %$av_conf };
126 1         16 }
127             return $conf;
128             }
129              
130 1     1 1 1966 sub BUILD {
131             my ($self) = @_;
132 1         5  
133             my $av = $self->analysis_version;
134              
135 1 50       53 $self->log->info("invoked ($av)") # if a script is run, log it
136             if ( !$ENV{GONZLOG_SILENT} );
137             }
138              
139             around 'analysis_version' => sub {
140             my $orig = shift;
141             my $self = shift;
142              
143             return $self->$orig()
144             unless @_;
145              
146             return $self->$orig( _prepare_av(shift) );
147             };
148              
149 1     1   3 sub _prepare_av {
150 1 50       9 my $av = shift;
    50          
151 0         0 if ( !$av ) {
152             return '.';
153 1 50       99 } elsif ( $av =~ /^[-A-Za-z_.0-9]+$/ ) {
154             mkdir $av unless ( -d $av );
155 0   0     0 } else {
156 0         0 carp "analysis version not or not correctly specified, variable contains: " . ( $av // 'nothing' );
157 0         0 carp "using current dir as output dir";
158             return '.';
159 1         19 }
160             return $av;
161             }
162 0     0 0 0  
163             sub av { shift->analysis_version(@_) }
164 0     0 0 0  
165             sub c { shift->conf(@_) }
166              
167 0     0 0 0 sub nfi {
168             my $self = shift;
169 0         0  
170             my $f = $self->_nfi(@_);
171              
172             # only log it once per filename
173 0 0       0 $self->log->info("(nfi) > $f <")
174             unless ( $self->_nfi_cache->{$f}++ );
175 0         0  
176             return $f;
177             }
178              
179 1     1   2 sub _nfi {
180 1         5 my $self = shift;
181             return File::Spec->catfile( $self->analysis_version, @_ );
182             }
183              
184 0     0 0   sub conf {
185             my ( $self, @keys ) = @_;
186 0            
187             my $data = $self->config;
188 0            
189 0 0         for my $k (@keys) {
190 0           confess "empty key supplied" unless ($k);
191 0 0 0       my $r = ref $data;
    0 0        
192 0 0         if ( $r && $r eq 'HASH' ) {
193 0           if ( exists( $data->{$k} ) ) {
194             $data = $data->{$k};
195 0           } else {
196             $self->log->fatal_confess("$k not found in gonzconf");
197             }
198 0 0         } elsif ( $r && $r eq 'ARRAY' ) {
199 0           if ( exists( $data->[$k] ) ) {
200             $data = $data->[$k];
201 0           } else {
202             $self->log->fatal_confess("$k not found in gonzconf");
203             }
204 0           } else {
205             $self->log->fatal_confess("$k not found in gonzconf");
206             }
207 0 0         }
208 0           if (@keys) {
209             my $k = join( " ", @keys );
210 0 0         $self->log->info( "(gonzconf) > " . $k . " <", np($data) )
211             unless ( $self->_config_key_cache->{ '_' . $k }++ );
212              
213             } else {
214 0 0         $self->log->info( "(gonzconf) dump", np($data) )
215             unless ( $self->_config_key_cache->{'_'}++ );
216 0           }
217             return $data;
218             }
219              
220 0     0 0   sub path_to {
221             my $self = shift;
222 0            
223             my $home = Bio::Gonzales::Util::Development::File::find_root(
224             {
225             location => '.',
226             dirs => [ '.git', 'analysis', ],
227             files => ['Makefile']
228             }
229             );
230 0 0          
231             confess "Could not find project home"
232 0           unless ($home);
233             return File::Spec->catfile( $home, @_ );
234             }
235              
236 0     0 0   sub analysis_path {
237             my $self = shift;
238 0            
239             return $self->path_to( "analysis", @_ );
240             }
241              
242             __PACKAGE__->meta->make_immutable();