diff options
author | Andreas Guldstrand <andreas.guldstrand@gmail.com> | 2016-09-01 13:02:13 +0200 |
---|---|---|
committer | Andreas Guldstrand <andreas.guldstrand@gmail.com> | 2016-09-01 13:02:13 +0200 |
commit | 353e59034a230b6a502b92ac16226e3b6a98c821 (patch) | |
tree | 316cf36e979a37c1ab671c9c5cca2b4d587bd5e0 | |
parent | c869532d063368ad0fe015eab7603c38e62c03c3 (diff) | |
download | sbotools2-353e59034a230b6a502b92ac16226e3b6a98c821.tar.xz |
sboinstall: add support for templates. this closes #38.
-rw-r--r-- | man1/sboinstall.1 | 13 | ||||
-rwxr-xr-x | sboinstall | 77 | ||||
-rwxr-xr-x | t/15-usage.t | 6 | ||||
-rwxr-xr-x | t/31-template.t | 164 |
4 files changed, 241 insertions, 19 deletions
diff --git a/man1/sboinstall.1 b/man1/sboinstall.1 index f6a4fc4..bee6b0f 100644 --- a/man1/sboinstall.1 +++ b/man1/sboinstall.1 @@ -4,7 +4,8 @@ sboinstall - install slackbuilds .SH SYNAPSES .P -sboinstall [-h|-v] [-d TRUE|FALSE] [-j #|FALSE] [-c TRUE|FALSE] [-NrRip] sbo_name (sbo_name) +sboinstall [-h|-v] [-d TRUE|FALSE] [-j #|FALSE] [-c TRUE|FALSE] [-NrRip] [--create-template FILE] sbo_name (sbo_name) +sboinstall [-h|-v] [-d TRUE|FALSE] [-j #|FALSE] [-c TRUE|FALSE] [-NRip] --use-template FILE .SH DESCRIPTION .P sboinstall is used to install SBos. If the -r flag is NOT specified, sboinstall will pull the list of requirements from the .info file for any specified slackbuild. If such a list exists, sboinstall will look to see whether or not those requirements are already installed, and if not, it will ask whether or not it should attempt to install them first. This is recursive, so that ordering happens correctly. sboinstall will refuse to handle circular requirements. sboinstall will attempt to note groupadd and useradd commands in README files and offer to run those first. If the README appears to document options of the KEY=value form, sboinstall will offer the opportunity to set options. @@ -54,6 +55,16 @@ Skip viewing of the README and the yes or no question which accompanies it. Anyt .RS This option causes sboinstall to skip requirement handling, but still show the README and prompt the user to proceed. .RE +.P +--create-template (FILE) +.RS +Create a template for the SlackBuilds including any optional commands or build options that you wish to set and store this in the specified FILE. +.RE +.P +--use-template (FILE) +.RS +Use a template file and let it specify all the build options and optional commands to be used. This also enables the --nointeractive flag. +.RE .SH EXIT CODES .P sboinstall can exit with the following exit codes: @@ -13,15 +13,17 @@ use 5.16.0; use strict; use warnings FATAL => 'all'; -use SBO::Lib qw/ %config get_arch get_build_queue get_installed_cpans get_installed_packages get_sbo_location get_sbo_locations merge_queues print_failures process_sbos show_version slackbuilds_or_fetch usage_error user_prompt /; +use SBO::Lib qw/ %config _ERR_OPENFH get_arch get_build_queue get_installed_cpans get_installed_packages get_sbo_location get_sbo_locations merge_queues open_fh print_failures process_sbos show_version slackbuilds_or_fetch slurp usage_error user_prompt /; use Getopt::Long qw(:config bundling); use File::Basename; +use JSON::PP; my $self = basename($0); sub show_usage { print <<"EOF"; Usage: $self [options] sbo + $self --use-template file Options (defaults shown first where applicable): -h|--help: @@ -42,6 +44,11 @@ Options (defaults shown first where applicable): non-interactive; skips README and all prompts. -R|--norequirements: view the README but do not parse requirements, commands, or options. + --create-template (FILE): + create a template with specified requirements, commands, and options. + --use-template (FILE): + use a template created by --create-template to install requirements with + specified commands and options. This also enables the --nointeractive flag. EOF return 1; @@ -50,24 +57,28 @@ EOF my $noclean = $config{NOCLEAN}; my $distclean = $config{DISTCLEAN}; my $jobs = $config{JOBS}; -my ($help, $vers, $no_install, $non_int, $no_reqs, $compat32); +my ($help, $vers, $no_install, $non_int, $no_reqs, $compat32, $ctemp, $utemp); GetOptions( - 'help|h' => \$help, - 'version|v' => \$vers, - 'noclean|c=s' => \$noclean, - 'distclean|d=s' => \$distclean, - 'noinstall|i' => \$no_install, - 'jobs|j=s' => \$jobs, - 'compat32|p' => \$compat32, - 'nointeractive|r' => \$non_int, - 'norequirements|R' => \$no_reqs, + 'help|h' => \$help, + 'version|v' => \$vers, + 'noclean|c=s' => \$noclean, + 'distclean|d=s' => \$distclean, + 'noinstall|i' => \$no_install, + 'jobs|j=s' => \$jobs, + 'compat32|p' => \$compat32, + 'nointeractive|r' => \$non_int, + 'norequirements|R' => \$no_reqs, + 'create-template=s' => \$ctemp, + 'use-template=s' => \$utemp, ); if ($help) { show_usage(); exit 0 } if ($vers) { show_version(); exit 0 } -if (!@ARGV) { show_usage(); exit 1 } +if (!@ARGV and not length $utemp) { show_usage(); exit 1 } +if (defined $utemp and not length $utemp) { show_usage(); exit 1 } +if (defined $ctemp and not length $ctemp) { show_usage(); exit 1 } $noclean = $noclean eq 'TRUE' ? 1 : 0; $distclean = $distclean eq 'TRUE' ? 1 : 0; @@ -84,14 +95,25 @@ if ($compat32) { # if we can't find SLACKBUILDS.TXT in $config{HOME}, prompt to fetch the tree slackbuilds_or_fetch(); -my (%warnings, $build_queue, %locations); +my (%warnings, $build_queue, %locations, $template); -if ($no_reqs or $non_int) { - $build_queue = \@ARGV; +if (length $utemp) { + my $json = JSON::PP->new->latin1; + $non_int = 1; + + my $data = slurp($utemp); + do { warn "Could not read template from $utemp.\n"; exit _ERR_OPENFH } if not length $data; + + $template = $json->decode($data); + $build_queue = $template->{build_queue}; } else { - for my $sbo (@ARGV) { - my $queue = get_build_queue([$sbo], \%warnings); - $build_queue = merge_queues($build_queue, $queue); + if ($no_reqs or $non_int) { + $build_queue = \@ARGV; + } else { + for my $sbo (@ARGV) { + my $queue = get_build_queue([$sbo], \%warnings); + $build_queue = merge_queues($build_queue, $queue); + } } } @@ -117,6 +139,10 @@ for my $sbo (@$build_queue) { # check for already-installeds and prompt for the rest my (@temp_queue, %commands, %options); +if (defined $template) { + %commands = %{ $template->{commands} }; + %options = %{ $template->{options} }; +} my $added = ' added to install queue.'; FIRST: for my $sbo (@$build_queue) { my $name = $compat32 ? "$sbo-compat32" : $sbo; @@ -183,6 +209,21 @@ unless ($non_int) { exit 0 unless <STDIN> =~ /^[Yy\n]/; } +if (defined $ctemp) { + my ($temp_fh, $exit) = open_fh($ctemp, '>'); + do { warn $temp_fh; exit $exit } if $exit; + + my $json = JSON::PP->new->latin1->pretty->canonical; + my $build_settings = { + build_queue => $build_queue, + commands => \%commands, + options => \%options, + }; + print {$temp_fh} $json->encode( $build_settings ); + close $temp_fh; + print "\nTemplate $ctemp saved.\n"; +} + my ($failures, $exit) = process_sbos( TODO => $build_queue, CMDS => \%commands, diff --git a/t/15-usage.t b/t/15-usage.t index 94eb9f0..0e1ee37 100755 --- a/t/15-usage.t +++ b/t/15-usage.t @@ -102,6 +102,7 @@ sbofind { expected => $sbofind, exit => 1 }; ## sboinstall my $sboinstall = <<'SBOINSTALL'; Usage: sboinstall [options] sbo + sboinstall --use-template file Options (defaults shown first where applicable): -h|--help: @@ -122,6 +123,11 @@ Options (defaults shown first where applicable): non-interactive; skips README and all prompts. -R|--norequirements: view the README but do not parse requirements, commands, or options. + --create-template (FILE): + create a template with specified requirements, commands, and options. + --use-template (FILE): + use a template created by --create-template to install requirements with + specified commands and options. This also enables the --nointeractive flag. SBOINSTALL sboinstall '-h', { expected => $sboinstall }; diff --git a/t/31-template.t b/t/31-template.t new file mode 100755 index 0000000..1871824 --- /dev/null +++ b/t/31-template.t @@ -0,0 +1,164 @@ +#!/usr/bin/env perl + +use 5.16.0; +use strict; +use warnings FATAL => 'all'; +use Test::More; +use Capture::Tiny qw/ capture_merged /; +use FindBin '$RealBin'; +use lib $RealBin; +use Test::Sbotools qw/ make_slackbuilds_txt set_lo sboinstall sboremove restore_perf_dummy /; +use File::Temp qw/ tempdir /; + +if ($ENV{TEST_INSTALL}) { + plan tests => 18; +} else { + plan skip_all => 'Only run these tests if TEST_INSTALL=1'; +} + +sub cleanup { + capture_merged { + system(qw!/sbin/removepkg envsettingtest!); + system(qw!/sbin/removepkg envsettingtest2!); + unlink "$RealBin/LO-readme/envsettingtest/perf.dummy"; + unlink "$RealBin/LO-readme/envsettingtest2/perf.dummy"; + system(qw!rm -rf /tmp/SBo/envsettingtest-1.0!); + system(qw!rm -rf /tmp/SBo/envsettingtest2-1.0!); + system(qw!rm -rf /tmp/package-envsettingtest!); + system(qw!rm -rf /tmp/package-envsettingtest2!); + }; +} + +cleanup(); +make_slackbuilds_txt(); +set_lo("$RealBin/LO-readme"); +restore_perf_dummy(); + +my $tempdir = tempdir(CLEANUP => 1); + +# 1-3: sboinstall envsettingtest - fail +sboinstall '-i', '--create-template', "$tempdir/1.temp", 'envsettingtest', { input => "n\ny\ny", expected => qr!Template \Q$tempdir/1.temp saved.\E\n!, exit => 3 }; +is (scalar capture_merged { system cat => "$tempdir/1.temp" }, <<"TEMP1", "1.temp is correct"); +{ + "build_queue" : [ + "envsettingtest" + ], + "commands" : { + "envsettingtest" : null + }, + "options" : { + "envsettingtest" : null + } +} +TEMP1 +sboinstall '--use-template', "$tempdir/1.temp", { exit => 3, expected => qr{FOO isn't bar!.*envsettingtest: envsettingtest.SlackBuild return non-zero}s }; + +# 4-6: sboinstall envsettingtest - fail 2 +sboinstall '-i', '--create-template', "$tempdir/2.temp", 'envsettingtest', { input => "y\nFOO=foo\ny\ny", expected => qr!Template \Q$tempdir/2.temp saved.\E\n!, exit => 3 }; +is (scalar capture_merged { system cat => "$tempdir/2.temp" }, <<"TEMP2", "2.temp is correct"); +{ + "build_queue" : [ + "envsettingtest" + ], + "commands" : { + "envsettingtest" : null + }, + "options" : { + "envsettingtest" : "FOO=foo" + } +} +TEMP2 +sboinstall '--use-template', "$tempdir/2.temp", { exit => 3, expected => qr{FOO isn't bar!.*envsettingtest: envsettingtest.SlackBuild return non-zero}s }; + +# 7-9: sboinstall envsettingtest - success +sboinstall '-i', '--create-template', "$tempdir/3.temp", 'envsettingtest', { input => "y\nFOO=bar\ny\ny", expected => qr!Template \Q$tempdir/3.temp saved.\E\n! }; +is (scalar capture_merged { system cat => "$tempdir/3.temp" }, <<"TEMP3", "3.temp is correct"); +{ + "build_queue" : [ + "envsettingtest" + ], + "commands" : { + "envsettingtest" : null + }, + "options" : { + "envsettingtest" : "FOO=bar" + } +} +TEMP3 +sboinstall '--use-template', "$tempdir/3.temp", { expected => qr{Install queue: envsettingtest.*Cleaning for envsettingtest-1[.]0}s }; +sboremove 'envsettingtest', { input => "y\ny", test => 0 }; + +# 10-12: sboinstall envsettingtest2 - fail prereq +sboinstall '-i', '--create-template', "$tempdir/4.temp", 'envsettingtest2', { input => "n\ny\ny\nFOO=quux\ny\ny\nn", expected => qr!Template \Q$tempdir/4.temp saved.\E\n!, exit => 3 }; +is (scalar capture_merged { system cat => "$tempdir/4.temp" }, <<"TEMP4", "4.temp is correct"); +{ + "build_queue" : [ + "envsettingtest", + "envsettingtest2" + ], + "commands" : { + "envsettingtest" : null, + "envsettingtest2" : null + }, + "options" : { + "envsettingtest" : null, + "envsettingtest2" : "FOO=quux" + } +} +TEMP4 +sboinstall '--use-template', "$tempdir/4.temp", { exit => 3, expected => qr{Install queue: envsettingtest envsettingtest2.*FOO isn't bar!.*envsettingtest: envsettingtest.SlackBuild return non-zero}s }; + +# 13-15: sboinstall envsettingtest2 - success +sboinstall '-i', '--create-template', "$tempdir/5.temp", 'envsettingtest2', { input => "y\nFOO=bar\ny\ny\nFOO=quux\ny\ny", expected => qr!Template \Q$tempdir/5.temp saved.\E\n! }; +is (scalar capture_merged { system cat => "$tempdir/5.temp" }, <<"TEMP5", "5.temp is correct"); +{ + "build_queue" : [ + "envsettingtest", + "envsettingtest2" + ], + "commands" : { + "envsettingtest" : null, + "envsettingtest2" : null + }, + "options" : { + "envsettingtest" : "FOO=bar", + "envsettingtest2" : "FOO=quux" + } +} +TEMP5 +sboinstall '--use-template', "$tempdir/5.temp", { expected => qr{Install queue: envsettingtest envsettingtest2.*Cleaning for envsettingtest2-1[.]0}s }; +sboremove 'envsettingtest2', { input => "n\ny\ny\ny", test => 0 }; + +# 16-18: sboinstall commandinreadme +SKIP: { + skip "Only run useradd/groupadd commands under Travis CI", 3 unless (defined $ENV{TRAVIS} and $ENV{TRAVIS} eq 'true'); + skip "Only run useradd/groupadd commands if there is no test user/group", 3, if (defined getgrnam('test') or defined getpwnam('test')); + + sboinstall '-i', '--create-template', "$tempdir/6.temp", 'commandinreadme', { input => "y\ny\ny", expected => qr!Template \Q$tempdir/6.temp saved.\E\n! }; + capture_merged { system(qw/ userdel test /); system(qw/ groupdel test /); }; + is (scalar capture_merged { system cat => "$tempdir/6.temp" }, <<"TEMP6", "6.temp is correct"); +{ + "build_queue" : [ + "commandinreadme" + ], + "commands" : { + "commandinreadme" : [ + "groupadd -g 200 test", + "useradd -u 200 -g 200 -d /tmp test" + ] + }, + "options" : { + "commandinreadme" : 0 + } +} +TEMP6 + sboinstall '--use-template', "$tempdir/6.temp", { expected => sub { ! m/exited non-zero/ } }; + sboremove 'commandinreadme', { input => "y\ny", test => 0 }; + + capture_merged { system(qw/ userdel test /); system(qw/ groupdel test /); }; +} + +# Cleanup +END { + cleanup(); +} |