File Coverage

blib/lib/oEdtk/Run.pm
Criterion Covered Total %
statement 39 222 17.5
branch 0 82 0.0
condition 0 31 0.0
subroutine 13 21 61.9
pod 0 7 0.0
total 52 363 14.3


line stmt bran cond sub pod time code
1             package oEdtk::Run;
2            
3 1     1   6 use strict;
  1         1  
  1         36  
4 1     1   6 use warnings;
  1         2  
  1         28  
5            
6 1     1   1191 use Archive::Zip qw(:ERROR_CODES);
  1         129248  
  1         162  
7 1     1   13 use Cwd;
  1         1  
  1         71  
8 1     1   6 use File::Copy;
  1         1  
  1         67  
9 1     1   5 use File::Path qw(rmtree);
  1         3  
  1         52  
10 1     1   1051 use Text::CSV;
  1         10748  
  1         7  
11 1     1   42 use oEdtk::Config qw(config_read);
  1         2  
  1         58  
12 1     1   674 use oEdtk::DBAdmin qw(db_connect);
  1         4  
  1         123  
13 1     1   788 use oEdtk::EDMS qw(EDMS_prepare EDMS_process EDMS_import);
  1         3  
  1         108  
14 1     1   1990 use oEdtk::Outmngr qw(omgr_import omgr_export);
  1         6  
  1         108  
15 1     1   676 use oEdtk::TexDoc;
  1         5  
  1         85  
16            
17 1     1   13 use Exporter;
  1         2  
  1         2791  
18            
19             our $VERSION = 0.8011;
20             our @ISA = qw(Exporter);
21             our @EXPORT_OK = qw(
22             oe_status_to_msg
23             oe_compo_run
24             oe_after_compo
25             oe_csv_to_doc
26             oe_outmngr_output_run_tex
27             );
28            
29             sub oe_cmd_run($) {
30 0     0 0   my $cmd = shift;
31            
32             # Redirect stdout to stderr so the output of the command doesn't confuse
33             # the scripts which parse stdout to get the list of files we generated.
34 0           $cmd .= ' >&2';
35            
36 0           warn "INFO : Running command \"$cmd\"\n";
37 0           eval { system($cmd); };
  0            
38 0 0         return if $? == 0;
39            
40 0           my $reason = oe_status_to_msg($?);
41 0           die "ERROR: Command failed : $reason\n";
42            
43 0           return 1;
44             }
45            
46             sub oe_cmd_run_bg($$) {
47 0     0 0   my ($cmd, $ref) = @_;
48            
49 0 0         if (ref($ref) ne 'SCALAR') {
50 0           die "ERROR: oe_cmd_run_bg() expects a SCALAR reference\n";
51             }
52            
53             # Install a signal handler first so that we are notified if our
54             # child exits prematurely, which should happen fairly rarely.
55             $SIG{'CHLD'} = sub {
56 0     0     my $pid = waitpid(-1, 0);
57 0 0         if ($pid > 0) {
58 0 0         if ($? != 0) {
59 0           my $msg = oe_status_to_msg($?);
60 0           die "ERROR: LaTeX process exited prematurely : $msg\n";
61             }
62 0           $$ref = 0;
63             }
64 0           };
65            
66 0           $cmd .= ' >&2';
67 0           my $pid = fork();
68 0 0         if (!defined($pid)) {
69 0           die "ERROR: Cannot fork process: $!\n";
70             }
71 0 0         if ($pid) {
72             # Parent process.
73 0           warn "INFO : Successfully started subprocess, pid $pid\n";
74             } else {
75             # Child process.
76 0           exec($cmd);
77             # NOT REACHED
78 0           exit;
79             }
80 0           return $pid;
81             }
82            
83             sub oe_status_to_msg($) {
84 0     0 0   my ($status) = @_;
85            
86 0 0         return undef if $status == 0;
87 0           my $msg = '';
88 0 0         if ($? == -1) {
    0          
89 0           $msg = "failed to execute: $!";
90             } elsif ($? & 127) {
91 0           $msg = sprintf("child died with signal %d", $? & 127);
92             } else {
93 0           $msg = sprintf("child exited with value %d", $? >> 8);
94             }
95 0           return $msg;
96             }
97            
98             sub oe_compo_run($;$) {
99 0     0 0   my ($app, $options) = @_;
100            
101 0           my $cfg = config_read(['COMPO'], $app);
102 0   0       my $mode = $options->{'mode'} || 'pdf';
103            
104 0           my $exe;
105 0 0         if ($mode =~ /^dvi/) {
106 0           $exe = $cfg->{'EDTK_COMPO_CMD_DVI'};
107             } else {
108 0           $exe = $cfg->{'EDTK_COMPO_CMD_PDF'};
109             }
110            
111             # XXXXXXXXXXXXX C'EST ICI QU'ON CHANGE LE MODE D'EXECUTION EN MODE INCLUDE
112             # Usage: pdftex [OPTION]... [TEXNAME[.tex]] [COMMANDS]
113             # or: pdftex [OPTION]... \FIRST-LINE
114             # or: pdftex [OPTION]... &FMT ARGS
115             # Run pdfTeX on TEXNAME, usually creating TEXNAME.pdf.
116             # Any remaining COMMANDS are processed as pdfTeX input, after TEXNAME is read.
117             # If the first line of TEXNAME is %&FMT, and FMT is an existing .fmt file,
118             # use it. Else use `NAME.fmt', where NAME is the program invocation name,
119             # most commonly `pdftex'.
120             #
121             # Alternatively, if the first non-option argument begins with a backslash,
122             # interpret all non-option arguments as a line of pdfTeX input.
123             #
124             # Alternatively, if the first non-option argument begins with a &, the
125             # next word is taken as the FMT to read, overriding all else. Any
126             # remaining arguments are processed as above.
127             #
128             # If no arguments or options are specified, prompt for input.
129            
130 0           my $param;
131             # if (defined $cfg->{'EDTK_COMPO_INCLUDE'} && $cfg->{'EDTK_COMPO_INCLUDE'}=~/yes/i) {
132             # # NE FONCTIONNE PAS, À REVOIR EN FONCTION DE pdftex --help
133             # $param = "./$app." . $cfg->{'EDTK_EXT_WORK'};
134             # } else {
135 0           $param = $cfg->{'EDTK_DIR_SCRIPT'} . "/$app." . $cfg->{'EDTK_EXT_COMPO'};
136             # }
137            
138             # Use the \edExtra mechanism to include additional packages if needed.
139 0 0         if (defined($options->{'extrapkgs'})) {
140 0           my $extra = '\newcommand{\edExtra}{';
141 0           foreach (@{$options->{'extrapkgs'}}) {
  0            
142 0           $extra .= '\RequirePackage';
143 0           my ($pkg, $opts);
144 0 0         if (ref($_) eq 'ARRAY') {
145 0           ($pkg, $opts) = @$_;
146 0           $extra .= "[$opts]";
147             } else {
148 0           $pkg = $_;
149             }
150 0           $extra .= "{$pkg}";
151             }
152 0           $param = $extra . '}\input{' . $param . '}';
153             }
154 0 0         if (defined($options->{'jobname'})) {
155 0           $exe .= " -jobname=$options->{'jobname'}";
156             }
157            
158 0           my $cmd = $cfg->{'EDTK_BIN_COMPO'} . "/$exe \"$param\"";
159            
160             # Handle additional include directories.
161 0           my @incdirs = ();
162 0 0         if (defined($options->{'incdirs'})) {
163 0           @incdirs = @{$options->{'incdirs'}};
  0            
164             }
165             # Add EDTK_DIR_DATA_IN to the list of directories LaTeX will
166             # look into for when we run via runEdtk.pl.
167 0           push(@incdirs, $cfg->{'EDTK_DIR_DATA_IN'});
168 0           my $old = $ENV{'TEXINPUTS'};
169 0 0         if (defined($old)) {
170 0           push(@incdirs, $old);
171             }
172 0           $ENV{'TEXINPUTS'} = ';' . join(';', @incdirs);
173            
174 0           my $pid;
175             # In FIFO mode we need to run the LaTeX process asynchronously.
176 0 0         if ($options->{'fifo'}) {
177 0           $pid = oe_cmd_run_bg($cmd, \$options->{'cldstatus'});
178             } else {
179 0           oe_cmd_run($cmd);
180             }
181             # Restore the old environment.
182 0 0         if (defined($old)) {
183 0           $ENV{'TEXINPUTS'} = $old;
184             } else {
185 0           delete $ENV{'TEXINPUTS'};
186             }
187            
188 0 0         return $pid if $options->{'fifo'};
189             }
190            
191            
192             sub oe_after_compo($$) {
193 0     0 0   my ($app, $options) = @_;
194            
195 0           my $cfg = config_read(['EDTK_DB'], $app);
196 0   0       my $mode = $options->{'mode'} || 'pdf';
197            
198             # Run dvipdfm if we were running in DVI+PDF mode.
199 0 0         if ($mode eq 'dvipdf') {
200 0           my $exe = $cfg->{'EDTK_COMPO_CMD_DVIPDF'};
201 0           my $cmd = "$cfg->{'EDTK_BIN_COMPO'}/$exe $app.dvi";
202 0           oe_cmd_run($cmd);
203             }
204            
205             # Output the full path to the generated PDF file (used by the
206             # composition.sh script to determine what we have generated).
207 0           my $pdf = "$app.pdf";
208 0 0         if (defined($options->{'jobname'})) {
209 0           $pdf = $options->{'jobname'} . ".pdf";
210             }
211 0 0         if (! -f $pdf) {
212 0           die "ERROR: Could not find the generated PDF file ($pdf)\n";
213             }
214 0           my $cwd = getcwd();
215 0           print "$cwd/$pdf\n";
216            
217             # Cleanup?
218 0           unlink("$app.aux");
219 0 0         if ($cfg->{'EDTK_TYPE_ENV'} ne 'Test') {
220 0 0         unlink($options->{'outfile'}) if ($options->{'outfile'});
221             }
222            
223             # If no index was requested, we are done.
224 0 0         if (!$options->{'index'}) {
225 0           warn "INFO : No index file was requested, done.\n";
226 0           return;
227             }
228            
229             # If an index file was requested, see if we need to import it
230             # for later processing, and/or if we need to produce a GED pack.
231 0           my $index = "$app." . $options->{'idldoc'} . ".idx1";
232 0 0         if (! -f $index) {
233 0           die "ERROR: Could not find the generated index file ($index)\n";
234             }
235            
236 0           my $corp = $options->{'corp'};
237 0 0         if (!defined($corp)) {
238 0           die "ERROR: No corporation name given\n";
239             }
240            
241 0           my $dbh = db_connect($cfg, 'EDTK_DBI_PARAM', { RaiseError => 1 });
242 0           my $appdata = $dbh->selectrow_hashref("SELECT * FROM EDTK_REFIDDOC " .
243             "WHERE ED_REFIDDOC = ? AND (ED_CORP = ? OR ED_CORP = '%')", undef,
244             $app, $corp);
245            
246 0 0         if (!defined($appdata)) {
247 0           warn "INFO : Application $app was not found in EDTK_REFIDDOC\n";
248             }
249            
250             # Do we need to import the index ?
251             # if ($options->{'massmail'} or (defined($appdata) && $appdata->{'ED_MASSMAIL'} eq 'Y')) {
252 0 0 0       if ( (defined($appdata) && $appdata->{'ED_MASSMAIL'} eq 'Y')
      0        
      0        
      0        
253             or
254             (defined($appdata) && $appdata->{'ED_MASSMAIL'} eq 'C' && $options->{'massmail'})
255             ) {
256 0           my $doclib = "$cfg->{'EDTK_DIR_DOCLIB'}/$options->{'doclib'}";
257 0           warn "INFO : Moving $pdf into $doclib\n";
258 0           copy($pdf, $doclib);
259 0           warn "INFO : Importing index into database...\n";
260 0           omgr_import($app, $index, $corp);
261             }
262            
263             # Do we need to prepare for GED processing?
264             # if (defined($appdata) && $appdata->{'ED_EDOCSHARE'} eq 'Y') {
265 0 0 0       if ( (defined($appdata) && $appdata->{'ED_EDOCSHARE'} eq 'Y')
      0        
      0        
      0        
266             or
267             (defined($appdata) && $appdata->{'ED_EDOCSHARE'} eq 'C' && $options->{'edms'})
268             ) {
269            
270 0 0 0       if ($options->{'cgi'} && $options->{'cgiged'}) {
    0          
271 0           warn "INFO : Direct GED processing...\n";
272 0           my ($index, @pdfs) = EDMS_process($app, $options->{'idldoc'},
273             $pdf, $index);
274 0 0         EDMS_import($index, @pdfs)
275             or die "ERROR: EDMS_import failed\n";
276             } elsif (!$options->{'cgi'}) {
277 0           warn "INFO : Preparing ZIP archive for GED...\n";
278 0           EDMS_prepare($app, $options->{'idldoc'}, $pdf, $index);
279             }
280             }
281            
282             # Now we can remove the index file.
283 0 0         if ($cfg->{'EDTK_TYPE_ENV'} ne 'Test') {
284 0           unlink($index);
285             }
286            
287 0           return 1;
288             }
289            
290             sub oe_csv_to_doc($$) {
291 0     0 0   my ($input, $endtag) = @_;
292            
293 0           my $doc = oEdtk::TexDoc->new;
294 0 0         open(my $fh, '<', $input) or die "Cannot open \"$input\": $!\n";
295            
296 0           my $csv = Text::CSV->new({ binary => 1 });
297 0           my @cols = map { s/_//g; $_ } @{$csv->getline($fh)};
  0            
  0            
  0            
298            
299 0           while (my $vals = $csv->getline($fh)) {
300 0           my %lists = ();
301 0           for (my $i = 0; $i < $#cols; $i++) {
302 0           my ($key, $val) = ($cols[$i], $vals->[$i]);
303 0 0         if ($key !~ /^(\D+)\d+$/) {
    0          
304 0           $doc->append($key, $val);
305             } elsif ($val ne '') {
306 0           push(@{$lists{$1}}, $val);
  0            
307             }
308             }
309 0           while (my ($key, $val) = each %lists) {
310 0           $doc->append_table($key, @$val);
311             }
312 0           $doc->append($endtag);
313             }
314 0           close($fh);
315 0           return $doc;
316             }
317            
318             sub oe_outmngr_output_run_tex($;$) {
319 0     0 0   my ($filter, $type) = @_;
320            
321             # Avec la distinction aplication de mise en forme et traitement de lotissement, le test suivant n'a plus de sens
322             # if ($type !~ /[MTD]/) {
323             # # oe_outmngr_output_run : on ne passe dans index_output qu'en cas de Mass, Debug ou Test de lotissement
324             # warn "INFO : traitement OM '$type' -> lotissement suspendu\n";
325             # return 1;
326             # }
327            
328 0           my $cfg = config_read('COMPO');
329 0           my $type_env= $cfg->{'EDTK_TYPE_ENV'};
330 0           my $basedir = $cfg->{'EDTK_DIR_OUTMNGR'};
331            
332 0           warn "INFO : Appel omgr_export\n";
333 0           my @lots = omgr_export(%$filter);
334            
335 0           foreach (@lots) {
336 0           my ($lot, @doclibs) = @$_;
337            
338 0           my $lotdir = "$basedir/$lot";
339 0 0         chdir($lotdir) or die "Cannot change directory to \"$lotdir\": $!\n";
340 0           warn "INFO : Preparing job ticket $lot for compo (doclibs = @doclibs)\n";
341            
342             # Création du flux intermédiaire.
343 0           my $doc = oEdtk::TexDoc->new;
344 0           $doc->append(oe_csv_to_doc("$lot.job", 'edStartPg'));
345            
346 0           warn "INFO : Preparing index $lot for compo\n";
347 0           $doc->append(oe_csv_to_doc("$lot.idx", 'xFLigne'));
348 0           $doc->append('edEndPg');
349 0           $doc->append('xFinFlux');
350            
351 0 0         open(my $txt, '>', 'LOTPDF.txt') or die "Cannot open \"LOT.txt\": $!\n";
352 0           print $txt "$doc";
353 0           close($txt);
354            
355 0           warn "INFO : Composition $lot in $basedir/$lotdir\n";
356 0           my $options = {
357             jobname => $lot,
358             incdirs => [$cfg->{'EDTK_DIR_DOCLIB'}]
359             };
360 0           oe_compo_run('LOTPDF', $options);
361 0           oe_after_compo('LOTPDF', $options);
362            
363             # Generate the final PDF file.
364 0 0         if (! -f "$lot.pdf") {
365 0           die "ERROR: Composition did not create PDF file\n";
366             }
367            
368 0           warn "INFO : Packaging $basedir $lot\n";
369 0           my $zip = Archive::Zip->new();
370 0           $zip->addFile("$lotdir/$lot.idx", "$lot.idx");
371 0           $zip->addFile("$lotdir/$lot.pdf", "$lot.pdf");
372 0 0         die "ERROR: Could not create zip archive\n"
373             unless $zip->writeToFileNamed("$basedir/$lot.zip") == AZ_OK;
374             }
375            
376             # Change the current working directory to the base directory, otherwise
377             # we wouldn't be able to remove the temporary directory we are still in.
378 0           chdir($basedir);
379 0           foreach (@lots) {
380 0           my ($lot) = @$_;
381            
382 0           print "$basedir/$lot.zip\n";
383 0 0         if ($type_env !~ /^De/i) { # on ne la fait pas pour les environnements de Dev ou Debug
384 0           warn "INFO : suppression des fichiers intermediaires ($type_env)\n";
385 0           rmtree("$basedir/$lot");
386             }
387             }
388 0           return @lots;
389             }
390            
391             1;