File Coverage

blib/lib/App/Fetchware/ExportAPI.pm
Criterion Covered Total %
statement 38 38 100.0
branch 8 10 80.0
condition n/a
subroutine 8 8 100.0
pod n/a
total 54 56 96.4


line stmt bran cond sub pod time code
1             package App::Fetchware::ExportAPI;
2             our $VERSION = '1.016'; # VERSION: generated by DZP::OurPkgVersion
3             # ABSTRACT: Used by fetchware extensions to export their API subroutines.
4 2     2   708 use strict;
  2         3  
  2         44  
5 2     2   6 use warnings;
  2         2  
  2         47  
6              
7             # CPAN modules making Fetchwarefile better.
8 2     2   6 use Sub::Mage;
  2         7  
  2         16  
9              
10             # ExportAPI takes advantage of CreateConfigOption's _create_config_options() and
11             # _add_export() to do its dirty work.
12 2     2   1032 use App::Fetchware::CreateConfigOptions ();
  2         4  
  2         37  
13             # _create_config_options() clone()'s some of App::Fetchware's API subroutines
14             # when a fetchware extension "KEEP"s them, so I must load it, so I can access
15             # these subroutines.
16 2     2   8 use App::Fetchware ();
  2         2  
  2         20  
17              
18             # Enable Perl 6 knockoffs, and use 5.10.1, because smartmatching and other
19             # things in 5.10 were changed in 5.10.1+.
20 2     2   22 use 5.010001;
  2         4  
21              
22             # Don't use Exporter's import; instead, provide your own. This is all ExportAPI
23             # does. Provide an import() method, so that it can set up correct exports, and
24             # ensure that your fetchware extension implementes all of fetchware's API
25             # subroutines at compile time.
26              
27              
28              
29             sub import {
30 6     6   2745 my ($class, @opts) = @_;
31              
32             # Just return success if user specified no options, because that just means
33             # the user wanted to load the module, but not actually import() anything.
34 6 100       26 return 'Success' if @opts == 0;
35              
36 5         9 my $caller = caller;
37              
38             # Forward call to _export_api(), which does all the work.
39 5         11 _export_api($caller, @opts);
40             }
41              
42              
43             # _export_api() has pretty much the same documentation as import() above, and
44             # why copy and paste any changes I make, when this not here makes more sense?
45             sub _export_api {
46 8     8   944 my ($callers_package_name, %opts) = @_;
47              
48             # clone() Exporter's import() into $callers_package_name, because
49             # fetchware extensions use Exporter's import() when fetchware eval()'s
50             # Fetchwarefile's that use that extension. Exporter's import() is what makes
51             # the magic happen.
52 8         26 clone(import => (from => 'Exporter', to => $callers_package_name));
53              
54 8         373 my %api_subs = (
55             check_syntax => 0,
56             new => 0,
57             new_install => 0,
58             start => 0,
59             lookup => 0,
60             download => 0,
61             verify => 0,
62             unarchive => 0,
63             build => 0,
64             install => 0,
65             end => 0,
66             uninstall => 0,
67             upgrade => 0,
68             );
69              
70             # Check %opts for correctness.
71 8         17 for my $sub_type (@opts{qw(KEEP OVERRIDE)}) {
72             # Skip KEEP or OVERRIDE if it does not exist.
73             # Needed, because the obove hash slice access will create it if it does
74             # not already exist.
75 16 100       29 next unless defined $sub_type;
76 10         10 for my $sub (@{$sub_type}) {
  10         14  
77 91 50       105 if (exists $api_subs{$sub}) {
78 91         80 $api_subs{$sub}++;
79             }
80             }
81             }
82              
83             # Use (scalar keys %api_subs) to dynamically determine how many API subs
84             # there are. I've implemented all of the ones that I've planned, but another
85             # upgrade() or check_syntax() could come out of now where, so calculate how
86             # many there are dynamically, and then I only have to remember to update
87             # %api_subs; instead, of that and also incrementing a constant integer
88             # that's now properly a constant.
89 8 100       20 die <
  104         110  
90             App-Fetchware-ExportAPI: _export_api() or import() must be called with either or
91             both of the KEEP and OVERRIDE options, and you must supply the names of all of
92             fetchware's API subroutines to either one of these 2 options.
93             EOD
94              
95             # Import any KEEP subs from App::Fetchware.
96 7         10 for my $sub (@{$opts{KEEP}}) {
  7         12  
97 42         935 clone($sub => ( from => 'App::Fetchware', to => $callers_package_name));
98              
99             }
100              
101             # Also import any subroutines the fetchware extension developer wants to
102             # keep unless the fetchware extension developer does not want them.
103             App::Fetchware::CreateConfigOptions::_create_config_options(
104             $callers_package_name,
105             IMPORT => $opts{KEEP})
106 7 50       112 unless $opts{NOIMPORT};
107              
108             ###LIMITATION###You may want _export_api() and import() and ExportAPI to
109             #check if all of the required fetchware extension API subroutines have been
110             #implemented by our caller using something like
111             #"$callers_package_name"->can($sub), but this can't work, because ExportAPI
112             #is run inside an implied BEGIN block, from the use(), That means that the
113             #rest of the file has *not* been compiled yet, so any subroutines defined
114             #later on in the same file have not actually been compiled yet, so any use
115             #of can() to lookup if they exist yet will fail, because they don't actually
116             #exist yet. But if they have been properly defined, they will properly
117             #exist.
118             #
119             #Therefore, I have moved checking if all of the proper API subroutines have
120             #been defined properly to bin/fetchware's parse_fetchwarefile(), because
121             #after the Fetchwarefile has been eval()'s the API subroutines should be in
122             #bin/fetchware's namespace, so it just uses Sub::Mage's sublist() to see if
123             #they all exist.
124              
125              
126             # _create_config_options() takes care of setting up KEEP's exports, but
127             # I need to ensure OVERRIDE's exports are also set up.
128             App::Fetchware::CreateConfigOptions::_add_export(
129             $_, $callers_package_name)
130 7         10 for @{$opts{OVERRIDE}};
  7         84  
131             }
132              
133              
134             1;
135              
136             __END__