File Coverage

blib/lib/Config/FileManager.pm
Criterion Covered Total %
statement 201 221 90.9
branch 44 70 62.8
condition 8 23 34.7
subroutine 23 23 100.0
pod 12 12 100.0
total 288 349 82.5


line stmt bran cond sub pod time code
1             ###############################################################################
2             # #
3             # Copyright © 2012-2018 -- LIRMM/UM #
4             # (Laboratoire d'Informatique, de Robotique et de #
5             # Microélectronique de Montpellier / #
6             # Université de Montpellier) #
7             # IRB/INSERM #
8             # (Institut de Recherche en Biothérapie / #
9             # Institut National de la Santé et de la #
10             # Recherche Médicale) #
11             # #
12             # Auteurs/Authors: Alban MANCHERON #
13             # Nicolas PHILIPPE #
14             # #
15             # ------------------------------------------------------------------------- #
16             # #
17             # Ce fichier fait partie du Pipeline de traitement de données NGS de la #
18             # plateforme ATGC labélisée par le GiS IBiSA. #
19             # #
20             # Ce logiciel est régi par la licence CeCILL soumise au droit français et #
21             # respectant les principes de diffusion des logiciels libres. Vous pouvez #
22             # utiliser, modifier et/ou redistribuer ce programme sous les conditions de #
23             # la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur #
24             # le site "http://www.cecill.info". #
25             # #
26             # En contrepartie de l'accessibilité au code source et des droits de copie, #
27             # de modification et de redistribution accordés par cette licence, il n'est #
28             # offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, #
29             # seule une responsabilité restreinte pèse sur l'auteur du programme, le #
30             # titulaire des droits patrimoniaux et les concédants successifs. #
31             # #
32             # À cet égard l'attention de l'utilisateur est attirée sur les risques #
33             # associés au chargement, à  l'utilisation, à  la modification et/ou au #
34             # développement et à la reproduction du logiciel par l'utilisateur étant #
35             # donné sa spécificité de logiciel libre, qui peut le rendre complexe à #
36             # manipuler et qui le réserve donc à des développeurs et des professionnels #
37             # avertis possédant des connaissances informatiques approfondies. Les #
38             # utilisateurs sont donc invités à  charger et tester l'adéquation du #
39             # logiciel à leurs besoins dans des conditions permettant d'assurer la #
40             # sécurité de leurs systêmes et ou de leurs données et, plus généralement, #
41             # à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. #
42             # #
43             # Le fait que vous puissiez accéder à cet en-tête signifie que vous avez #
44             # pris connaissance de la licence CeCILL, et que vous en avez accepté les #
45             # termes. #
46             # #
47             # ------------------------------------------------------------------------- #
48             # #
49             # This File is part of the NGS data processing Pipeline of the ATGC #
50             # accredited by the IBiSA GiS. #
51             # #
52             # This software is governed by the CeCILL license under French law and #
53             # abiding by the rules of distribution of free software. You can use, #
54             # modify and/ or redistribute the software under the terms of the CeCILL #
55             # license as circulated by CEA, CNRS and INRIA at the following URL #
56             # "http://www.cecill.info". #
57             # #
58             # As a counterpart to the access to the source code and rights to copy, #
59             # modify and redistribute granted by the license, users are provided only #
60             # with a limited warranty and the software's author, the holder of the #
61             # economic rights, and the successive licensors have only limited #
62             # liability. #
63             # #
64             # In this respect, the user's attention is drawn to the risks associated #
65             # with loading, using, modifying and/or developing or reproducing the #
66             # software by the user in light of its specific status of free software, #
67             # that may mean that it is complicated to manipulate, and that also #
68             # therefore means that it is reserved for developers and experienced #
69             # professionals having in-depth computer knowledge. Users are therefore #
70             # encouraged to load and test the software's suitability as regards their #
71             # requirements in conditions enabling the security of their systems and/or #
72             # data to be ensured and, more generally, to use and operate it in the same #
73             # conditions as regards security. #
74             # #
75             # The fact that you are presently reading this means that you have had #
76             # knowledge of the CeCILL license and that you accept its terms. #
77             # #
78             ###############################################################################
79             #
80             # $Id: FileManager.pm,v 1.7 2018/03/19 13:16:31 doccy Exp $
81             #
82             ###############################################################################
83             #
84             # $Log: FileManager.pm,v $
85             # Revision 1.7 2018/03/19 13:16:31 doccy
86             # BugFix: module file was encoded with ISO-8859-1. Switching to UT-8.
87             #
88             # Revision 1.6 2013/11/07 10:19:25 doccy
89             # Renaming the module.
90             #
91             # Revision 1.5 2013/05/22 11:39:02 doccy
92             # Update Copyright informations
93             #
94             # Revision 1.4 2013/05/22 10:42:43 doccy
95             # Add CéCILL Copyright Notice
96             #
97             # Revision 1.3 2013/05/22 08:11:25 doccy
98             # Fix POD examples.
99             #
100             # Revision 1.2 2013/05/21 17:04:08 doccy
101             # Update version.
102             # Will be automatic from now.
103             #
104             # Revision 1.1.1.1 2013/05/21 16:43:23 doccy
105             # Perl Module for manage configuration files.
106             #
107             ###############################################################################
108              
109             package Config::FileManager;
110              
111             # Force having good coding conventions.
112 2     2   104895 use 5.010000;
  2         10  
113 2     2   8 use strict;
  2         3  
  2         38  
114 2     2   7 use warnings;
  2         4  
  2         46  
115 2     2   742 use POSIX;
  2         9444  
  2         8  
116 2     2   5266 use utf8;
  2         22  
  2         8  
117              
118 2     2   768 use File::HomeDir;
  2         8306  
  2         81  
119 2     2   11 use File::Basename;
  2         3  
  2         117  
120 2     2   672 use Text::Patch;
  2         3540  
  2         85  
121 2     2   734 use Text::Diff;
  2         14073  
  2         89  
122              
123 2     2   984 use Data::Dumper;
  2         10486  
  2         95  
124              
125 2     2   13 use Carp;
  2         3  
  2         4097  
126             require Exporter;
127              
128             our @ISA = qw(Exporter);
129              
130             our $VERSION = (qw$Revision: 1.7 $)[-1];
131              
132             ###########################
133             # Plain Old Documentation #
134             # Name #
135             # Synopsys #
136             # Decription 1/2 #
137             ###########################
138              
139             =encoding utf8
140              
141             =head1 NAME
142              
143             Config::FileManager - Configuration File Management with versionning
144              
145             =head1 SYNOPSIS
146              
147             The Config::FileManager module helps to manage configuration files.
148             It provides versionning and check for updates of obsolete
149             versions.
150              
151             Usage:
152              
153             use Config::FileManager;
154              
155             =head1 DESCRIPTION
156              
157             The I module:
158              
159             =over
160              
161             =item check wether the user configuration file version is up-to-date
162              
163             =item can propose update taking into account user modifications
164              
165             =item keep (and ca restore) the previous versions of the configuration file
166              
167             =item search the configuration file in an ordered list of paths
168              
169             =back
170              
171             =cut
172              
173             ###########################
174             # Perl #
175             # Specific Options #
176             ###########################
177              
178             our %default_settings = (
179             # Standard Settings
180             "toolname" => undef, # Mandatory
181             "version" => undef, # Not mandatory
182             "filename" => "config", # Not mandatory
183             "paths" => [qw(. __APPDIR__ /usr/local/etc /etc)], # Not mandatory
184             "interactive" => 1, # Not mandatory
185             );
186             our @available_settings = keys %default_settings;
187              
188             ###########################
189             # Plain Old Documentation #
190             # Export Tags #
191             ###########################
192              
193             =head2 EXPORT
194              
195             =cut
196              
197             #################
198             # Perl #
199             # Export Tags #
200             #################
201              
202             # Items to export into callers namespace by default. Note: do not export
203             # names by default without a very good reason. Use EXPORT_OK instead.
204             # Do not simply export all your public functions/methods/constants.
205              
206             our @EXPORT_OK = (qw());
207              
208             our @EXPORT = qw();
209              
210             ##################################
211             # Perl Subroutines Implentations #
212             ##################################
213              
214             =over 2
215              
216             =item * the new operator can be given the following parameters:
217              
218             =over 2
219              
220             =item * C<< toolname= >> (mandatory)
221              
222             sets the name of the tool the configuration file is designed for.
223              
224             =item * C<< version= >>
225              
226             sets the current version of the configuration file (can be the same as the tool version).
227              
228             =item * C<< filename= >>
229              
230             sets the base file name of the configuration file.
231              
232             =item * C<< paths=[qw(string array of paths)] >>
233              
234             sets the ordered list of paths where the configuration file will be searched. The special C<__APPDIR__> is OS dependent and is the user application directory.
235              
236             =item * C<< interactive= >>
237              
238             if set to 1, user is asked if some update is available. If set to 0, then update is automatic.
239              
240             =back
241              
242             Usage:
243              
244             my $cfg = new Config(
245             # Mandatory settings
246             "toolname" => "tool name",
247             # Optional settings
248             "version" => "version string", # default to undef
249             "filename" => "config file basename", # default to "config"
250             "paths" => [qw(list of/paths /to/look ./for)], # default to [qw(. __APPDIR__ /usr/local/etc /etc)],
251             "interactive" => 0, # default to 1
252             );
253              
254             =cut
255              
256             sub new {
257 1     1 1 216 my $class = shift;
258              
259 1         5 my %settings = @_;
260 1         2 my $self = {};
261 1         3 bless $self, $class;
262              
263 1         2 for my $required (qw(toolname)) {
264             croak "Required parameter '$required' not passed to '$class' constructor"
265 1 50       4 unless exists $settings{$required};
266             }
267 1         7 $self->{toolname} = $settings{"toolname"};
268 1         4 $self->{filename} = $self->toolname."conf";
269              
270             # initialize all attributes by passing arguments to accessor methods.
271 1         4 for my $attrib (keys %settings) {
272 3 50       10 croak "Invalid parameter '$attrib' passed to '$class' constructor"
273             unless $self->can($attrib);
274 3         8 $self->$attrib($settings{$attrib});
275             }
276              
277             # Fill missing settings with default values
278 1         2 for my $attrib (@available_settings) {
279 5 100       13 $self->$attrib($default_settings{$attrib}) unless defined($settings{$attrib});
280             }
281              
282 1         1 $self->{full_path} = undef;
283 1         3 @{$self->{allVersions}} = ();
  1         2  
284              
285 1         3 return $self;
286             }
287              
288             =item * Method C
289              
290             This method get/set the name of the tool for which the config file is.
291              
292             Usage:
293              
294             my $toolname = $cfg->toolname();
295             $cfg->toolname("tool name");
296              
297             =cut
298              
299             sub toolname($;$) {
300 9     9 1 25 my $self = shift;
301 9 100       17 if (@_) {
302 1         2 my $toolname = shift;
303 1         2 $self->{toolname} = $toolname;
304 1         2 $self->{full_path} = undef;
305             }
306 9         51 return $self->{toolname};
307             }
308              
309             =item * Method C
310              
311             This method get/set the file basename of the config file
312              
313             Usage:
314              
315             my $filename = $cfg->filename();
316             $cfg->filename("file name");
317              
318             =cut
319              
320             sub filename($;$) {
321 3     3 1 3 my $self = shift;
322 3 100       7 if (@_) {
323 1         1 my $filename = shift;
324 1         19 $self->{filename} = basename $filename;
325 1         2 $self->{full_path} = undef;
326             }
327 3         37 return $self->{filename};
328             }
329              
330             =item * Method C
331              
332             This method get/set the paths where the config file should be found.
333             The special __APPDIR__ path is OS dependant (see I module documentation).
334              
335             Usage:
336              
337             my @paths = $cfg->paths();
338             $cfg->paths(qw(list ./of/paths));
339              
340             =cut
341              
342             sub paths($;@) {
343 3     3 1 6 my $self = shift;
344 3 100       4 if (@_) {
345 1         2 my @p = @{$_[0]};
  1         2  
346 1         2 @{$self->{paths}} = @p;
  1         2  
347 1         3 $self->{full_path} = undef;
348             }
349 3         4 return @{$self->{paths}};
  3         8  
350             }
351              
352             =item * Method C
353              
354             This method get/set the value of interactive...
355              
356             Usage:
357              
358             my $v = $cfg->interactive();
359             $cfg->interactive(0); # or $cfg->interactive(1);
360              
361             =cut
362              
363             sub interactive($;$) {
364 2     2 1 4 my $self = shift;
365 2 100       5 if (@_) {
366 1         2 my $val = shift;
367 1         2 $self->{interactive} = $val;
368             }
369 2         5 return $self->{interactive};
370             }
371              
372             =item * Method C
373              
374             This method get/set the current version of the config file
375              
376             Usage:
377              
378             my $vers = $cfg->version();
379             $cfg->version("0.1.2");
380              
381             =cut
382              
383             sub version($;$) {
384 18     18 1 26 my $self = shift;
385 18 100       31 if (@_) {
386 3         4 my $version = shift;
387 3         3 $self->{version} = $version;
388 3         4 @{$self->{allVersions}} = ();
  3         5  
389             }
390 18         32 return $self->{version};
391             }
392              
393             =item * Method C
394              
395             This method returns (and prior computes if required) the array of all version's strings from the newest to the oldest.
396              
397             Usage:
398              
399             $cfg->versions();
400              
401             =cut
402              
403             sub versions($) {
404 11     11 1 20 my $self = shift;
405 11 100       13 if (!@{$self->{allVersions}}) {
  11         23  
406 2         3 my $cur_ver = $self->{version};
407 2         2 my $old_ver;
408 2         3 do {
409 9 100       17 if (ref($cur_ver) eq 'HASH') {
410 7         12 my @k = keys %{$cur_ver};
  7         16  
411 7         11 $cur_ver = $k[0];
412             }
413 9         18 $cur_ver =~ s/^to v//;
414 9         11 push @{$self->{allVersions}}, $cur_ver;
  9         14  
415 9         11 $old_ver = $cur_ver;
416 9         19 $cur_ver = $self->{patches}->{"patch from v$old_ver"};
417             } while (defined($cur_ver));
418             }
419 11         13 return @{$self->{allVersions}};
  11         150  
420             }
421              
422             =item * Method C
423              
424             This method get/set the current default content of the config file.
425             You can (should) use '__VERSION__' instead of giving it explicitely.
426             In such case, it will be replaced by the corresponding version string.
427              
428             Usage:
429              
430             my $cfg_txt = $cfg->defaultContent();
431             $cfg->defaultContent("# the default config content of the current version");
432              
433             =cut
434              
435             sub defaultContent($;$) {
436 13     13 1 18 my $self = shift;
437 13 100       26 if (@_) {
438 2         4 my $defaultContent = shift;
439 2         3 $self->{defaultContent} = $defaultContent;
440             }
441 13         23 return $self->{defaultContent};
442             }
443              
444             =item * Method C
445              
446             This method adds the patch from a given version of the default config file
447             to the preceeding version of the default config.
448              
449             Usage:
450              
451             $cfg->addPatch(
452             "from" => "some version",
453             "to" => "previous version",
454             "diffs" => '
455             @@ -1,1 +0,0 @@
456             -# blablabla
457             ');
458              
459             =cut
460              
461             sub addPatch($%) {
462 4     4 1 20 my $self = shift;
463 4         12 my %params = @_;
464 4         6 for my $required (qw(from to diffs)) {
465             croak "Required parameter '$required' not passed to addPatch method."
466 12 50       20 unless exists $params{$required};
467             }
468             croak "A patch already exists from version ".$params{"from"}."."
469 4 50       12 unless !defined($self->{patches}->{"patch from v".$params{"from"}});
470 4         23 $self->{patches}->{"patch from v".$params{"from"}}{"to v".$params{"to"}}= $params{"diffs"};
471 4         5 @{$self->{allVersions}} = ();
  4         11  
472             }
473              
474             =item * Method C
475              
476             This method gets (and prior computes if required) the path where the config file is.
477             If no config file is found, then the default current config file is created in the "correct" place.
478              
479             Usage:
480              
481             $cfg->getPath();
482              
483             =cut
484              
485             sub getPath($) {
486 11     11 1 22 my $self = shift;
487 11 100       144 return $self->{full_path} if defined($self->{full_path});
488              
489             # No config file already defined
490             # check all given paths in the given order
491 1         2 my @p = $self->paths;
492 1         2 foreach my $path (@p) {
493             #print "DBG:path=$path\n";
494 1   50     9 my $appdir = File::HomeDir->my_dist_data($self->toolname) || "";
495 1         129 $path =~ s/^__APPDIR__$/$appdir/;
496             #print "DBG:path=$path\n";
497 1 50       35 if (-e $path) {
498 1         6 my $full_path = File::Spec->rel2abs(File::Spec->join($path, $self->filename));
499 1 50       38 if (-e "$full_path") {
500 0         0 $self->{full_path} = $full_path;
501 0         0 return $self->{full_path};
502             }
503             }
504             }
505             # No config file found
506             # try to create a config file in all given paths in the given order
507 1         4 foreach my $path ($self->paths) {
508             #print "DBG3:path=$path\n";
509 1 50       3 if ($path =~ m/^__APPDIR__$/) {
510 0         0 my $appdir = File::HomeDir->my_dist_data($self->toolname, { create => 1 });
511 0         0 $path =~ s/^__APPDIR__$/$appdir/;
512             }
513             #print "DBG4:path=$path\n";
514 1 50       10 if (-e $path) {
515 1         4 my $full_path = File::Spec->rel2abs(File::Spec->join($path, $self->filename));
516 1         3 print "Creation of a default config file for ".$self->toolname.": $full_path\n";
517 1         5 my $current_default_config = $self->defaultContent;
518 1         4 $current_default_config =~ s/^\s+//;
519 1         7 $current_default_config =~ s/\s+$/\n/;
520 1         2 my $v = $self->version;
521 1         4 $current_default_config =~ s/__VERSION__/$v/;
522 1 50       110 open (CFG_FILE, ">".$full_path) or croak "Unable to create config file [".$full_path."]: $!";
523 1         14 print CFG_FILE $current_default_config;
524 1         23 close(CFG_FILE);
525 1         4 $self->{full_path} = $full_path;
526 1         10 return $self->{full_path};
527             }
528             }
529 0         0 return undef;
530             }
531              
532             =item * Method C
533              
534             This method check if the current config file is up-to-date and proposes an update if it is not.
535             The update tries to preserve custom user's settings.
536              
537             Usage:
538              
539             $cfg->update();
540              
541             =cut
542              
543             sub update($) {
544 1     1 1 6 my $self = shift;
545              
546             # Check if config file is up-to-date
547 1 50       3 open (CFG_FILE, "<".$self->getPath) or croak "Unable to open config file [".$self->getPath."]: $!";
548 1         4 my @versions = $self->versions;
549 1         2 my $current_user_config_version = $versions[-1];
550 1         2 my $current_user_config = "";
551 1         20 while () {
552 7         11 $current_user_config .= $_;
553 7 100       23 if (/^#.*configuration file (\d+.\d+.\d+.*)$/) {
554 1         4 $current_user_config_version = $1;
555             }
556             }
557 1         8 close(CFG_FILE);
558             #print "*** Current user use config file version $current_user_config_version:\n$current_user_config*** EOF\n";
559 1 50       3 if ($current_user_config_version ne $self->version) {
560 1         1 my $diffs;
561 1         3 print "Your configuration file [".$self->getPath."] is not up-to-date!\n";
562             eval {
563             # Computing original corresponding version file
564 1         3 my $old_default_config = $self->getDefaultContent($current_user_config_version);
565 1         10 $old_default_config =~ s/$current_user_config_version/__VERSION__/;
566             # Diffing original corresponding version file with potentially modified file
567 1         7 $current_user_config =~ s/$current_user_config_version/__VERSION__/;
568 1         9 $diffs = diff(\$old_default_config, \$current_user_config, { STYLE => 'OldStyle' });
569 1 50       472 if ($diffs) {
570             #print "*** Diffs between corresponding obsolete default version:\n$diffs*** END\n";
571             # Trying to apply these diffs to up-to-date version...
572 1         3 $current_user_config = patch($self->defaultContent, $diffs, { STYLE => 'OldStyle' });
573             #print "DBG:::\n".$self->getDefaultContent."DBG:::\n";
574             } else {
575 0         0 $current_user_config = $self->getDefaultContent;
576             }
577 0         0 my $v = $self->version;
578 0         0 $current_user_config =~ s/__VERSION__/$v/;
579 0         0 $_ = 1;
580 1 50       3 } or do {
581             #print "Unable to automatically propose an update for this file\n";
582 1         150 $current_user_config = $self->getDefaultContent;
583 1         3 my $v = $self->version;
584 1         3 $current_user_config =~ s/__VERSION__/$v/;
585             };
586             #print "*** diff between v. $current_user_config_version and ".$self->version." ***\n";
587 1         5 print diff($self->getPath, \$current_user_config, { STYLE => "Table", FILENAME_B => "Proposed Up-to-date config file"});
588 1         14309 my $answer;
589 1 50       4 if ($self->interactive) {
590 0 0       0 print "Do you want to upgrade your configuration file [".($diffs ? "y/N" : "Y/n")."] ? ";
591 0         0 $answer = ;
592             } else {
593 1         2 $answer = "Y\n";
594             }
595 1 50 33     6 if (($answer eq "Y\n") or ($answer eq "y\n") or (!$diffs and ($answer eq "\n"))) {
      0        
      33        
596 1         3 print "Upgrading the config file for ".$self->toolname.": ".$self->getPath."\n";
597 1 50       4 open (CFG_FILE, ">".$self->getPath) or croak "Unable to create config file [".$self->getPath."]: $!";
598 1         14 print CFG_FILE $current_user_config;
599 1         75 close(CFG_FILE);
600             } else {
601 0 0       0 if ($self->interactive) {
602 0         0 print "Do you want to continue [y/N] ? ";
603 0         0 $answer = ;
604             } else {
605 0         0 $answer = "Y\n";
606             }
607 0 0 0     0 exit 0 unless (($answer eq "Y\n") or ($answer eq "y\n"));
608             }
609             #print "*** End of diff between v. $current_user_config_version and ".$self->version." ***\n";
610             }
611             }
612              
613             =item * Method C
614              
615             This method gets the default config content of the given version. If ommited, then uses the current version.
616              
617             Usage:
618              
619             $cfg->getDefaultContent();
620             $cfg->getDefaultContent("a given version");
621              
622             =cut
623              
624             sub getDefaultContent($;$) {
625 9     9 1 41 my $self = shift;
626 9   66     20 my $wanted_version = shift || $self->version;
627 9         14 my $computed_version = $self->version;
628 9         16 my $computed_config = $self->defaultContent;
629 9         40 $computed_config =~ s/^\s+//;
630 9         68 $computed_config =~ s/\s+$/\n/;
631 9         11 my $error = undef;
632             eval {
633             # print "looking for version $wanted_version\n";
634 9 50       17 if (!grep(/^$wanted_version$/, $self->versions)) {
635             # print "not a valid version\n";
636 0         0 $error = "version '$wanted_version' is not valid.";
637             }
638             # print "against $computed_version\n";
639 9   66     37 while (!defined($error) && ($computed_version ne $wanted_version)) {
640 8         15 $error = "Unable to find a patch from version '$computed_version'";
641             # print "looking keys of patches\n";
642 8         10 foreach my $k (keys %{$self->{patches}}) {
  8         17  
643             # print "looking key '$k' against 'patch from v$computed_version'\n";
644 18 100       107 if ($k =~ /^patch from v$computed_version$/) {
645             # print "Found!!!\n";
646 8         16 my $previous_version;
647             my $str;
648 8         10 $error = "Unable to find a patch to version '$wanted_version'";
649 8         10 foreach my $kk (keys %{$self->{patches}->{$k}}) {
  8         39  
650             # print "looking sub key '$kk'\n";
651 8 50       27 if ($kk =~ /^to v(.*)$/) {
652             # print "Found again!!!\n";
653 8         15 $previous_version = $1;
654 8         14 $str = $self->{patches}->{$k}->{$kk};
655 8         20 $str =~ s/^\s+//;
656 8         44 $str =~ s/\s+$/\n/;
657 8         11 last;
658             }
659             }
660 8 50 33     24 if (defined($str) && defined($previous_version)) {
661             # print "\n============\n\n*** $k ***\n$str*** end $k ***\n\n";
662             # print "*** applying patch to v$computed_version would give v$previous_version ***\n";
663 8         20 $error = "Unable to apply the patch from version v$computed_version to v$previous_version\n";
664 8         26 $computed_config = patch($computed_config, $str, { STYLE => 'Unified' });
665             # print "$computed_config*** end of patch from v$computed_version to v$previous_version ***\n";
666 8         1873 $computed_version = $previous_version;
667 8         12 $error = undef;
668 8         34 last;
669             }
670             }
671             }
672             }
673 9         26 $computed_config =~ s/__VERSION__/$computed_version/;
674 9         21 !defined($error);
675 9 50       14 } or do {
676 0         0 croak $error."\n";
677 0         0 $computed_version = undef;
678 0         0 $computed_config = undef;
679             };
680 9         122 return $computed_config;
681             }
682              
683             ############################
684             # End of this Perl Module #
685             ############################
686              
687             ###########################
688             # Plain Old Documentation #
689             # Authors #
690             # Copyright and License #
691             ###########################
692              
693             =back
694              
695             =head1 AUTHORS
696              
697             Alban MANCHERON ELE,
698             Nicolas PHILIPPE ELE.
699              
700             =head1 COPYRIGHT AND LICENSE
701              
702             Copyright (C) 2012-2013 -- LIRMM/UM2
703             (Laboratoire d'Informatique, de Robotique et de
704             Microélectronique de Montpellier /
705             Université de Montpellier 2)
706             IRB/INSERM
707             (Institut de Recherche en Biothérapie /
708             Institut National de la Santé et de la
709             Recherche Médicale)
710              
711             =head2 FRENCH
712              
713             Ce fichier fait partie du Pipeline de traitement de données NGS de la
714             plateforme ATGC labélisée par le GiS IBiSA.
715              
716             Ce logiciel est régi par la licence CeCILL soumise au droit français et
717             respectant les principes de diffusion des logiciels libres. Vous pouvez
718             utiliser, modifier et/ou redistribuer ce programme sous les conditions de
719             la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA sur
720             le site "http://www.cecill.info".
721              
722             =head2 ENGLISH
723              
724             This File is part of the NGS data processing Pipeline of the ATGC
725             accredited by the IBiSA GiS.
726              
727             This software is governed by the CeCILL license under French law and
728             abiding by the rules of distribution of free software. You can use,
729             modify and/ or redistribute the software under the terms of the CeCILL
730             license as circulated by CEA, CNRS and INRIA at the following URL
731             "http://www.cecill.info".
732              
733             =cut
734              
735             ##############
736             # End of POD #
737             ##############
738              
739             1;
740             __END__