File Coverage

blib/lib/App/Rcsync.pm
Criterion Covered Total %
statement 49 84 58.3
branch 12 40 30.0
condition 2 6 33.3
subroutine 13 14 92.8
pod 3 3 100.0
total 79 147 53.7


line stmt bran cond sub pod time code
1             package App::Rcsync;
2             {
3             $App::Rcsync::VERSION = '0.03';
4             }
5              
6             # ABSTRACT: Sync configuration files across machines
7              
8 1     1   48225 use strict;
  1         2  
  1         31  
9 1     1   5 use warnings;
  1         1  
  1         29  
10              
11 1     1   1697 use File::HomeDir;
  1         7013  
  1         72  
12 1     1   2820 use Template;
  1         42766  
  1         36  
13 1     1   1221 use Config::General;
  1         37428  
  1         75  
14 1     1   12 use File::Path qw(make_path);
  1         2  
  1         70  
15 1     1   1103 use Path::Class qw(file dir);
  1         39786  
  1         90  
16 1     1   9 use File::Copy qw(copy);
  1         1  
  1         58  
17 1     1   871 use Ref::Explicit qw(hashref);
  1         273  
  1         56  
18              
19 1     1   19 use base qw(App::Cmd::Simple);
  1         1  
  1         872  
20              
21             sub opt_spec
22             {
23             return (
24 1     1 1 45930 [ "help|h", "display usage information" ],
25             [ "config|c=s", "configuration file to use",
26             { default => file( File::HomeDir->my_home, '.rcsync' ) }
27             ],
28             [ "all|a", "sync all profiles" ],
29             [ "list|l", "list all profiles" ],
30             [ "init|i", "create configuration file" ],
31             [ "which|w", "print path to profile template" ],
32             [ "stdout|s", "print to STDOUT" ],
33             );
34             }
35              
36             sub validate_args
37             {
38 1     1 1 2311 my ($self, $opt, $args) = @_;
39              
40 1 50 33     48 if ( !$opt->{init} and ! -e $opt->{config} )
41             {
42 0         0 $self->usage_error("Configuration file " . $opt->{config} . " not found, aborting");
43             }
44              
45 1 50 33     26 if ( !$opt->{help} and !$opt->{init} and !$opt->{all} and !$opt->{list} and !@$args )
46             {
47 0         0 $self->usage_error("Please specify profiles to sync");
48             }
49             }
50              
51             sub execute
52             {
53 1     1 1 13 my ($self, $opt, $args) = @_;
54              
55 1 50       8 if ( $opt->{init} )
    50          
56             {
57 0         0 my $home = File::HomeDir->my_home;
58 0         0 my $rcsync_home = dir $home, 'rcsync';
59              
60 0 0       0 if ( -e $opt->{config} )
61             {
62 0         0 print "Configuration file $$opt{config} already exists, will not overwrite\n";
63 0         0 return;
64             }
65              
66 0 0       0 make_path $rcsync_home unless -e $rcsync_home;
67              
68 0         0 my $sample_config = file ($rcsync_home, 'rcsync');
69              
70 0 0       0 if ( -e ( my $sample_config = file ($rcsync_home, 'rcsync') ) )
71             {
72 0 0       0 copy( $sample_config, $opt->{config} )
73             or die "Failed to copy $sample_config to $$opt{config}: $!";
74 0         0 print "Created configuration file $$opt{config} as copy of $sample_config";
75             }
76             else
77             {
78 0         0 my @children = $rcsync_home->children( no_hidden => 1 );
79 0 0       0 @children = file ('sample.tt') unless @children;
80              
81 0         0 my @templates;
82              
83 0         0 foreach my $template (@children)
84             {
85 0         0 my $basename = $template->basename;
86 0         0 $basename =~ s/\.\w+$//;
87              
88 0         0 push @templates, {
89             name => $basename,
90             base_name => $template->basename,
91             deploy_path => file ( $home, ".$basename" ),
92             };
93             }
94              
95 0 0       0 my $tt = Template->new or die Template->error;
96 0 0       0 $tt->process(
97             \_config_template(),
98             { templates => \@templates, rcsync_home => $rcsync_home },
99             $opt->{config}->stringify,
100             ) or die $tt->error;
101              
102 0         0 print "Created sample configuration file $$opt{config}\n";
103             }
104              
105 0         0 return;
106             }
107             elsif ($opt->{help})
108             {
109 0         0 print $self->app->usage->text;
110             }
111              
112 1         21 my %config = Config::General->new( $opt->{config} )->getall;
113 1         1439 my @all_profiles = grep { ref $config{$_} eq 'HASH' } keys %config;
  2         8  
114              
115 1         3 my %profiles_config;
116 1         4 @profiles_config{@all_profiles} = @config{@all_profiles};
117              
118 1 50       6 my @profiles = $opt->{all} ? @all_profiles : @$args;
119              
120 1 50       13 if ( $opt->{list} )
    50          
121             {
122 0         0 print "$_\n" for @all_profiles;
123 0         0 return;
124             }
125             elsif ( $opt->{which} )
126             {
127 0         0 my $profile_name = $$args[0];
128 0 0       0 if ( exists $profiles_config{$profile_name} )
129             {
130 0         0 print file($config{base_dir}, $profiles_config{$profile_name}{template})->absolute->stringify;
131             }
132             else
133             {
134 0         0 warn "No such profile '$profile_name'\n";
135             }
136 0         0 return;
137             }
138              
139              
140 1 50       21 my $tt = Template->new( INCLUDE_PATH => $config{base_dir} ) or die Template->error;
141              
142 1         41317 foreach my $profile_name (@profiles)
143             {
144 1 50       7 if (!$profiles_config{$profile_name})
145             {
146 0         0 warn "No such profile '$profile_name'\n";
147 0         0 next;
148             }
149              
150 1         3 my $profile = $profiles_config{$profile_name};
151              
152 1 50       12 $tt->process(
    50          
153             $profile->{template},
154             $profile->{param},
155             $opt->{stdout} ? \*STDOUT : $profile->{filename},
156             ) or die $tt->error;
157              
158 1 50       207 if (!$opt->{stdout})
159             {
160 0           print "Successfully synced profile '$profile_name'\n";
161             }
162             }
163             }
164              
165             sub _config_template
166             {
167             return <
168             base_dir [% rcsync_home %]
169              
170             [% FOREACH template IN templates %]<[% template.name %]>
171             filename [% template.deploy_path %]
172             template [% template.base_name %]
173            
174             # enter parameters here
175            
176            
177              
178             [% END %]
179             EoT
180 0     0     }
181              
182             1;