diff options
-rw-r--r-- | hscript/meta.cc | 58 | ||||
-rw-r--r-- | hscript/meta.hh | 9 | ||||
-rw-r--r-- | hscript/script.cc | 3 | ||||
-rw-r--r-- | hscript/script_e.cc | 5 | ||||
-rw-r--r-- | hscript/script_i.hh | 12 | ||||
-rw-r--r-- | hscript/script_v.cc | 3 | ||||
-rw-r--r-- | tests/fixtures/0223-arch-basic.installfile | 6 | ||||
-rw-r--r-- | tests/fixtures/0224-arch-unknown.installfile | 6 | ||||
-rw-r--r-- | tests/fixtures/0225-arch-invalid.installfile | 6 | ||||
-rw-r--r-- | tests/spec/simulator_spec.rb | 7 | ||||
-rw-r--r-- | tests/spec/validator_spec.rb | 18 |
11 files changed, 131 insertions, 2 deletions
diff --git a/hscript/meta.cc b/hscript/meta.cc index b5309f3..f95e2ad 100644 --- a/hscript/meta.cc +++ b/hscript/meta.cc @@ -163,11 +163,65 @@ bool Hostname::execute(ScriptOptions opts) const { } +static std::set<std::string> valid_arches = { + "aarch64", "aarch64_be", "alpha", "armel", "armhf", "armv7", + "m68k", "mips", "mips64", "mipsel", "mips64el", + "pmmx", "ppc", "ppc64", + "riscv", "riscv64", + "s390x", "sparc", "sparc64", + "x86", "x86_64" +}; + + +Key *Arch::parseFromData(const std::string &data, int lineno, int *errors, + int *warnings) { + if(data.find_first_not_of("abcdefghijklmnopqrstuvwyxz1234567890") != + std::string::npos) { + if(errors) *errors += 1; + output_error("installfile:" + std::to_string(lineno), + "arch: expected CPU architecture name", + "'" + data + "' is not a valid CPU architecture name"); + return nullptr; + } + + if(valid_arches.find(data) == valid_arches.end()) { + if(warnings) *warnings += 1; + output_warning("installfile:" + std::to_string(lineno), + "arch: unknown CPU architecture '" + data + "'"); + } + + return new Arch(lineno, data); +} + +bool Arch::execute(ScriptOptions opts) const { + output_info("installfile:" + std::to_string(line), + "arch: setting system CPU architecture to " + value()); + + if(opts.test(Simulate)) { + std::cout << "printf '" << this->value() << "\\" << "n'" + << " > /target/etc/apk/arch" << std::endl; + return true; + } + +#ifdef HAS_INSTALL_ENV + std::ofstream arch_f("/target/etc/apk/arch", std::ios_base::trunc); + if(!arch_f) { + output_error("installfile:" + std::to_string(line), + "arch: cannot write target CPU architecture information"); + return false; + } + + arch_f << this->value() << std::endl; +#endif + return true; +} + + static std::regex valid_pkg("[0-9A-Za-z+_.-]*((>?<|[<>]?=|[~>])[0-9A-Za-z-_.]+)?"); -Key *PkgInstall::parseFromData(const std::string &data, int lineno, int *errors, - int *warnings) { +Key *PkgInstall::parseFromData(const std::string &data, int lineno, + int *errors, int *warnings) { std::string next_pkg; std::istringstream stream(data); std::set<std::string> all_pkgs; diff --git a/hscript/meta.hh b/hscript/meta.hh index 547349d..8740f96 100644 --- a/hscript/meta.hh +++ b/hscript/meta.hh @@ -30,6 +30,15 @@ public: bool execute(ScriptOptions) const override; }; +class Arch : public StringKey { +private: + Arch(int _line, const std::string &arch) : + StringKey(_line, arch) {} +public: + static Key *parseFromData(const std::string &, int, int *, int *); + bool execute(ScriptOptions) const override; +}; + class PkgInstall : public Key { private: const std::set<std::string> _pkgs; diff --git a/hscript/script.cc b/hscript/script.cc index cb67fe6..10dfe6b 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -40,6 +40,7 @@ const std::map<std::string, key_parse_fn> valid_keys = { {"pkginstall", &PkgInstall::parseFromData}, {"rootpw", &RootPassphrase::parseFromData}, + {"arch", &Arch::parseFromData}, {"language", &Language::parseFromData}, {"keymap", &Keymap::parseFromData}, {"firmware", &Firmware::parseFromData}, @@ -92,6 +93,8 @@ bool Script::ScriptPrivate::store_key(const std::string &key_name, Key *obj, return store_hostname(obj, lineno, errors, warnings, opts); } else if(key_name == "pkginstall") { return store_pkginstall(obj, lineno, errors, warnings, opts); + } else if(key_name == "arch") { + return store_arch(obj, lineno, errors, warnings, opts); } else if(key_name == "rootpw") { return store_rootpw(obj, lineno, errors, warnings, opts); } else if(key_name == "language") { diff --git a/hscript/script_e.cc b/hscript/script_e.cc index f8c4ff6..2ae48d0 100644 --- a/hscript/script_e.cc +++ b/hscript/script_e.cc @@ -438,6 +438,11 @@ bool Script::execute() const { } #endif /* HAS_INSTALL_ENV */ + /* REQ: Runner.Execute.pkginstall.arch */ + if(internal->arch) { + EXECUTE_OR_FAIL("arch", internal->arch) + } + /* REQ: Runner.Execute.pkginstall */ output_info("internal", "installing packages to target"); std::ostringstream pkg_list; diff --git a/hscript/script_i.hh b/hscript/script_i.hh index cb7da13..9d854eb 100644 --- a/hscript/script_i.hh +++ b/hscript/script_i.hh @@ -46,6 +46,8 @@ struct Script::ScriptPrivate { std::set<std::string> packages; /*! The root shadow line. */ std::unique_ptr<RootPassphrase> rootpw; + /*! The system CPU architecture. */ + std::unique_ptr<Arch> arch; /*! The system language. */ std::unique_ptr<Language> lang; /*! The system keymap. */ @@ -148,6 +150,16 @@ struct Script::ScriptPrivate { return true; } + bool store_arch(Key* obj, int line, int *errors, int *, ScriptOptions) { + if(arch) { + DUPLICATE_ERROR(arch, "arch", arch->value()) + return false; + } + std::unique_ptr<Arch> a(dynamic_cast<Arch *>(obj)); + arch = std::move(a); + return true; + } + bool store_rootpw(Key* obj, int line, int *errors, int *, ScriptOptions) { if(rootpw) { DUPLICATE_ERROR(rootpw, "rootpw", "an encrypted passphrase") diff --git a/hscript/script_v.cc b/hscript/script_v.cc index 7905cfa..ad40f72 100644 --- a/hscript/script_v.cc +++ b/hscript/script_v.cc @@ -259,6 +259,9 @@ bool Horizon::Script::validate() const { /* REQ: Runner.Validate.rootpw */ if(!internal->rootpw->validate(opts)) failures++; + /* REQ: Runner.Validate.arch */ + if(internal->arch && !internal->arch->validate(opts)) failures++; + /* REQ: Runner.Validate.language */ if(internal->lang && !internal->lang->validate(opts)) failures++; diff --git a/tests/fixtures/0223-arch-basic.installfile b/tests/fixtures/0223-arch-basic.installfile new file mode 100644 index 0000000..21c6e37 --- /dev/null +++ b/tests/fixtures/0223-arch-basic.installfile @@ -0,0 +1,6 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +arch ppc64 diff --git a/tests/fixtures/0224-arch-unknown.installfile b/tests/fixtures/0224-arch-unknown.installfile new file mode 100644 index 0000000..cc457c1 --- /dev/null +++ b/tests/fixtures/0224-arch-unknown.installfile @@ -0,0 +1,6 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +arch hppa diff --git a/tests/fixtures/0225-arch-invalid.installfile b/tests/fixtures/0225-arch-invalid.installfile new file mode 100644 index 0000000..42adb08 --- /dev/null +++ b/tests/fixtures/0225-arch-invalid.installfile @@ -0,0 +1,6 @@ +network false +hostname test.machine +pkginstall adelie-base +rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/ +mount /dev/sda1 / +arch Intel x86_64 diff --git a/tests/spec/simulator_spec.rb b/tests/spec/simulator_spec.rb index df2b2ae..67177c2 100644 --- a/tests/spec/simulator_spec.rb +++ b/tests/spec/simulator_spec.rb @@ -156,6 +156,13 @@ printf '%s\\t%s\\t%s\\t%s\\t0\\t0\\n' /dev/gwyn/source /usr/src auto noatime >> expect(last_command_started.stderr).to include("set domain name 'we-sing-it-proudly.new-romantics.club'") end end + context "simulating 'arch' execution" do + it "sets the architecture properly" do + use_fixture '0223-arch-basic.installfile' + run_simulate + expect(last_command_started.stdout).to include("printf 'ppc64\\n' > /target/etc/apk/arch") + end + end context "simulating 'repository' execution" do it "outputs default repositories when none are specified" do use_fixture '0001-basic.installfile' diff --git a/tests/spec/validator_spec.rb b/tests/spec/validator_spec.rb index eea3f2a..ba38563 100644 --- a/tests/spec/validator_spec.rb +++ b/tests/spec/validator_spec.rb @@ -203,6 +203,24 @@ RSpec.describe 'HorizonScript validation', :type => :aruba do expect(last_command_started).to have_output(/error: .*language.*invalid/) end end + context "for 'arch' key" do + it "succeeds with valid architecture" do + use_fixture '0223-arch-basic.installfile' + run_validate + expect(last_command_started).to have_output(PARSER_SUCCESS) + expect(last_command_started).to have_output(VALIDATOR_SUCCESS) + end + it "warns on unrecognised architecture" do + use_fixture '0224-arch-unknown.installfile' + run_validate + expect(last_command_started).to have_output(/warning: .*arch.*unknown CPU/) + end + it "fails on malformed architecture name" do + use_fixture '0225-arch-invalid.installfile' + run_validate + expect(last_command_started).to have_output(/error: .*arch.*expected/) + end + end context "for 'nameserver' key" do it "succeeds with IPv4 and IPv6 addresses" do use_fixture '0183-nameserver-basic.installfile' |