File Coverage

lib/App/Followme.pm
Criterion Covered Total %
statement 81 84 96.4
branch 9 12 75.0
condition 2 3 66.6
subroutine 15 15 100.0
pod 1 7 14.2
total 108 121 89.2


line stmt bran cond sub pod time code
1             package App::Followme;
2              
3 2     2   1288 use 5.008005;
  2         24  
4 2     2   14 use strict;
  2         4  
  2         57  
5 2     2   11 use warnings;
  2         4  
  2         58  
6              
7 2     2   10 use lib '..';
  2         3  
  2         11  
8              
9 2     2   271 use base qw(App::Followme::Module);
  2         3  
  2         1042  
10              
11 2     2   14 use IO::File;
  2         4  
  2         251  
12 2     2   15 use File::Spec::Functions qw(splitdir catfile);
  2         15  
  2         83  
13 2     2   12 use App::Followme::FIO;
  2         3  
  2         1707  
14              
15             our $VERSION = "2.03";
16              
17             #----------------------------------------------------------------------
18             # Read the default parameter values
19              
20             sub parameters {
21 20     20 1 37 my ($pkg) = @_;
22              
23             return (
24 20         45 );
25             }
26              
27             #----------------------------------------------------------------------
28             # Perform all updates on the directory
29              
30             sub run {
31 6     6 0 830 my ($self, $directory) = @_;
32              
33 6         33 my $configuration_files = $self->find_configuration($directory);
34              
35             $self->update_folder($directory,
36             $configuration_files,
37 6         51 %{$self->{configuration}});
  6         81  
38              
39 6         38 return;
40             }
41              
42             #----------------------------------------------------------------------
43             # Check case sensitivity of this system
44              
45             sub check_sensitivity {
46 8     8 0 21 my ($self, $config_file) = @_;
47              
48 8         23 my ($dir, $filename) = fio_split_filename($config_file);
49 8         35 $filename = ucfirst($filename);
50 8         36 my $other_config_file = catfile($dir, $filename);
51              
52 8         20 my $sensitivity;
53 8 50       121 if (-e $other_config_file) {
54 0         0 my $date = fio_get_date($config_file);
55 0         0 my $other_date = fio_get_date($other_config_file);
56 0         0 $sensitivity = $date != $other_date;
57              
58             } else {
59 8         27 $sensitivity = 1;
60             }
61              
62 8         29 return $sensitivity;
63             }
64              
65             #----------------------------------------------------------------------
66             # Find the configuration files above a directory
67              
68             sub find_configuration {
69 7     7 0 31 my ($self, $directory) = @_;
70              
71             # Push a possibly non-existent configuration file in the current
72             # directory onto the list of configuration files
73              
74 7         59 my $config_file = catfile($directory, $self->{configuration_file});
75 7         26 my @configuration_files = ($config_file);
76              
77 7         40 my @dirs = splitdir($directory);
78 7         68 pop(@dirs);
79              
80             # Find configuration files in and above directory
81              
82 7         31 while (@dirs) {
83 45         219 $config_file = catfile(@dirs, $self->{configuration_file});
84 45 100       600 push(@configuration_files, $config_file) if -e $config_file;
85 45         147 pop(@dirs);
86             }
87              
88 7         17 @configuration_files = reverse @configuration_files;
89              
90             # The topmost configuration file is the top and base directory
91 7         36 $self->set_configuration(@configuration_files);
92              
93 7         25 return \@configuration_files;
94             }
95              
96             #----------------------------------------------------------------------
97             # Load a modeule and then run it
98              
99             sub load_and_run_modules {
100 40     40 0 171 my ($self, $modules, $base_directory, $directory, %configuration) = @_;
101              
102 40         113 $configuration{base_directory} = $base_directory;
103              
104 40         74 foreach my $module (@$modules) {
105 23 50       1552 eval "require $module" or die "Module not found: $module\n";
106              
107 23         218 my $object = $module->new(%configuration);
108 23         117 $object->run($directory);
109             }
110              
111 40         112 return;
112             }
113              
114             #----------------------------------------------------------------------
115             # Set the initial configuration parameters
116              
117             sub set_configuration {
118 8     8 0 37 my ($self, @configuration_files) = @_;
119              
120 8         35 my ($directory, $file) = fio_split_filename($configuration_files[0]);
121 8         41 $self->{configuration}{base_directory} = $directory;
122 8         25 $self->{configuration}{top_directory} = $directory;
123              
124             $self->{configuration}{case_sensitive} =
125 8         30 $self->check_sensitivity($configuration_files[0]);
126              
127 8         26 return;
128             }
129              
130             #----------------------------------------------------------------------
131             # Update files in one folder
132              
133             sub update_folder {
134 20     20 0 102 my ($self, $directory, $configuration_files, %configuration) = @_;
135              
136             my $configuration_file = shift(@$configuration_files) ||
137 20   66     115 catfile($directory, $self->{configuration_file});
138              
139 20         87 my ($base_directory, $filename) = fio_split_filename($configuration_file);
140              
141 20         56 my ($run_before, $run_after);
142 20 100       257 if (-e $configuration_file) {
143 19         142 %configuration = $self->read_configuration($configuration_file,
144             %configuration);
145              
146 19         59 $run_before = $configuration{run_before};
147 19         48 delete $configuration{run_before};
148              
149 19         34 $run_after = $configuration{run_after};
150 19         40 delete $configuration{run_after};
151             }
152              
153 20         92 $self->load_and_run_modules($run_before,
154             $base_directory,
155             $directory,
156             %configuration);
157              
158              
159 20 100       96 if (@$configuration_files) {
    50          
160 7         38 $self->update_folder($directory,
161             $configuration_files,
162             %configuration);
163              
164             } elsif (! $self->{quick_update}) {
165 13         48 my ($filenames, $directories) = fio_visit($directory);
166 13         266 foreach my $subdirectory (@$directories) {
167 7         53 $self->update_folder($subdirectory,
168             $configuration_files,
169             %configuration);
170             }
171             }
172              
173 20         96 $self->load_and_run_modules($run_after,
174             $base_directory,
175             $directory,
176             %configuration);
177 20         90 return;
178             }
179              
180             1;
181             __END__
182              
183             =encoding utf-8
184              
185             =head1 NAME
186              
187             App::Followme - Update a static website
188              
189             =head1 SYNOPSIS
190              
191             use App::Followme;
192             my $app = App::Followme->new(\%configuration);
193             $app->run($directory);
194              
195             =head1 DESCRIPTION
196              
197             See L<App::Followme::Guide> for more information on how to install and configure
198             followme.
199              
200             This class reads and processes the configuration files in a website and as a
201             result of that runs the modules named in them.
202              
203             The configuration file for followme is followme.cfg in the top directory of
204             your site. It contains the names of the Perl modules that are run when the
205             followme command is run:
206              
207             run_before:
208             - App::Followme::FormatPage
209             - App::Followme::ConvertPage
210              
211             Perl modules are run in the order they appear in the configuration file. If they
212             are named run_before then they are run before modules in configuration files in
213             subdirectories. If they are named run_after, they are run after modules in
214             configuration files in subdirectories. See L<App::Followme::Guide> for an
215             overview of the available modules.
216              
217             A larger website will be spread across several folders. Each folder can have its
218             own configuration file. If they contain modules, they will be run on that folder
219             and all the subfolders below it.
220              
221             Followme is run from the folder it is invoked from if it is called with no
222             arguments, or if it is run with arguments, it will run on the folder passed as
223             an argument or the folder the file passed as an argument is contained in.
224             Followme looks for its configuration files in all the directories above the
225             directory it is run from and runs all the modules it finds in them. But they are
226             are only run on the folder it is run from and subfolders of it. Followme
227             only looks at the folder it is run from to determine if other files in the
228             folder need to be updated. So after changing a file, it should be run from the
229             directory containing the file.
230              
231             When followme is run, it searches the directories above it for configuration
232             files. The topmost file defines the top directory of the website. It reads each
233             configuration file it finds and then starts updating the directory passed as an
234             argument to run, or if no directory is passed, the directory the followme script
235             is run from.
236              
237             Configuration file lines are organized as lines containing
238              
239             NAME: VALUE
240              
241             and may contain blank lines or comment lines starting with a C<#>. Values in
242             configuration files are combined with those set in the files in directories
243             above it.
244              
245             The run_before and run_after parameters contain the names of modules to be run
246             on the directory containing the configuration file and possibly its
247             subdirectories. There may be more than one run_before or run_after parameter in
248             a configuration file. They are run in order, starting with the modules in the
249             topmost configuration file. Each module to be run must have new and run methods.
250             An object of the module's class is created by calling the new method with the a
251             reference to a hash containing the configuration parameters. The run method is
252             then called with the directory as its argument.
253              
254             =head1 CONFIGURATION
255              
256             The following parameter is used from the configuration:
257              
258             =over 4
259              
260             =item configuration_file
261              
262             The name of the file containing the configuration data. The default value is
263             followme.cfg. The followme script derives the value of this parameter from
264             the name of the script, so by adding a link to the script, you can have
265             different sets of configuration files.
266              
267             =back
268              
269             =head1 LICENSE
270              
271             Copyright (C) Bernie Simon.
272              
273             This library is free software; you can redistribute it and/or modify
274             it under the same terms as Perl itself.
275              
276             =head1 AUTHOR
277              
278             Bernie Simon E<lt>bernie.simon@gmail.comE<gt>
279              
280             =cut