source: LMDZ6/branches/Amaury_dev/tools/fcm/lib/FCM/Admin/Util.pm @ 5095

Last change on this file since 5095 was 5095, checked in by abarral, 4 months ago

Revert cosp*/ from the trunk, as it's external code
Add missing bits from FCM2 source

File size: 10.3 KB
Line 
1# ------------------------------------------------------------------------------
2# Copyright (C) 2006-2021 British Crown (Met Office) & Contributors.
3#
4# This file is part of FCM, tools for managing and building source code.
5#
6# FCM is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# FCM is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with FCM. If not, see <http://www.gnu.org/licenses/>.
18# ------------------------------------------------------------------------------
19
20use strict;
21use warnings;
22
23package FCM::Admin::Util;
24
25use Exporter qw{import};
26use FCM::Admin::Config;
27use FCM::Admin::Runner;
28use File::Basename qw{dirname};
29use File::Copy qw{copy};
30use File::Path qw{mkpath rmtree};
31use IO::File;
32use SVN::Client;
33
34our @EXPORT_OK = qw{
35    option2config
36    read_file
37    run_copy
38    run_create_archive
39    run_extract_archive
40    run_mkpath
41    run_rename
42    run_rmtree
43    run_rsync
44    run_svn_info
45    run_svn_update
46    run_symlink
47    sed_file
48    write_file
49};
50
51my @HTML2PS = qw{html2ps -n -U -W b};
52my @PS2PDF  = qw{
53    ps2pdf
54    -dMaxSubsetPct=100
55    -dCompatibilityLevel=1.3
56    -dSubsetFonts=true
57    -dEmbedAllFonts=true
58    -dAutoFilterColorImages=false
59    -dAutoFilterGrayImages=false
60    -dColorImageFilter=/FlateEncode
61    -dGrayImageFilter=/FlateEncode
62    -dMonoImageFilter=/FlateEncode
63    -sPAPERSIZE=a4
64};
65
66# ------------------------------------------------------------------------------
67# Loads values of an option hash into the configuration.
68sub option2config {
69    my ($option_ref) = @_;
70    my $config = FCM::Admin::Config->instance();
71    for my $key (keys(%{$option_ref})) {
72        my $method = $key;
73        $method =~ s{-}{_}gxms;
74        $method = "set_$method";
75        if ($config->can($method)) {
76            $config->$method($option_ref->{$key});
77        }
78    }
79    return 1;
80}
81
82# ------------------------------------------------------------------------------
83# Reads lines from a file.
84sub read_file {
85    my ($path, $sub_ref) = @_;
86    my $file = IO::File->new($path);
87    if (!defined($file)) {
88        die("$path: cannot open for reading ($!).\n");
89    }
90    while (my $line = $file->getline()) {
91        $sub_ref->($line);
92    }
93    $file->close() || die("$path: cannot close for reading ($!).\n");
94    return 1;
95}
96
97# ------------------------------------------------------------------------------
98# Runs copy with checks and diagnostics.
99sub run_copy {
100    my ($source_path, $dest_path) = @_;
101    FCM::Admin::Runner->instance()->run(
102        "copy $source_path to $dest_path",
103        sub {
104            my $mode = (stat($source_path))[2];
105            my $rc = copy($source_path, $dest_path) && chmod($mode, $dest_path);
106            if (!$rc) {
107                die($!);
108            }
109            return $rc;
110        },
111    );
112}
113
114# ------------------------------------------------------------------------------
115# Creates a TAR-GZIP archive.
116sub run_create_archive {
117    my ($archive_path, $work_dir, @base_names) = @_;
118    FCM::Admin::Runner->instance()->run(
119        "creating archive $archive_path",
120        sub {
121            my $command
122                = qq{tar -c -z -C '$work_dir' -f -}
123                . q{ } . join(q{ }, map {qq{'$_'}} @base_names)
124                . qq{ | dd 'conv=fsync' 'of=$archive_path'};
125            return !system($command);
126            # Note: can use Archive::Tar, but "tar" is much faster.
127        },
128    );
129}
130
131# ------------------------------------------------------------------------------
132# Extracts from a TAR-GZIP archive.
133sub run_extract_archive {
134    my ($archive_path, $work_dir) = @_;
135    FCM::Admin::Runner->instance()->run(
136        "extracting archive $archive_path",
137        sub {
138            return !system(
139                qw{tar -x -z},
140                q{-C} => $work_dir,
141                q{-f} => $archive_path,
142            );
143            # Note: can use Archive::Tar, but "tar" is much faster.
144        },
145    );
146}
147
148# ------------------------------------------------------------------------------
149# Runs mkpath with checks and diagnostics.
150sub run_mkpath {
151    my ($path) = @_;
152    if (!-d $path) {
153        FCM::Admin::Runner->instance()->run(
154            "creating $path",
155            sub {return mkpath($path)},
156        );
157    }
158    return 1;
159}
160
161# ------------------------------------------------------------------------------
162# Runs rename with checks and diagnostics.
163sub run_rename {
164    my ($source_path, $dest_path) = @_;
165    FCM::Admin::Runner->instance()->run(
166        "renaming $source_path to $dest_path",
167        sub {
168            run_mkpath(dirname($dest_path));
169            my $rc = rename($source_path, $dest_path);
170            if (!$rc) {
171                die($!);
172            }
173            return $rc;
174        },
175    );
176    return 1;
177}
178
179# ------------------------------------------------------------------------------
180# Runs rmtree with checks and diagnostics.
181sub run_rmtree {
182    my ($path) = @_;
183    if (-e $path) {
184        FCM::Admin::Runner->instance()->run(
185            "removing $path",
186            sub {
187                rmtree($path);
188                return !-e $path;
189            },
190        );
191    }
192    return 1;
193}
194
195# ------------------------------------------------------------------------------
196# Runs rsync.
197sub run_rsync {
198    my ($sources_ref, $dest_path, $option_list_ref) = @_;
199    FCM::Admin::Runner->instance()->run(
200        sprintf('mirroring %s <- %s', $dest_path, join(q{ }, @{$sources_ref})),
201        sub {return !system(
202            q{rsync},
203            ($option_list_ref ? @{$option_list_ref} : ()),
204            @{$sources_ref},
205            $dest_path,
206        )},
207    );
208    return 1;
209}
210
211# ------------------------------------------------------------------------------
212# Runs "svn info".
213sub run_svn_info {
214    my ($path) = @_;
215    my $return;
216    my $ctx = SVN::Client->new();
217    $ctx->info($path, undef, 'WORKING', sub {$return = $_[1]}, 0);
218    return $return;
219}
220
221# ------------------------------------------------------------------------------
222# Runs "svn update".
223sub run_svn_update {
224    my ($path) = @_;
225    my @return;
226    my $ctx = SVN::Client->new(
227        notify => sub {
228            if ($path ne $_[0]) {
229                push(@return, $_[0]);
230            }
231        }
232    );
233    $ctx->update($path, 'HEAD', 1);
234    return @return;
235}
236
237# ------------------------------------------------------------------------------
238# Runs symlink with checks and diagnostics.
239sub run_symlink {
240    my ($source_path, $dest_path) = @_;
241    FCM::Admin::Runner->instance()->run(
242        "creating symlink: $source_path -> $dest_path",
243        sub {
244            my $rc = symlink($source_path, $dest_path);
245            if (!$rc) {
246                die($!);
247            }
248            return $rc;
249        },
250    );
251    return 1;
252}
253
254# ------------------------------------------------------------------------------
255# Edits content of a file.
256sub sed_file {
257    my ($path, $sub_ref) = @_;
258    my @lines;
259    read_file(
260        $path,
261        sub {
262            my ($line) = @_;
263            $line = $sub_ref->($line);
264            push(@lines, $line);
265        },
266    );
267    write_file($path, @lines);
268}
269
270# ------------------------------------------------------------------------------
271# Writes content to a file.
272sub write_file {
273    my ($path, @contents) = @_;
274    mkpath(dirname($path));
275    my $file = IO::File->new($path, q{w});
276    if (!defined($file)) {
277        die("$path: cannot open for writing ($!).\n");
278    }
279    for my $content (@contents) {
280        $file->print($content);
281    }
282    $file->close() || die("$path: cannot close for writing ($!).\n");
283    return 1;
284}
285
2861;
287__END__
288
289=head1 NAME
290
291FCM::Admin::Util
292
293=head1 SYNOPSIS
294
295    use FCM::Admin::Util qw{ ... };
296    # ... see descriptions of individual functions for detail
297
298=head1 DESCRIPTION
299
300This module contains utility functions for the administration of Subversion
301repositories and Trac environments hosted by the FCM team.
302
303=head1 FUNCTIONS
304
305=over 4
306
307=item option2config($option_ref)
308
309Loads the values of an option hash into
310L<FCM::Admin::Config|FCM::Admin::Config>.
311
312=item read_file($path,$sub_ref)
313
314Reads from $path. For each $line the file, calls $sub_ref->($line).
315
316=item run_copy($source_path,$dest_path)
317
318Copies $source_path to $dest_path, with diagnostic.
319
320=item run_create_archive($archive_path,$work_dir,@base_names)
321
322Creates a TAR-GZIP archive at $archive_path using $work_dir as the working
323directory and @base_names as members of the archive. Depends on GNU "tar" or
324compatible.
325
326=item run_extract_archive($archive_path,$work_dir)
327
328Extracts a TAR-GZIP archive at $archive_path using $work_dir as the working
329directory. Depends on GNU "tar" or compatible.
330
331=item run_mkpath($path)
332
333Creates $path if it does not already exist, with diagnostic.
334
335=item run_rename($source_path,$dest_path)
336
337Same as the core I<rename>, but with diagnostic.
338
339=item run_rmtree($path)
340
341Removes $path, with diagnostic.
342
343=item run_rsync(\@sources,$dest_path,$option_list_ref)
344
345Invokes the "rsync" shell command with diagnostics to mirror the paths in
346@sources to $dest_path. Command line options can be specified in a list with
347$option_list_ref. Depends on "rsync".
348
349=item run_svn_info($path)
350
351Wrapper of the info() method of L<SVN::Client|SVN::Client>. Expects $path to be
352a Subversion working copy. Returns the C<svn_info_t> object as described by the
353info() method of L<SVN::Client|SVN::Client>.
354
355=item run_svn_update($path)
356
357Wrapper of the update() method of L<SVN::Client|SVN::Client>. Expects $path to be
358a Subversion working copy. Returns a list of updated paths.
359
360=item run_symlink($source_path,$dest_path)
361
362Same as the core I<symlink>, but with diagnostic.
363
364=item sed_file($path,$sub_ref)
365
366For each $line in $path, runs $line = $sub_ref->($line). Writes results back to
367$path.
368
369=item write_file($path,$content)
370
371Writes $content to $path.
372
373=back
374
375=head1 SEE ALSO
376
377L<FCM::Admin::Config|FCM::Admin::Config>,
378L<FCM::Admin::Runner|FCM::Admin::Runner>,
379L<SVN::Client|SVN::Client>
380
381=head1 COPYRIGHT
382
383Copyright (C) 2006-2021 British Crown (Met Office) & Contributors.
384
385=cut
Note: See TracBrowser for help on using the repository browser.