File Coverage

lib/UR/Namespace/Command/Update/TabCompletionSpec.pm
Criterion Covered Total %
statement 56 66 84.8
branch 10 24 41.6
condition 2 6 33.3
subroutine 9 10 90.0
pod 1 3 33.3
total 78 109 71.5


line stmt bran cond sub pod time code
1             package UR::Namespace::Command::Update::TabCompletionSpec;
2              
3 1     1   23 use strict;
  1         2  
  1         30  
4 1     1   4 use warnings;
  1         1  
  1         28  
5              
6 1     1   4 use UR;
  1         1  
  1         9  
7             our $VERSION = "0.46"; # UR $VERSION;
8 1     1   4 use IO::File;
  1         0  
  1         151  
9 1     1   426 use POSIX qw(ENOENT);
  1         4506  
  1         4  
10              
11             UR::Object::Type->define(
12             class_name => __PACKAGE__,
13             is => 'UR::Namespace::Command::Base',
14             has => [
15             classname => {
16             is => 'Text',
17             shell_args_position => 1,
18             doc => 'The base class to use as trunk of command tree, e.g. UR::Namespace::Command',
19             },
20             output => {
21             is => 'Text',
22             is_optional => 1,
23             doc => 'Override output location of the opts spec file.',
24             },
25             ]
26             );
27              
28              
29             sub help_brief {
30 0     0 0 0 "Creates a .opts file beside class/module passed as argument, e.g. UR::Namespace::Command.";
31             }
32              
33             sub create {
34 1     1 1 133 my $class = shift;
35              
36 1         11 my $bx = $class->define_boolexpr(@_);
37 1 50 33     4 if($bx->specifies_value_for('classname') and !$bx->specifies_value_for('namespace_name')) {
38 1         5 my $classname = $bx->value_for('classname');
39 1         5 my($namespace) = ($classname =~ m/^(\w+)::/);
40 1 50       5 $bx = $bx->add_filter(namespace_name => $namespace) if $namespace;
41             }
42 1         3 return $class->SUPER::create($bx);
43             }
44              
45              
46              
47 2     2 0 9 sub is_sub_command_delegator { 0; }
48              
49             sub execute {
50 1     1   2 my $self = shift;
51 1         4 my $class = $self->classname;
52              
53 1         3 my $req_exception = do {
54 1         1 local $@;
55 1         3 eval {
56 1         599 require Getopt::Complete;
57 1         9755 require Getopt::Complete::Cache;
58             };
59 1         3 $@;
60             };
61 1 50       4 if ($req_exception) {
62 0         0 die "Errors using Getopt::Complete. Do you have Getopt::Complete installed? If not try 'cpanm Getopt::Complete'";
63             }
64              
65 1         1 my $use_exception = do {
66 1         1 local $@;
67 1     1   305 eval "use above '$class';";
  1         2  
  1         5  
  1         57  
68 1         3 $@;
69             };
70 1 50       2 if ($use_exception) {
71 0         0 $self->error_message("Unable to use above $class.\n$@");
72 0         0 return;
73             }
74              
75 1         11 (my $module_path) = Getopt::Complete::Cache->module_and_cache_paths_for_package($class, 1);
76 1         3054 my $cache_path = $module_path . ".opts";
77              
78 1         5 eval {
79 1         69 my $rename_ok = rename($cache_path, "$cache_path.bak");
80 1 50 33     12 if (!$rename_ok && $! != ENOENT) {
81 0         0 die "failed to rename file: $!: $cache_path";
82             }
83              
84 1 50       12 unless ($self->output) {
85 0         0 $self->output($cache_path);
86             }
87 1         7 $self->status_message("Generating " . $self->output . " file for $class.");
88 1         6 $self->status_message("This may take some time and may generate harmless warnings...");
89              
90 1 50       7 my $fh = IO::File->new($self->output, 'w')
91             or die "Cannot create file at " . $self->output . "\n";
92              
93 1         204 my $src = Data::Dumper::Dumper($class->resolve_option_completion_spec());
94 1         1363 $src =~ s/^\$VAR1/\$$class\:\:OPTS_SPEC/;
95 1         7 $fh->print($src);
96             };
97              
98 1 50       176 if (-s $cache_path) {
99 0         0 $self->status_message("\nOPTS_SPEC file created at $cache_path");
100 0 0       0 unlink("$cache_path.bak")
101             or $self->error_message("failed to remove backup file: $!");
102             } else {
103 1 50       21 if (-s "$cache_path.bak") {
104 1         14 $self->error_message("$cache_path is 0 bytes, reverting to previous");
105 1 50       60 rename("$cache_path.bak", $cache_path)
106             or $self->error_message("failed to restore file: $!");
107             } else {
108 0           $self->error_message("$cache_path is 0 bytes and no backup exists, removing file");
109 0 0         unlink($cache_path)
110             or $self->error_message("failed to remove file: $!");
111             }
112             }
113             }
114              
115             1;