File Coverage

blib/lib/Config/FileManager.pm
Criterion Covered Total %
statement 202 222 90.9
branch 44 70 62.8
condition 8 23 34.7
subroutine 23 23 100.0
pod 12 12 100.0
total 289 350 82.5


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