File Coverage

blib/lib/Build/Hopen/G/Runnable.pm
Criterion Covered Total %
statement 46 52 88.4
branch 3 8 37.5
condition 4 8 50.0
subroutine 11 14 78.5
pod 2 2 100.0
total 66 84 78.5


line stmt bran cond sub pod time code
1             # Build::Hopen::G::Runnable - parent class for anything runnable in a hopen graph
2             package Build::Hopen::G::Runnable;
3 7     7   3373 use Build::Hopen::Base;
  7         15  
  7         42  
4 7     7   1530 use Build::Hopen;
  7         14  
  7         416  
5              
6             our $VERSION = '0.000008'; # TRIAL
7              
8 7     7   2417 use Build::Hopen::Scope::Hash;
  7         69  
  7         317  
9 7     7   47 use Build::Hopen::Util::Data qw(forward_opts);
  7         27  
  7         310  
10 7     7   42 use Build::Hopen::Util::NameSet;
  7         16  
  7         164  
11 7     7   41 use Build::Hopen::Arrrgs;
  7         14  
  7         275  
12 7     7   3652 use Hash::Merge;
  7         28259  
  7         365  
13              
14             # Docs {{{1
15              
16             =head1 NAME
17              
18             Build::Hopen::G::Runnable - parent class for runnable things in a hopen graph
19              
20             =head1 SYNOPSIS
21              
22             Anything with L inherits from this. TODO should this be a role?
23              
24             =head1 ATTRIBUTES
25              
26             =head2 need
27              
28             Inputs this Runnable requires.
29             A L, with the restriction that C may not
30             contain regexes. ("Sorry, I can't run unless you give me every variable
31             in the world that starts with Q." I don't think so!)
32              
33             =head2 scope
34              
35             If defined, a L that will have the final say on the
36             data used by L. This is the basis of the fine-grained override
37             mechanism in hopen.
38              
39             =head2 want
40              
41             Inputs this Runnable accepts but does not require.
42             A L, which may include regexes.
43              
44             =cut
45              
46             # }}}1
47              
48 7     7   53 use parent 'Build::Hopen::G::Entity';
  7         15  
  7         41  
49             use Class::Tiny {
50             # NOTE: want and need are not currently used.
51 0         0 want => sub { Build::Hopen::Util::NameSet->new },
52 0         0 need => sub { Build::Hopen::Util::NameSet->new },
53              
54 6         61 scope => sub { Build::Hopen::Scope::Hash->new },
55 7     7   749 };
  7         18  
  7         67  
56              
57             =head1 FUNCTIONS
58              
59             =head2 run
60              
61             Run the operation, whatever that means. Returns a new hashref.
62             Usage:
63              
64             my $hrOutputs = $op->run([options])
65              
66             Options are:
67              
68             =over
69              
70             =item -context
71              
72             A L or subclass including the inputs the caller wants to
73             pass to the Runnable. The L of the Runnable itself may override
74             values in the C.
75              
76             =item -phase
77              
78             If given, the phase that is currently under way in a build-system run.
79              
80             =item -generator
81              
82             If given, the L instance in use for the current
83             build-system run.
84              
85             =item -nocontext
86              
87             If C<< -nocontext=>1 >> is specified, don't link a context scope into
88             this one. May not be specified together with C<-context>.
89              
90             =back
91              
92             See the source for this function, which contains as an example of setting the
93             scope.
94              
95             =cut
96              
97             sub run {
98 9     9 1 1002 my ($self, %args) = parameters('self', [qw(; context phase generator nocontext)], @_);
99 9         24 my $context_scope = $args{context}; # which may be undef - that's OK
100 9 50 33     46 croak "Can't combine -context and -nocontext" if $args{context} && $args{nocontext};
101              
102             # Link the outer scope to our scope
103 9 50       224 my $saver = $args{nocontext} ? undef : $self->scope->outerize($context_scope);
104              
105 9     0   69 hlog { ref($self), $self->name, 'input', Dumper($self->scope->as_hashref) } 3;
  0         0  
106              
107 9         79 my $retval = $self->_run(forward_opts(\%args, {'-'=>1}, qw[phase generator]));
108              
109 9     0   75 hlog { ref $self, $self->name, 'output', Dumper($retval) } 3;
  0         0  
110              
111 9         70 return $retval;
112             } #run()
113              
114             =head2 _run
115              
116             The internal method that implements L. Must be implemented by
117             subclasses. When C<_run> is called, C<< $self->scope >> has been hooked
118             to the context scope, if any.
119              
120             Parameters are C<-phase> and C<-generator>. C<_run> is always called in scalar
121             context, and must return a new hashref.
122              
123             =cut
124              
125             sub _run {
126 0     0   0 my ($self, %args) = parameters('self', [qw(; phase generator)], @_);
127             ...
128 0         0 }
129              
130             =head2 passthrough
131              
132             Returns a new hashref of this Runnable's local values, as defined
133             by L. Usage:
134              
135             my $hashref = $runnable->passthrough([-context => $outer_scope]);
136             # To use $outer_scope as the context
137             my $hashref = $runnable->passthrough(-nocontext => 1);
138             # To leave the context untouched
139              
140             Other valid options include L<-levels|Build::Hopen::Scope/$levels>.
141              
142             =cut
143              
144             sub passthrough {
145 8     8 1 88 my ($self, %args) = parameters('self', ['*'], @_);
146 8         22 my $outer_scope = $args{context}; # which may be undef - that's OK
147 8 0 33     24 croak "Can't combine -context and -nocontext" if $args{context} && $args{nocontext};
148              
149             # Link the outer scope to our scope
150 8 50       21 my $saver = $args{nocontext} ? undef : $self->scope->outerize($outer_scope);
151              
152             # Copy the names
153 8   100     26 my $levels = $args{levels} // 'local';
154 8         12 my @names = @{$self->scope->names(-levels=>$levels)};
  8         176  
155 8         118 my $retval = {};
156 8         552 $retval->{$_} = $self->scope->find($_, -levels=>$levels) foreach @names;
157              
158 8         32 return $retval;
159             } #passthrough()
160              
161             1;
162             __END__