From d20d2a641351b7f9e8c9bd9b841d8de4d824aa82 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 10 Aug 2019 17:14:37 +0300 Subject: Add default options loading and merging API --- tests/default-options/buildfile | 7 ++ tests/default-options/driver.cxx | 186 +++++++++++++++++++++++++++++++++++++++ tests/default-options/testscript | 109 +++++++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 tests/default-options/buildfile create mode 100644 tests/default-options/driver.cxx create mode 100644 tests/default-options/testscript (limited to 'tests') diff --git a/tests/default-options/buildfile b/tests/default-options/buildfile new file mode 100644 index 0000000..5530a10 --- /dev/null +++ b/tests/default-options/buildfile @@ -0,0 +1,7 @@ +# file : tests/default-options/buildfile +# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +import libs = libbutl%lib{butl} + +exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/default-options/driver.cxx b/tests/default-options/driver.cxx new file mode 100644 index 0000000..a2ed43d --- /dev/null +++ b/tests/default-options/driver.cxx @@ -0,0 +1,186 @@ +// file : tests/default-options/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#ifndef __cpp_lib_modules_ts +#include +#include +#include +#endif + +// Other includes. + +#ifdef __cpp_modules_ts +#ifdef __cpp_lib_modules_ts +import std.core; +import std.io; +#endif +import butl.path; +import butl.path_io; +import butl.optional; +import butl.fdstream; +import butl.default_options; +#else +#include +#include +#include // eof() +#include +#include +#include +#endif + +using namespace std; +using namespace butl; + +// Usage: argv[0] [-f ] [-d ] [-s ] [-h ] +// [-e] +// +// Parse default options files, merge them with the command line options, and +// print the resulting options to STDOUT one per line. Note that the options +// instance is a vector of arbitrary strings. +// +// -f +// Default options file name. Can be specified multiple times. +// +// -d +// Directory to start the default options files search from. +// +// -s +// System directory. +// +// -h +// Home directory. +// +// -e +// Print the default options entries (rather than the merged options) to +// STDOUT one per line in the following format: +// +// ,, +// +int +main (int argc, const char* argv[]) +{ + using butl::optional; + + class scanner + { + public: + scanner (const string& f): ifs_ (f, fdopen_mode::in, ifdstream::badbit) {} + + optional + next () + { + string s; + return !eof (getline (ifs_, s)) ? optional (move (s)) : nullopt; + } + + private: + ifdstream ifs_; + }; + + enum class unknow_mode + { + fail + }; + + class options: public vector + { + public: + bool + parse (scanner& s, unknow_mode, unknow_mode) + { + bool r (false); + while (optional o = s.next ()) + { + push_back (move (*o)); + r = true; + } + return r; + } + + void + merge (const options& o) + { + insert (end (), o.begin (), o.end ()); + } + }; + + // Parse and validate the arguments. + // + default_options_files fs; + optional sys_dir; + optional home_dir; + options cmd_ops; + bool print_entries (false); + + for (int i (1); i != argc; ++i) + { + string op (argv[i]); + + if (op == "-f") + { + assert (++i != argc); + fs.files.push_back (path (argv[i])); + } + else if (op == "-d") + { + assert (++i != argc); + fs.start_dir = dir_path (argv[i]); + } + else if (op == "-s") + { + assert (++i != argc); + sys_dir = dir_path (argv[i]); + } + else if (op == "-h") + { + assert (++i != argc); + home_dir = dir_path (argv[i]); + } + else if (op == "-e") + { + print_entries = true; + } + else + cmd_ops.push_back (argv[i]); + } + + // Load and print the default options. + // + default_options def_ops ( + load_default_options (sys_dir, + home_dir, + fs)); + + if (print_entries) + { + for (const default_options_entry& e: def_ops) + { + cout << e.file << ','; + + for (const string& o: e.options) + { + if (&o != &e.options[0]) + cout << ' '; + + cout << o; + } + + cout << (e.remote ? ",true" : ",false") << endl; + } + } + + // Merge the options and print the result. + // + options ops (merge_default_options (def_ops, cmd_ops)); + + if (!print_entries) + { + for (const string& o: ops) + cout << o << endl; + } + + return 0; +} diff --git a/tests/default-options/testscript b/tests/default-options/testscript new file mode 100644 index 0000000..c0c3816 --- /dev/null +++ b/tests/default-options/testscript @@ -0,0 +1,109 @@ +# file : tests/default-options/testscript +# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +# Note that when cross-testing the driver may not be able to run the command +# due to the meaningless program path. +# ++if ($test.target != $build.host) + exit +end + +sys_dir = $canonicalize([dir_path] $~/build2) ++mkdir -p $sys_dir/local + ++echo 'sys-foo' >=$sys_dir/foo ++echo 'sys-bar' >=$sys_dir/bar ++echo 'sys-local-foo' >=$sys_dir/local/foo ++echo 'sys-local-bar' >=$sys_dir/local/bar + +home_dir = $canonicalize([dir_path] $~/home) ++mkdir -p $home_dir/.build2/local/ + ++echo 'home-foo' >=$home_dir/.build2/foo ++echo 'home-bar' >=$home_dir/.build2/bar ++echo 'home-local-foo' >=$home_dir/.build2/local/foo ++echo 'home-local-bar' >=$home_dir/.build2/local/bar + +: in-home +: +{ + d = $home_dir/work/.build2 + +mkdir -p $d/local/ + + +echo 'work-foo' >=$d/foo + +echo 'work-bar' >=$d/bar + +echo 'work-local-foo' >=$d/local/foo + +echo 'work-local-bar' >=$d/local/bar + + d = $home_dir/work/project/.build2 + +mkdir -p $d/local/ + +touch $home_dir/work/project/.git + + +echo 'project-foo' >=$d/foo + +echo 'project-bar' >=$d/bar + +echo 'project-local-foo' >=$d/local/foo + +echo 'project-local-bar' >=$d/local/bar + + d = $home_dir/work/project/package/.build2 + +mkdir -p $d/local/ + + +echo 'package-foo' >=$d/foo + +echo 'package-bar' >=$d/bar + +echo 'package-local-foo' >=$d/local/foo + +echo 'package-local-bar' >=$d/local/bar + + start_dir = $canonicalize([dir_path] $home_dir/work/project/package) + + : entries + : + $* -e -f foo -f bar -d $start_dir -s $sys_dir -h $home_dir cmd-foo cmd-bar >>/~%EOO%d + %\.+/build2/foo,sys-foo,false% + %\.+/build2/bar,sys-bar,false% + %\.+/build2/local/foo,sys-local-foo,false% + %\.+/build2/local/bar,sys-local-bar,false% + %\.+/home/.build2/foo,home-foo,false% + %\.+/home/.build2/bar,home-bar,false% + %\.+/home/.build2/local/foo,home-local-foo,false% + %\.+/home/.build2/local/bar,home-local-bar,false% + %\.+/home/work/.build2/foo,work-foo,false% + %\.+/home/work/.build2/bar,work-bar,false% + %\.+/home/work/.build2/local/foo,work-local-foo,false% + %\.+/home/work/.build2/local/bar,work-local-bar,false% + %\.+/home/work/project/.build2/foo,project-foo,true% + %\.+/home/work/project/.build2/bar,project-bar,true% + %\.+/home/work/project/.build2/local/foo,project-local-foo,true% + %\.+/home/work/project/.build2/local/bar,project-local-bar,true% + %\.+/home/work/project/package/.build2/foo,package-foo,true% + %\.+/home/work/project/package/.build2/bar,package-bar,true% + %\.+/home/work/project/package/.build2/local/foo,package-local-foo,true% + %\.+/home/work/project/package/.build2/local/bar,package-local-bar,true% + EOO + + : merged + : + $* -f foo -f bar -d $start_dir -s $sys_dir -h $home_dir cmd-foo cmd-bar >>EOO + sys-foo + sys-bar + sys-local-foo + sys-local-bar + home-foo + home-bar + home-local-foo + home-local-bar + work-foo + work-bar + work-local-foo + work-local-bar + project-foo + project-bar + project-local-foo + project-local-bar + package-foo + package-bar + package-local-foo + package-local-bar + cmd-foo + cmd-bar + EOO +} -- cgit v1.1