File Coverage

lib/UR/Namespace/Command/Update/Pod.pm
Criterion Covered Total %
statement 12 89 13.4
branch 0 30 0.0
condition 0 5 0.0
subroutine 4 8 50.0
pod 0 3 0.0
total 16 135 11.8


line stmt bran cond sub pod time code
1             package UR::Namespace::Command::Update::Pod;
2              
3 1     1   23 use strict;
  1         1  
  1         28  
4 1     1   3 use warnings;
  1         1  
  1         24  
5              
6 1     1   4 use UR;
  1         1  
  1         6  
7             our $VERSION = "0.46"; # UR $VERSION;
8 1     1   4 use IO::File;
  1         1  
  1         815  
9              
10             class UR::Namespace::Command::Update::Pod {
11             is => 'Command::V2',
12             has => [
13             executable_name => {
14             is => 'Text',
15             shell_args_position => 1,
16             doc => 'the name of the executable to document'
17             },
18             class_name => {
19             is => 'Text',
20             shell_args_position => 2,
21             doc => 'the command class which maps to the executable'
22             },
23             targets => {
24             is => 'Text',
25             shell_args_position => 3,
26             is_many => 1,
27             doc => 'specific classes to document (documents all unless specified)',
28             },
29             input_path => {
30             is => 'Path',
31             is_optional => 1,
32             doc => 'optional location of the modules to document',
33             },
34             output_path => {
35             is => 'Text',
36             is_optional => 1,
37             doc => 'optional location to output .pod files',
38             },
39             ],
40             doc => "generate man-page-like POD for a commands"
41             };
42              
43             sub help_synopsis {
44             return <<"EOS"
45             ur update pod -i ./lib -o ./pod ur UR::Namespace::Command
46             EOS
47 0     0 0   }
48              
49             sub help_detail {
50 0     0 0   return join("\n",
51             'This tool generates POD documentation for each all of the commands in a tree for a given executable.',
52             'This command must be run from within the namespace directory.');
53             }
54              
55             sub execute {
56 0     0     my $self = shift;
57             #$DB::single = 1;
58              
59 0           local $ENV{ANSI_COLORS_DISABLED} = 1;
60 0           my $entry_point_bin = $self->executable_name;
61 0           my $entry_point_class = $self->class_name;
62              
63 0           my @targets = $self->targets;
64 0 0         unless (@targets) {
65 0           @targets = ($entry_point_class);
66             }
67              
68 0           local @INC = @INC;
69 0 0         if ($self->input_path) {
70 0           unshift @INC, $self->input_path;
71 0           $self->status_message("using modules at " . $self->input_path);
72             }
73              
74 0           my $errors = 0;
75 0           for my $target (@targets) {
76 0           eval "use $target";
77 0 0         if ($@) {
78 0           $self->error_message("Failed to use $target: $@");
79 0           $errors++;
80             }
81             }
82 0 0         return if $errors;
83              
84 0           my @commands = map( $self->get_all_subcommands($_), @targets);
85 0           push @commands, @targets;
86              
87 0 0         if ($self->output_path) {
88 0 0         unless (-d $self->output_path) {
89 0 0         if (-e $self->output_path) {
90 0           $self->status_message("output path is not a directory!: " . $self->output_path);
91             }
92             else {
93 0           mkdir $self->output_path;
94 0 0         if (-d $self->output_path) {
95 0           $self->status_message("using output directory " . $self->output_path);
96             }
97             else {
98 0           $self->status_message("error creating directory: $! for " . $self->output_path);
99             }
100             }
101             }
102             }
103              
104 0           local $Command::V1::entry_point_bin = $entry_point_bin;
105 0           local $Command::V2::entry_point_bin = $entry_point_bin;
106 0           local $Command::V1::entry_point_class = $entry_point_class;
107 0           local $Command::V2::entry_point_class = $entry_point_class;
108              
109 0           for my $command (@commands) {
110 0           my $pod;
111 0           eval {
112 0           $pod = $command->help_usage_command_pod();
113             };
114              
115 0 0         if($@) {
116 0           $self->warning_message('Could not generate POD for ' . $command . '. ' . $@);
117 0           next;
118             }
119              
120 0 0         unless($pod) {
121 0           $self->warning_message('No POD generated for ' . $command);
122 0           next;
123             }
124              
125 0           my $pod_path;
126 0 0         if (defined $self->output_path) {
127 0           my $filename = $command->command_name . '.pod';
128 0           $filename =~ s/ /-/g;
129 0           my $output_path = $self->output_path;
130 0           $output_path =~ s|/+$||m;
131 0           $pod_path = join('/', $output_path, $filename);
132             } else {
133 0           $pod_path = $command->__meta__->module_path;
134 0           $pod_path =~ s/.pm/.pod/;
135             }
136              
137 0           $self->status_message("Writing $pod_path");
138              
139 0           my $fh;
140 0   0       $fh = IO::File->new('>' . $pod_path) || die "Cannot create file at " . $pod_path . "\n";
141 0           print $fh $pod;
142 0           close($fh);
143             }
144              
145 0           return 1;
146             }
147              
148             sub get_all_subcommands {
149 0     0 0   my $self = shift;
150 0           my $command = shift;
151 0           my $src = "use $command";
152 0           eval $src;
153              
154 0 0         if ($@) {
155 0           $self->error_message("Failed to load class $command: $@");
156             }
157             else {
158 0           my $module_name = $command;
159 0           $module_name =~ s|::|/|g;
160 0           $module_name .= '.pm';
161 0           $self->status_message("Loaded $command from $module_name at $INC{$module_name}\n");
162             }
163              
164 0           my @subcommands;
165 0           eval {
166 0 0         if ($command->can('sub_command_classes')) {
167 0           @subcommands = $command->sub_command_classes;
168             }
169             };
170              
171 0 0         if($@) {
172 0           $self->warning_message("Error getting subclasses for module $command: " . $@);
173             }
174              
175 0 0 0       return unless @subcommands and $subcommands[0]; #Sometimes sub_command_classes returns 0 instead of the empty list
176              
177 0           return map($self->get_all_subcommands($_), @subcommands), @subcommands;
178             }
179              
180             1;