| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package App::Fetchware::ExportAPI; | 
| 2 |  |  |  |  |  |  | $App::Fetchware::ExportAPI::VERSION = '1.014'; | 
| 3 |  |  |  |  |  |  | # ABSTRACT: Used by fetchware extensions to export their API subroutines. | 
| 4 | 2 |  |  | 2 |  | 1139 | use strict; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 89 |  | 
| 5 | 2 |  |  | 2 |  | 13 | use warnings; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 72 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | # CPAN modules making Fetchwarefile better. | 
| 8 | 2 |  |  | 2 |  | 13 | use Sub::Mage; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 23 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | # ExportAPI takes advantage of CreateConfigOption's _create_config_options() and | 
| 11 |  |  |  |  |  |  | # _add_export() to do its dirty work. | 
| 12 | 2 |  |  | 2 |  | 2223 | use App::Fetchware::CreateConfigOptions (); | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 60 |  | 
| 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 |  | 14 | use App::Fetchware (); | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 35 |  | 
| 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 |  | 41 | use 5.010001; | 
|  | 2 |  |  |  |  | 8 |  | 
|  | 2 |  |  |  |  | 857 |  | 
| 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 |  | 4428 | 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 |  |  |  | 36 | return 'Success' if @opts == 0; | 
| 35 |  |  |  |  |  |  |  | 
| 36 | 5 |  |  |  |  | 15 | my $caller = caller; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | # Forward call to _export_api(), which does all the work. | 
| 39 | 5 |  |  |  |  | 15 | _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 |  | 1715 | 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 |  |  |  |  | 40 | clone(import => (from => 'Exporter', to => $callers_package_name)); | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 8 |  |  |  |  | 568 | 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 |  |  |  |  | 24 | 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 |  |  |  | 44 | next unless defined $sub_type; | 
| 76 | 10 |  |  |  |  | 13 | for my $sub (@{$sub_type}) { | 
|  | 10 |  |  |  |  | 18 |  | 
| 77 | 91 | 50 |  |  |  | 196 | if (exists $api_subs{$sub}) { | 
| 78 | 91 |  |  |  |  | 120 | $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 |  |  |  | 30 | die < | 
|  | 104 |  |  |  |  | 176 |  | 
| 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 |  |  |  |  | 13 | for my $sub (@{$opts{KEEP}}) { | 
|  | 7 |  |  |  |  | 20 |  | 
| 97 | 42 |  |  |  |  | 1560 | 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 | 7 | 50 |  |  |  | 185 | $callers_package_name, | 
| 105 |  |  |  |  |  |  | IMPORT => $opts{KEEP}) | 
| 106 |  |  |  |  |  |  | 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 | 7 |  |  |  |  | 119 | App::Fetchware::CreateConfigOptions::_add_export( | 
| 129 |  |  |  |  |  |  | $_, $callers_package_name) | 
| 130 | 7 |  |  |  |  | 13 | for @{$opts{OVERRIDE}}; | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | 1; | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | __END__ |