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
|
|
|
|
|
|
|
[% template.name %]> |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
[% END %] |
179
|
|
|
|
|
|
|
EoT |
180
|
0
|
|
|
0
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |