aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorent Villard <warly@mandriva.com>2006-10-16 16:33:43 +0000
committerFlorent Villard <warly@mandriva.com>2006-10-16 16:33:43 +0000
commit0a44a5718469afd7ba370a44510454a2ffe91aef (patch)
tree2d817f73fcfdcb1513cf2a79021260bcd26491a6
parente8f142d1249d5d4684e5f879c21a0c8acc94710b (diff)
downloadmga-youri-core-0a44a5718469afd7ba370a44510454a2ffe91aef.tar
mga-youri-core-0a44a5718469afd7ba370a44510454a2ffe91aef.tar.gz
mga-youri-core-0a44a5718469afd7ba370a44510454a2ffe91aef.tar.bz2
mga-youri-core-0a44a5718469afd7ba370a44510454a2ffe91aef.tar.xz
mga-youri-core-0a44a5718469afd7ba370a44510454a2ffe91aef.zip
merging dev with upstream
-rw-r--r--lib/Youri/Config.pm295
1 files changed, 131 insertions, 164 deletions
diff --git a/lib/Youri/Config.pm b/lib/Youri/Config.pm
index 004f240..09cfbe6 100644
--- a/lib/Youri/Config.pm
+++ b/lib/Youri/Config.pm
@@ -3,225 +3,192 @@ package Youri::Config;
=head1 NAME
-Youri::Config - Youri configuration handler
+Youri::Application - Youri application handler
=head1 SYNOPSIS
- use Youri::Config;
+ use Youri::Application;
- my $config = Youri::Config->new(
- command_spec => [
- 'help|h!',
- ],
- file_spec => [
- 'foo=s',
- ],
+ my $app = Youri::Application->new(
+ options => {
+ help => '|h!'
+ },
directories => [ '/etc/youri', "$ENV{HOME}/.youri" ],
- file_name => 'app.conf',
- caller => $0,
+ file => 'app.conf',
);
- # get configuration directive
- my $foo = $config->get('foo');
+ # get command line argument
+ my $foo = $app->get_arg('foo');
- # get configuration section
- my %bar = $config->get_section('bar');
+ # get configuration file parameter
+ my $bar = $app->get_param('bar');
=head1 DESCRIPTION
-This class handle configuration for all YOURI tools.
-
-It uses distinct command line and config files specification, but merges the
-two inputs transparently, command line directives overriding config file
-directives with the same name.
-
-Given directories are scanned for a file with given name, and only the first
-one found is used. If B<--config> argument is given on command line, no
-scanning occurs. If no readable file is found, an exception is thrown.
-
-==head1 FORMAT
-
-The file format used is the one from AppConfig, with the additional ability to
-use YAML. Here is an exemple configuration file:
-
- [updates]
- class = Youri::Check::Check::Updates
- grabbers = <<EOF
- --- #YAML:1.0
- debian:
- class: Youri::Check::Check::Updates::Debian
- aliases:
- fuse: ~
- cpan:
- class: Youri::Check::Check::Updates::CPAN
- fedora:
- class: Youri::Check::Check::Updates::Fedora
- gentoo:
- class: Youri::Check::Check::Updates::Gentoo
- freshmeat:
- class: Youri::Check::Check::Updates::Freshmeat
- aliases:
- fuse: fuse-emulator
- EOF
-
-As a side-effect of using YAML, the use of character '~' anywhere is prohibited.
-Use ${HOME} instead.
+This class handle configuration for all YOURI applications.
+
+The command line specification is used to manage arguments through
+Getopt::Long. Unless B<--config> argument is given, the list of directories is
+then scanned for a file with given name, and halt as soon as it find one. If no
+readable file is found, an exception is thrown. The file is then processed
+through YAML::AppConfig. If parsing fails, an exception is thrown.
+
+=head1 CONFIGURATION FILE FORMAT
+
+=head2 SHARED KEYS
+
+In addition to the application-specific optional or mandatory parameters, all
+YOURI applications support the following optional top-level parameters:
+
+=over
+
+=item B<includes>
+
+A list of additional configuration files.
+
+=item B<foo>
+
+An arbitrary variable, usable everywhere else in the file.
+
+=back
+
+=head2 PLUGIN DEFINITION
+
+All YOURI application heavily rely on plugins defined in their configuration
+files. A plugin definition is composed from the following parameters:
+
+=over
+
+=item B<class>
+
+The class of this plugin.
+
+=item B<options>
+
+The options of this plugin.
+
+=back
=head1 SEE ALSO
-AppConfig, YAML
+YAML::AppConfig, Getopt::Long
=cut
use strict;
use warnings;
-use AppConfig qw/:argcount :expand/;
+use YAML::AppConfig;
+use Getopt::Long;
use File::Spec;
use Pod::Usage;
use Carp;
-use YAML;
sub new {
my ($class, %options) = @_;
- my ($command_config, $file_config);
-
- # process command line
- if ($options{command_spec}) {
- $command_config = AppConfig->new(
- {
- CREATE => 1,
- GLOBAL => {
- DEFAULT => '',
- EXPAND => EXPAND_VAR | EXPAND_ENV,
- ARGCOUNT => ARGCOUNT_ONE,
- }
- },
- @{$options{command_spec}}
- );
- $command_config->args();
-
- pod2usage(
- -input => $options{caller},
- -verbose => 0
- ) if $command_config->get('help');
- }
- # process config file
- $file_config = AppConfig->new(
- {
- CREATE => 1,
- GLOBAL => {
- DEFAULT => '',
- EXPAND => EXPAND_VAR | EXPAND_ENV,
- ARGCOUNT => ARGCOUNT_ONE,
- }
- },
- @{$options{file_spec}}
+ # command line arguments
+ my $args = {
+ verbose => 0
+ };
+ my @args;
+ if ($options{args}) {
+ while (my ($arg, $spec) = each %{$options{args}}) {
+ push(@args, ($arg . $spec) => \$args->{$arg});
+ }
+ }
+ push(@args,
+ 'config=s' => \$args->{config},
+ 'h|help' => \$args->{help},
+ 'v|verbose+' => \$args->{verbose}
);
+ GetOptions(@args);
+
+ if ($args->{help}) {
+ if (!@ARGV) {
+ # standard help, available immediatly
+ my $filename = (caller)[1];
+ pod2usage(
+ -input => $filename,
+ -verbose => 0
+ );
+ }
+ }
+ # config files parameters
+
# find configuration file to use
my $main_file;
-
- if ($command_config) {
- my $file = $command_config->get('config');
- if ($file) {
- if (! -f $file) {
- carp "Non-existing file $file, skipping";
- } elsif (! -r $file) {
- carp "Non-readable file $file, skipping";
- } else {
- $main_file = $file;
- }
- };
- }
-
- unless ($main_file) {
+ if ($args->{config}) {
+ if (! -f $args->{config}) {
+ croak "Non-existing file $args->{config}";
+ } elsif (! -r $args->{config}) {
+ croak "Non-readable file $args->{config}";
+ } else {
+ $main_file = $args->{config};
+ }
+ } else {
foreach my $directory (@{$options{directories}}) {
- my $file = "$directory/$options{file_name}";
+ my $file = "$directory/$options{file}";
next unless -f $file && -r $file;
$main_file = $file;
last;
}
+ croak 'No config file found, aborting' unless $main_file;
}
- croak 'No config file found, aborting' unless $main_file;
- $file_config->file($main_file);
-
- # process inclusions
- my $need_rescan;
- foreach my $include_file (split(/\s+/, $file_config->get('includes'))) {
- # convert relative path to absolute ones
- $include_file = File::Spec->rel2abs(
- $include_file, (File::Spec->splitpath($main_file))[1]
- );
-
- if (! -f $include_file) {
- warn "Non-existing file $include_file, skipping";
- } elsif (! -r $include_file) {
- warn "Non-readable file $include_file, skipping";
- } else {
- $file_config->file($include_file);
- $need_rescan = 1;
- }
+ my $params;
+ eval {
+ $params = YAML::AppConfig->new(file => $main_file);
+ };
+ if ($@) {
+ croak "Invalid configuration file $main_file, aborting";
}
- $file_config->file($main_file) if $need_rescan;
-
- # merge command line configuration
- if ($command_config) {
- my %command_vars = $command_config->varlist('.*');
- while (my ($key, $value) = each %command_vars) {
- $file_config->set($key, $value);
+ # process inclusions
+ my $includes = $params->get('includes');
+ if ($includes) {
+ foreach my $include_file (@{$includes}) {
+ # convert relative path to absolute ones
+ $include_file = File::Spec->rel2abs(
+ $include_file, (File::Spec->splitpath($main_file))[1]
+ );
+
+ if (! -f $include_file) {
+ warn "Non-existing file $include_file, skipping";
+ } elsif (! -r $include_file) {
+ warn "Non-readable file $include_file, skipping";
+ } else {
+ eval {
+ $params->merge(file => $include_file);
+ };
+ if ($@) {
+ carp "Invalid included configuration file $include_file, skipping";
+ }
+ }
}
}
my $self = bless {
- _appconfig => $file_config
+ _args => $args,
+ _params => $params
}, $class;
return $self;
}
-=head2 get_section($id)
-
-Simple wrapper around $config->varlist(), throwing a warning if section I<$id> doesn't exists.
-
-=cut
-
-sub get_section {
- my ($self, $id) = @_;
+sub get_arg {
+ my ($self, $arg) = @_;
croak "Not a class method" unless ref $self;
- my %values = $self->{_appconfig}->varlist('^' . $id . '_', 1);
-
- carp "No such section $id" unless %values;
-
- foreach my $value (values %values) {
- $value = _yamlize($value);
- }
-
- return %values;
+ return $self->{_args}->{$arg};
}
-sub get {
- my ($self, $variable) = @_;
+sub get_param {
+ my ($self, $param) = @_;
croak "Not a class method" unless ref $self;
- return _yamlize($self->{_appconfig}->get($variable));
-}
-
-sub _yamlize {
- my ($value) = @_;
-
- if ($value =~ /^--- #YAML:1.0/) {
- eval {
- $value = Load($value . "\n");
- };
- $value = undef if $@;
- }
-
- return $value;
+ return $self->{_params}->get($param);
}
=head1 COPYRIGHT AND LICENSE