diff options
-rwxr-xr-x | bin/youri-submit.in | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/bin/youri-submit.in b/bin/youri-submit.in new file mode 100755 index 0000000..c232cfb --- /dev/null +++ b/bin/youri-submit.in @@ -0,0 +1,410 @@ +#!/usr/bin/perl +# $Id$ + +=head1 NAME + +youri-upload - package upload agent + +=head1 VERSION + +Version 2.0 + +=head1 SYNOPSIS + +youri-upload [options] <target> <files> + +Options: + + --config <file> use file <file> as config file + --skip-pre <pre> skip pre <pre> + --skip-action <action> skip action <action> + --skip-check <check> skip check <check> + --skip-post <post> skip post <post> + --skip-reject <reject> skip reject <reject> + --define <key>=<value> pass additional values + --list-targets list available targets + --list-checks <target> list configured checks for for <target> + --list-actions <target> list configured actions for for <target> + --verbose verbose run + --test test run + --help print this help message + +=head1 DESCRIPTION + +B<youri-upload> allows to upload packages in a repository. + +All packages given on command lines are passed to a list of check plugins, +depending on given upload target. If none of them fails, all packages are +passed to a list of action plugins, depending also on given upload target. + +=head1 OPTIONS + +=over + +=item B<--config> I<file> + +Use given file as configuration, instead of normal one. + +=item B<--skip-pre> I<id> + +Skip pre transaction plugin with given identity + +=item B<--skip-check> I<id> + +Skip check plugin with given identity. + +=item B<--skip-action> I<id> + +Skip action plugin with given identity. + +=item B<--skip-post> I<id> + +Skip post transaction plugin with given identity. + +=item B<--skip-reject> I<id> + +Skip reject action plugin with given identity. + +=item B<--define> <key>=<value> + +Define additional parameters, to be used by plugins. + +=item B<--verbose> + +Produce more verbose output (can be used more than once) + +=item B<--test> + +Don't perform any modification. + +=item B<--list-targets> + +List available targets + +=item B<--list-checks> I<target> + +List configured checks for given target + +=item B<--list-actions> I<target> + +List configured actions for given target + +=item B<--help> + +Print a brief help message and exits. + +=back + +=head1 CONFIGURATION + +Configuration is read from the first file found among: + +=over + +=item * the one specified by B<--config> option on command-line + +=item * $HOME/.youri/upload.conf + +=item * @sysconfdir@/youri/upload.conf + +=back + +All additional configuration files specified by B<includes> directive are then +processed. Then command line options. Any directive overrides prior definition. + +=over + +=item B<includes> I<files> + +Uses space-separated list I<files> as a list of additional configuration files. + +=item B<repository> I<id> + +Declares a repository object with identity I<id>. + +=item B<targets> I<ids> + +Declares a list of upload target objects with identity taken in space-separated list I<ids>. + +=back + +Each object declared in configuration must be fully defined later, using a +configuration section, starting with bracketed object identity, followed by at +least a class directive, then any number of additional object-specific +directives. + +Example: + + objects = foo + + [foo] + class = Foo::Bar + key1 = value1 + key2 = value2 + +=head1 SEE ALSO + +Youri::Config, for configuration file format. + +Each used plugin man page, for available options. + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2002-2006, YOURI project + +This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. + +=cut + +use strict; +use warnings; + +use Youri::Config; +use Youri::Utils; +use Pod::Usage; + +my $config = Youri::Config->new( + command_spec => [ + 'config=s', + 'skip-pre=s@', + 'skip-check=s@', + 'skip-action=s@', + 'skip-post=s@', + 'skip-reject=s@', + 'list-targets!', + 'list-checks=s', + 'list-actions=s', + 'define=s%', + 'help|h!', + 'test|t!', + 'server|s', + 'verbose|v!' + ], + file_spec => [ + 'includes=s', + 'targets=s', + 'repository=s', + ], + directories => [ '@sysconfdir@', "$ENV{HOME}/.youri" ], + file_name => 'upload.conf', + caller => $0, +); + +# compute available targets first +my %targets = map { $_ => 1 } split(/\s+/, $config->get('targets')); + +if ($config->get('list-targets')) { + print join(' ', keys %targets) . "\n"; + exit 0; +} elsif ($config->get('list-checks')) { + my %target = get_target_config($config->get('list-checks')); + print join(' ', @{$target{checks}}) . "\n"; + exit 0; +} elsif ($config->get('list-actions')) { + my %target = get_target_config($config->get('list-actions')); + print join(' ', @{$target{actions}}) . "\n"; + exit 0; +} + +pod2usage(-verbose => 0, -message => "No target specified, aborting\n") + unless @ARGV > 0; + +# convenient global flags +my $test = $config->get('test'); +my $verbose = $config->get('verbose'); + +# check target +my $target = shift @ARGV; +my %target = get_target_config($target); + +# create repository +my $repository; +my $repository_id = $config->get('repository'); +die "No repository declared" unless $repository_id; +print "Creating repository $repository_id\n" if $verbose; +eval { + $repository = create_instance( + 'Youri::Repository', + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + targets => [ keys %targets ], + $config->get_section($repository_id) + ); +}; +die "Failed to create repository $repository_id: $@\n" if $@; + +# perfrom pre action +my %skip_pres = map { $_ => 1 } @{$config->get('skip-pre')}; +my $pre_packages = []; +my $ok = 1; +foreach my $id (@{$target{pre}}) { + next if $skip_pres{$id}; + print "Creating pre $id\n" if $verbose; + my $pre; + eval { + $pre = create_instance( + 'Youri::Upload::Pre', + id => $id, + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + $config->get_section($id) + ); + }; + if ($@) { + print STDERR "Failed to create pre $id: $@\n"; + } else { + print "running pre $id\n" if $verbose; + unless ($pre->run($pre_packages, $repository, $target, $config->get('define'))) { + print STDERR "Error: " . $pre->get_error() . "\n"; + $ok = 0; + } + } +} +exit(1) unless $ok; + +# create packages group +my @packages_group; +foreach my $group ((map { [ { section => "", file => $_ } ] } @ARGV), @$pre_packages) { + my @packages; + foreach my $opt (@$group) { + print "Preparing upload for $opt->{file}\n" if $verbose; + push( + @packages, + create_instance( + 'Youri::Package', + class => $repository->get_package_class(), + file => $opt->{file}, + %$opt + ) + ); + } + @packages or next; + +# check all packages pass all tests + my %skip_checks = map { $_ => 1 } @{$config->get('skip-check')}; + my $ok = 1; + my @error; + foreach my $id (@{$target{checks}}) { + next if $skip_checks{$id}; + print "Creating check $id\n" if $verbose; + my $check; + eval { + $check = create_instance( + 'Youri::Upload::Check', + id => $id, + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + $config->get_section($id) + ); + }; + if ($@) { + print STDERR "Failed to create check $id: $@\n"; + } else { + foreach my $package (@packages) { + print "running check $id on package $package\n" if $verbose; + unless ($check->run($package, $repository, $target, $config->get('define'))) { + my $err = $check->get_error(); + print STDERR "Error: $err\n"; + push @error, $err; + $ok = 0 + } + } + + } + } + if (!$ok) { + # reject the packages + my %skip_rejects = map { $_ => 1 } @{$config->get('skip-reject')}; + foreach my $id (@{$target{rejects}}) { + next if $skip_rejects{$id}; + print "Creating reject $id\n" if $verbose; + my $reject; + eval { + $reject = create_instance( + 'Youri::Upload::Reject', + id => $id, + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + $config->get_section($id) + ); + }; + if ($@) { + print STDERR "Failed to create reject $id: $@\n"; + } else { + foreach my $package (@packages) { + print "running reject $id on package $package\n" if $verbose; + eval { + $reject->run($package, \@error, $repository, $target, $config->get('define')); + }; + if ($@) { + print STDERR "Failed to run action $id on package $package: $@\n"; + } + } + } + } + next + } + +# proceed further + my %skip_actions = map { $_ => 1 } @{$config->get('skip-action')}; + foreach my $id (@{$target{actions}}) { + next if $skip_actions{$id}; + print "Creating action $id\n" if $verbose; + my $action; + eval { + $action = create_instance( + 'Youri::Upload::Action', + id => $id, + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + $config->get_section($id) + ); + }; + if ($@) { + print STDERR "Failed to create action $id: $@\n"; + } else { + foreach my $package (@packages) { + print "running action $id on package $package\n" if $verbose; + eval { + $action->run($package, $repository, $target, $config->get('define')); + }; + if ($@) { + print STDERR "Failed to run action $id on package $package: $@\n"; + } + } + } + } +} +# perfrom post action +my %skip_posts = map { $_ => 1 } @{$config->get('skip-post')}; +foreach my $id (@{$target{post}}) { + next if $skip_posts{$id}; + print "Creating post $id\n" if $verbose; + my $post; + eval { + $post = create_instance( + 'Youri::Upload::Post', + id => $id, + test => $test, + verbose => $verbose > 0 ? $verbose - 1 : 0, + $config->get_section($id) + ); + }; + if ($@) { + print STDERR "Failed to create post $id: $@\n"; + } else { + print "running post $id\n" if $verbose; + unless ($post->run($repository, $target, $config->get('define'))) { + print STDERR "Error: " . $post->get_error() . "\n"; + } + } +} + +sub get_target_config { + my ($id) = @_; + die "Unavailable target $target" unless $targets{$id}; + + my %target = $config->get_section($id); + die "Undefined target $id" unless %target; + return %target; +} |