diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2022-04-08 17:49:15 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2022-04-08 17:55:29 +0300 |
commit | 5cdcfa38ad51e72a3c6bbe8c1f578e5ea21e8f64 (patch) | |
tree | 744fe5854e7a93e225a7de926aff8720517605df | |
parent | 45ec3066eae5e2f62cdefbb751d6878b5e39d022 (diff) |
Make changes required for CIci
100 files changed, 55083 insertions, 21 deletions
diff --git a/bpkg/argument-grouping.cxx b/bpkg/argument-grouping.cxx new file mode 100644 index 0000000..abbae6f --- /dev/null +++ b/bpkg/argument-grouping.cxx @@ -0,0 +1,85 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/argument-grouping.hxx> + +#include <map> +#include <cstring> + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_argument_grouping_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg\033[0m \033[1m{\033[0m \033[4moptions\033[0m \033[1m}+\033[0m \033[4margument\033[0m \033[1m+{\033[0m \033[4moptions\033[0m \033[1m}\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "For certain commands certain options and command line variables can be grouped" << ::std::endl + << "to only apply to specific arguments. This help topic describes the argument" << ::std::endl + << "grouping facility used for this purpose." << ::std::endl + << ::std::endl + << "Groups can be specified before (leading) and/or after (trailing) the argument" << ::std::endl + << "they apply to. A leading group starts with '\033[1m{\033[0m' and ends with '\033[1m}+\033[0m' while a" << ::std::endl + << "trailing group starts with '\033[1m+{\033[0m' and ends with '\033[1m}\033[0m'. For example:" << ::std::endl + << ::std::endl + << "{ --foo --bar }+ arg # 'arg' with '--foo' '--bar'" << ::std::endl + << "arg +{ fox=1 baz=2 } # 'arg' with 'fox=1' 'baz=2'" << ::std::endl + << ::std::endl + << "Multiple leading and/or trailing groups can be specified for the same argument." << ::std::endl + << "For example:" << ::std::endl + << ::std::endl + << "{ -f }+ { -b }+ arg +{ f=1 } +{ b=2 } # 'arg' with '-f' 'b' 'f=1' 'b=2'" << ::std::endl + << ::std::endl + << "The group applies to a single argument only unless multiple arguments are" << ::std::endl + << "themselves grouped with '\033[1m{\033[0m' and '\033[1m}\033[0m'. For example:" << ::std::endl + << ::std::endl + << "{ --foo }+ arg1 arg2 +{ --bar } # 'arg1' with '--foo'" << ::std::endl + << " # 'arg2' with '--bar'" << ::std::endl + << ::std::endl + << "{ --foo }+ { arg1 arg2 } +{ --bar } # 'arg1' with '--foo' '--bar'" << ::std::endl + << " # 'arg2' with '--foo' '--bar'" << ::std::endl + << ::std::endl + << "The group separators ('\033[1m{\033[0m', '\033[1m}+'\033[0m, etc) must be separate command line arguments." << ::std::endl + << "In particular, they must not be adjacent either to the arguments inside the" << ::std::endl + << "group nor to the argument they apply to. All such cases will be treated as" << ::std::endl + << "ordinary arguments. For example:" << ::std::endl + << ::std::endl + << "{--foo}+ arg # '{--foo}+' ..." << ::std::endl + << "arg+{ --foo } # 'arg+{' ..." << ::std::endl + << ::std::endl + << "If one of the group separators needs to be specified as an argument verbatim," << ::std::endl + << "then it must be escaped with '\033[1m\\\033[0m'. For example:" << ::std::endl + << ::std::endl + << "} # error: unexpected group separator" << ::std::endl + << "}x # '}x'" << ::std::endl + << "\\} # '}'" << ::std::endl + << "{ \\}+ }+ arg # 'arg' with '}+'" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/argument-grouping.hxx b/bpkg/argument-grouping.hxx new file mode 100644 index 0000000..64019de --- /dev/null +++ b/bpkg/argument-grouping.hxx @@ -0,0 +1,31 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_ARGUMENT_GROUPING_HXX +#define BPKG_ARGUMENT_GROUPING_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_argument_grouping_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_ARGUMENT_GROUPING_HXX diff --git a/bpkg/bpkg-options.cxx b/bpkg/bpkg-options.cxx new file mode 100644 index 0000000..0ebf02f --- /dev/null +++ b/bpkg/bpkg-options.cxx @@ -0,0 +1,1560 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/bpkg-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // commands + // + + commands:: + commands () + : help_ (), + cfg_create_ (), + cfg_info_ (), + cfg_link_ (), + cfg_unlink_ (), + rep_info_ (), + rep_add_ (), + rep_remove_ (), + rep_list_ (), + rep_fetch_ (), + rep_create_ (), + pkg_status_ (), + pkg_build_ (), + pkg_drop_ (), + pkg_install_ (), + pkg_uninstall_ (), + pkg_update_ (), + pkg_test_ (), + pkg_clean_ (), + pkg_verify_ (), + pkg_fetch_ (), + pkg_unpack_ (), + pkg_checkout_ (), + pkg_configure_ (), + pkg_disfigure_ (), + pkg_purge_ () + { + } + + bool commands:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool commands:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool commands:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool commands:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool commands:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void commands:: + merge (const commands& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.help_) + { + ::bpkg::cli::parser< bool>::merge ( + this->help_, a.help_); + } + + if (a.cfg_create_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cfg_create_, a.cfg_create_); + } + + if (a.cfg_info_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cfg_info_, a.cfg_info_); + } + + if (a.cfg_link_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cfg_link_, a.cfg_link_); + } + + if (a.cfg_unlink_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cfg_unlink_, a.cfg_unlink_); + } + + if (a.rep_info_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_info_, a.rep_info_); + } + + if (a.rep_add_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_add_, a.rep_add_); + } + + if (a.rep_remove_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_remove_, a.rep_remove_); + } + + if (a.rep_list_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_list_, a.rep_list_); + } + + if (a.rep_fetch_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_fetch_, a.rep_fetch_); + } + + if (a.rep_create_) + { + ::bpkg::cli::parser< bool>::merge ( + this->rep_create_, a.rep_create_); + } + + if (a.pkg_status_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_status_, a.pkg_status_); + } + + if (a.pkg_build_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_build_, a.pkg_build_); + } + + if (a.pkg_drop_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_drop_, a.pkg_drop_); + } + + if (a.pkg_install_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_install_, a.pkg_install_); + } + + if (a.pkg_uninstall_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_uninstall_, a.pkg_uninstall_); + } + + if (a.pkg_update_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_update_, a.pkg_update_); + } + + if (a.pkg_test_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_test_, a.pkg_test_); + } + + if (a.pkg_clean_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_clean_, a.pkg_clean_); + } + + if (a.pkg_verify_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_verify_, a.pkg_verify_); + } + + if (a.pkg_fetch_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_fetch_, a.pkg_fetch_); + } + + if (a.pkg_unpack_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_unpack_, a.pkg_unpack_); + } + + if (a.pkg_checkout_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_checkout_, a.pkg_checkout_); + } + + if (a.pkg_configure_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_configure_, a.pkg_configure_); + } + + if (a.pkg_disfigure_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_disfigure_, a.pkg_disfigure_); + } + + if (a.pkg_purge_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_purge_, a.pkg_purge_); + } + } + + ::bpkg::cli::usage_para commands:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMANDS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1mhelp\033[0m [\033[4mtopic\033[0m] \033[1mbpkg-help(1)\033[0m -- show help for a command or help topic" << ::std::endl; + + os << "\033[1mcfg-create\033[0m|\033[1mcreate\033[0m \033[1mbpkg-cfg-create(1)\033[0m -- create configuration" << ::std::endl; + + os << "\033[1mcfg-info\033[0m \033[1mbpkg-cfg-info(1)\033[0m -- print configuration information" << ::std::endl; + + os << "\033[1mcfg-link\033[0m|\033[1mlink\033[0m \033[1mbpkg-cfg-link(1)\033[0m -- link configuration" << ::std::endl; + + os << "\033[1mcfg-unlink\033[0m|\033[1munlink\033[0m \033[1mbpkg-cfg-unlink(1)\033[0m -- unlink configuration" << ::std::endl; + + os << "\033[1mrep-info\033[0m \033[1mbpkg-rep-info(1)\033[0m -- print repository information" << ::std::endl; + + os << "\033[1mrep-add\033[0m|\033[1madd\033[0m \033[1mbpkg-rep-add(1)\033[0m -- add repository to configuration" << ::std::endl; + + os << "\033[1mrep-remove\033[0m|\033[1mremove\033[0m \033[1mbpkg-rep-remove(1)\033[0m -- remove repository from" << ::std::endl + << " configuration" << ::std::endl; + + os << "\033[1mrep-list\033[0m|\033[1mlist\033[0m \033[1mbpkg-rep-list(1)\033[0m -- list repositories in configuration" << ::std::endl; + + os << "\033[1mrep-fetch\033[0m|\033[1mfetch\033[0m \033[1mbpkg-rep-fetch(1)\033[0m -- fetch list of available packages" << ::std::endl; + + os << "\033[1mrep-create\033[0m \033[1mbpkg-rep-create(1)\033[0m -- create repository" << ::std::endl; + + os << "\033[1mpkg-status\033[0m|\033[1mstatus\033[0m \033[1mbpkg-pkg-status(1)\033[0m -- print package status" << ::std::endl; + + os << "\033[1mpkg-build\033[0m|\033[1mbuild\033[0m \033[1mbpkg-pkg-build(1)\033[0m -- build package" << ::std::endl; + + os << "\033[1mpkg-drop\033[0m|\033[1mdrop\033[0m \033[1mbpkg-pkg-drop(1)\033[0m -- drop package" << ::std::endl; + + os << "\033[1mpkg-install\033[0m|\033[1minstall\033[0m \033[1mbpkg-pkg-install(1)\033[0m -- install package" << ::std::endl; + + os << "\033[1mpkg-uninstall\033[0m|\033[1muninstall\033[0m \033[1mbpkg-pkg-uninstall(1)\033[0m -- uninstall package" << ::std::endl; + + os << "\033[1mpkg-update\033[0m|\033[1mupdate\033[0m \033[1mbpkg-pkg-update(1)\033[0m -- update package" << ::std::endl; + + os << "\033[1mpkg-test\033[0m|\033[1mtest\033[0m \033[1mbpkg-pkg-test(1)\033[0m -- test package" << ::std::endl; + + os << "\033[1mpkg-clean\033[0m|\033[1mclean\033[0m \033[1mbpkg-pkg-clean(1)\033[0m -- clean package" << ::std::endl; + + os << "\033[1mpkg-verify\033[0m \033[1mbpkg-pkg-verify(1)\033[0m -- verify package archive" << ::std::endl; + + os << "\033[1mpkg-fetch\033[0m \033[1mbpkg-pkg-fetch(1)\033[0m -- fetch package archive" << ::std::endl; + + os << "\033[1mpkg-unpack\033[0m \033[1mbpkg-pkg-unpack(1)\033[0m -- unpack package archive" << ::std::endl; + + os << "\033[1mpkg-checkout\033[0m \033[1mbpkg-pkg-checkout(1)\033[0m -- check out package version" << ::std::endl; + + os << "\033[1mpkg-configure\033[0m \033[1mbpkg-pkg-configure(1)\033[0m -- configure package" << ::std::endl; + + os << "\033[1mpkg-disfigure\033[0m \033[1mbpkg-pkg-disfigure(1)\033[0m -- disfigure package" << ::std::endl; + + os << "\033[1mpkg-purge\033[0m \033[1mbpkg-pkg-purge(1)\033[0m -- purge package" << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (commands&, ::bpkg::cli::scanner&)> + _cli_commands_map; + + static _cli_commands_map _cli_commands_map_; + + struct _cli_commands_map_init + { + _cli_commands_map_init () + { + _cli_commands_map_["help"] = + &::bpkg::cli::thunk< commands, bool, &commands::help_ >; + _cli_commands_map_["cfg-create"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_create_ >; + _cli_commands_map_["create"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_create_ >; + _cli_commands_map_["cfg-info"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_info_ >; + _cli_commands_map_["cfg-link"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_link_ >; + _cli_commands_map_["link"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_link_ >; + _cli_commands_map_["cfg-unlink"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_unlink_ >; + _cli_commands_map_["unlink"] = + &::bpkg::cli::thunk< commands, bool, &commands::cfg_unlink_ >; + _cli_commands_map_["rep-info"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_info_ >; + _cli_commands_map_["rep-add"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_add_ >; + _cli_commands_map_["add"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_add_ >; + _cli_commands_map_["rep-remove"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_remove_ >; + _cli_commands_map_["remove"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_remove_ >; + _cli_commands_map_["rep-list"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_list_ >; + _cli_commands_map_["list"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_list_ >; + _cli_commands_map_["rep-fetch"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_fetch_ >; + _cli_commands_map_["fetch"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_fetch_ >; + _cli_commands_map_["rep-create"] = + &::bpkg::cli::thunk< commands, bool, &commands::rep_create_ >; + _cli_commands_map_["pkg-status"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_status_ >; + _cli_commands_map_["status"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_status_ >; + _cli_commands_map_["pkg-build"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_build_ >; + _cli_commands_map_["build"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_build_ >; + _cli_commands_map_["pkg-drop"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_drop_ >; + _cli_commands_map_["drop"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_drop_ >; + _cli_commands_map_["pkg-install"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_install_ >; + _cli_commands_map_["install"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_install_ >; + _cli_commands_map_["pkg-uninstall"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_uninstall_ >; + _cli_commands_map_["uninstall"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_uninstall_ >; + _cli_commands_map_["pkg-update"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_update_ >; + _cli_commands_map_["update"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_update_ >; + _cli_commands_map_["pkg-test"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_test_ >; + _cli_commands_map_["test"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_test_ >; + _cli_commands_map_["pkg-clean"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_clean_ >; + _cli_commands_map_["clean"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_clean_ >; + _cli_commands_map_["pkg-verify"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_verify_ >; + _cli_commands_map_["pkg-fetch"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_fetch_ >; + _cli_commands_map_["pkg-unpack"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_unpack_ >; + _cli_commands_map_["pkg-checkout"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_checkout_ >; + _cli_commands_map_["pkg-configure"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_configure_ >; + _cli_commands_map_["pkg-disfigure"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_disfigure_ >; + _cli_commands_map_["pkg-purge"] = + &::bpkg::cli::thunk< commands, bool, &commands::pkg_purge_ >; + } + }; + + static _cli_commands_map_init _cli_commands_map_init_; + + bool commands:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_commands_map::const_iterator i (_cli_commands_map_.find (o)); + + if (i != _cli_commands_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool commands:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // topics + // + + topics:: + topics () + : common_options_ (), + default_options_files_ (), + repository_types_ (), + repository_signing_ (), + argument_grouping_ () + { + } + + bool topics:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool topics:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool topics:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool topics:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool topics:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void topics:: + merge (const topics& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.common_options_) + { + ::bpkg::cli::parser< bool>::merge ( + this->common_options_, a.common_options_); + } + + if (a.default_options_files_) + { + ::bpkg::cli::parser< bool>::merge ( + this->default_options_files_, a.default_options_files_); + } + + if (a.repository_types_) + { + ::bpkg::cli::parser< bool>::merge ( + this->repository_types_, a.repository_types_); + } + + if (a.repository_signing_) + { + ::bpkg::cli::parser< bool>::merge ( + this->repository_signing_, a.repository_signing_); + } + + if (a.argument_grouping_) + { + ::bpkg::cli::parser< bool>::merge ( + this->argument_grouping_, a.argument_grouping_); + } + } + + ::bpkg::cli::usage_para topics:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mHELP TOPICS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1mcommon-options\033[0m \033[1mbpkg-common-options(1)\033[0m -- details on common options" << ::std::endl; + + os << "\033[1mdefault-options-files\033[0m \033[1mbpkg-default-options-files(1)\033[0m -- specifying default" << ::std::endl + << " options" << ::std::endl; + + os << "\033[1mrepository-types\033[0m \033[1mbpkg-repository-types(1)\033[0m -- repository types," << ::std::endl + << " structure, and URLs" << ::std::endl; + + os << "\033[1mrepository-signing\033[0m \033[1mbpkg-repository-signing(1)\033[0m -- how to sign repository" << ::std::endl; + + os << "\033[1margument-grouping\033[0m \033[1mbpkg-argument-grouping(1)\033[0m -- argument grouping" << ::std::endl + << " facility" << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (topics&, ::bpkg::cli::scanner&)> + _cli_topics_map; + + static _cli_topics_map _cli_topics_map_; + + struct _cli_topics_map_init + { + _cli_topics_map_init () + { + _cli_topics_map_["common-options"] = + &::bpkg::cli::thunk< topics, bool, &topics::common_options_ >; + _cli_topics_map_["default-options-files"] = + &::bpkg::cli::thunk< topics, bool, &topics::default_options_files_ >; + _cli_topics_map_["repository-types"] = + &::bpkg::cli::thunk< topics, bool, &topics::repository_types_ >; + _cli_topics_map_["repository-signing"] = + &::bpkg::cli::thunk< topics, bool, &topics::repository_signing_ >; + _cli_topics_map_["argument-grouping"] = + &::bpkg::cli::thunk< topics, bool, &topics::argument_grouping_ >; + } + }; + + static _cli_topics_map_init _cli_topics_map_init_; + + bool topics:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_topics_map::const_iterator i (_cli_topics_map_.find (o)); + + if (i != _cli_topics_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool topics:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } + + // options + // + + options:: + options () + : help_ (), + version_ () + { + } + + bool options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void options:: + merge (const options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.help_) + { + ::bpkg::cli::parser< bool>::merge ( + this->help_, a.help_); + } + + if (a.version_) + { + ::bpkg::cli::parser< bool>::merge ( + this->version_, a.version_); + } + } + + ::bpkg::cli::usage_para options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + // common_options base + // + p = ::bpkg::common_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (options&, ::bpkg::cli::scanner&)> + _cli_options_map; + + static _cli_options_map _cli_options_map_; + + struct _cli_options_map_init + { + _cli_options_map_init () + { + _cli_options_map_["--help"] = + &::bpkg::cli::thunk< options, bool, &options::help_ >; + _cli_options_map_["--version"] = + &::bpkg::cli::thunk< options, bool, &options::version_ >; + } + }; + + static _cli_options_map_init _cli_options_map_init_; + + bool options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_options_map::const_iterator i (_cli_options_map_.find (o)); + + if (i != _cli_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg --help\033[0m" << ::std::endl + << "\033[1mbpkg --version\033[0m" << ::std::endl + << "\033[1mbpkg help\033[0m [\033[4mcommand\033[0m | \033[4mtopic\033[0m]" << ::std::endl + << "\033[1mbpkg\033[0m [\033[4mcommon-options\033[0m] \033[4mcommand\033[0m [\033[4mcommand-options\033[0m] \033[4mcommand-args\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mbuild2\033[0m package dependency manager is used to manipulate build" << ::std::endl + << "configurations, packages, and repositories using a set of commands that are" << ::std::endl + << "summarized below." << ::std::endl + << ::std::endl + << "For a detailed description of any command or help topic, use the \033[1mhelp\033[0m command" << ::std::endl + << "or see the corresponding man page (the man pages have the \033[1mbpkg-\033[0m prefix, for" << ::std::endl + << "example \033[1mbpkg-help(1)\033[0m). Note also that \033[4mcommand-options\033[0m and \033[4mcommand-args\033[0m can be" << ::std::endl + << "specified in any order and \033[4mcommon-options\033[0m can be specified as part of" << ::std::endl + << "\033[4mcommand-options\033[0m." << ::std::endl; + + p = ::bpkg::commands::print_usage (os, ::bpkg::cli::usage_para::text); + + p = ::bpkg::topics::print_usage (os, p); + + p = ::bpkg::options::print_usage (os, p); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mENVIRONMENT\033[0m" << ::std::endl + << ::std::endl + << "Commands executed by \033[1mbpkg\033[0m while the current and linked build configuration" << ::std::endl + << "databases are open will have the \033[1mBPKG_OPEN_CONFIGS\033[0m environment variable set to" << ::std::endl + << "the space-separated, \033[1m\"\033[0m-quoted list of absolute and normalized configuration" << ::std::endl + << "directory paths. This can be used by build system hooks and/or programs that" << ::std::endl + << "they execute." << ::std::endl; + + os << std::endl + << "\033[1mEXIT STATUS\033[0m" << ::std::endl + << ::std::endl + << "\033[1m0\033[0m" << ::std::endl + << " Success." << ::std::endl + << "\033[1m1\033[0m" << ::std::endl + << " Fatal error." << ::std::endl + << "\033[1m2\033[0m" << ::std::endl + << " Recoverable error which is likely to disappear if the command is" << ::std::endl + << " re-executed." << ::std::endl + << ::std::endl + << "\033[1mENVIRONMENT\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mBPKG_DEF_OPT\033[0m environment variable is used to suppress loading of default" << ::std::endl + << "options files in nested \033[1mbpkg\033[0m invocations. Its values are \033[1mfalse\033[0m or \033[1m0\033[0m to suppress" << ::std::endl + << "and \033[1mtrue\033[0m or \033[1m1\033[0m to load." << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/bpkg-options.hxx b/bpkg/bpkg-options.hxx new file mode 100644 index 0000000..08a875b --- /dev/null +++ b/bpkg/bpkg-options.hxx @@ -0,0 +1,387 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_BPKG_OPTIONS_HXX +#define BPKG_BPKG_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class commands + { + public: + commands (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const commands&); + + // Option accessors. + // + const bool& + help () const; + + const bool& + cfg_create () const; + + const bool& + cfg_info () const; + + const bool& + cfg_link () const; + + const bool& + cfg_unlink () const; + + const bool& + rep_info () const; + + const bool& + rep_add () const; + + const bool& + rep_remove () const; + + const bool& + rep_list () const; + + const bool& + rep_fetch () const; + + const bool& + rep_create () const; + + const bool& + pkg_status () const; + + const bool& + pkg_build () const; + + const bool& + pkg_drop () const; + + const bool& + pkg_install () const; + + const bool& + pkg_uninstall () const; + + const bool& + pkg_update () const; + + const bool& + pkg_test () const; + + const bool& + pkg_clean () const; + + const bool& + pkg_verify () const; + + const bool& + pkg_fetch () const; + + const bool& + pkg_unpack () const; + + const bool& + pkg_checkout () const; + + const bool& + pkg_configure () const; + + const bool& + pkg_disfigure () const; + + const bool& + pkg_purge () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + bool help_; + bool cfg_create_; + bool cfg_info_; + bool cfg_link_; + bool cfg_unlink_; + bool rep_info_; + bool rep_add_; + bool rep_remove_; + bool rep_list_; + bool rep_fetch_; + bool rep_create_; + bool pkg_status_; + bool pkg_build_; + bool pkg_drop_; + bool pkg_install_; + bool pkg_uninstall_; + bool pkg_update_; + bool pkg_test_; + bool pkg_clean_; + bool pkg_verify_; + bool pkg_fetch_; + bool pkg_unpack_; + bool pkg_checkout_; + bool pkg_configure_; + bool pkg_disfigure_; + bool pkg_purge_; + }; + + class topics + { + public: + topics (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const topics&); + + // Option accessors. + // + const bool& + common_options () const; + + const bool& + default_options_files () const; + + const bool& + repository_types () const; + + const bool& + repository_signing () const; + + const bool& + argument_grouping () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + bool common_options_; + bool default_options_files_; + bool repository_types_; + bool repository_signing_; + bool argument_grouping_; + }; + + class options: public ::bpkg::common_options + { + public: + options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const options&); + + // Option accessors. + // + const bool& + help () const; + + const bool& + version () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + bool help_; + bool version_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/bpkg-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_BPKG_OPTIONS_HXX diff --git a/bpkg/bpkg-options.ixx b/bpkg/bpkg-options.ixx new file mode 100644 index 0000000..6a2ef7e --- /dev/null +++ b/bpkg/bpkg-options.ixx @@ -0,0 +1,225 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // commands + // + + inline const bool& commands:: + help () const + { + return this->help_; + } + + inline const bool& commands:: + cfg_create () const + { + return this->cfg_create_; + } + + inline const bool& commands:: + cfg_info () const + { + return this->cfg_info_; + } + + inline const bool& commands:: + cfg_link () const + { + return this->cfg_link_; + } + + inline const bool& commands:: + cfg_unlink () const + { + return this->cfg_unlink_; + } + + inline const bool& commands:: + rep_info () const + { + return this->rep_info_; + } + + inline const bool& commands:: + rep_add () const + { + return this->rep_add_; + } + + inline const bool& commands:: + rep_remove () const + { + return this->rep_remove_; + } + + inline const bool& commands:: + rep_list () const + { + return this->rep_list_; + } + + inline const bool& commands:: + rep_fetch () const + { + return this->rep_fetch_; + } + + inline const bool& commands:: + rep_create () const + { + return this->rep_create_; + } + + inline const bool& commands:: + pkg_status () const + { + return this->pkg_status_; + } + + inline const bool& commands:: + pkg_build () const + { + return this->pkg_build_; + } + + inline const bool& commands:: + pkg_drop () const + { + return this->pkg_drop_; + } + + inline const bool& commands:: + pkg_install () const + { + return this->pkg_install_; + } + + inline const bool& commands:: + pkg_uninstall () const + { + return this->pkg_uninstall_; + } + + inline const bool& commands:: + pkg_update () const + { + return this->pkg_update_; + } + + inline const bool& commands:: + pkg_test () const + { + return this->pkg_test_; + } + + inline const bool& commands:: + pkg_clean () const + { + return this->pkg_clean_; + } + + inline const bool& commands:: + pkg_verify () const + { + return this->pkg_verify_; + } + + inline const bool& commands:: + pkg_fetch () const + { + return this->pkg_fetch_; + } + + inline const bool& commands:: + pkg_unpack () const + { + return this->pkg_unpack_; + } + + inline const bool& commands:: + pkg_checkout () const + { + return this->pkg_checkout_; + } + + inline const bool& commands:: + pkg_configure () const + { + return this->pkg_configure_; + } + + inline const bool& commands:: + pkg_disfigure () const + { + return this->pkg_disfigure_; + } + + inline const bool& commands:: + pkg_purge () const + { + return this->pkg_purge_; + } + + // topics + // + + inline const bool& topics:: + common_options () const + { + return this->common_options_; + } + + inline const bool& topics:: + default_options_files () const + { + return this->default_options_files_; + } + + inline const bool& topics:: + repository_types () const + { + return this->repository_types_; + } + + inline const bool& topics:: + repository_signing () const + { + return this->repository_signing_; + } + + inline const bool& topics:: + argument_grouping () const + { + return this->argument_grouping_; + } + + // options + // + + inline const bool& options:: + help () const + { + return this->help_; + } + + inline const bool& options:: + version () const + { + return this->version_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/cfg-create-options.cxx b/bpkg/cfg-create-options.cxx new file mode 100644 index 0000000..238bdfd --- /dev/null +++ b/bpkg/cfg-create-options.cxx @@ -0,0 +1,794 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/cfg-create-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // cfg_create_options + // + + cfg_create_options:: + cfg_create_options () + : directory_ ("."), + directory_specified_ (false), + existing_ (), + wipe_ (), + host_config_ (), + host_config_specified_ (false), + no_host_config_ (), + build2_config_ (), + build2_config_specified_ (false), + no_build2_config_ (), + name_ (), + name_specified_ (false), + type_ ("target"), + type_specified_ (false), + uuid_ (), + uuid_specified_ (false) + { + } + + bool cfg_create_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_create_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_create_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_create_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_create_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cfg_create_options:: + merge (const cfg_create_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.directory_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->directory_, a.directory_); + this->directory_specified_ = true; + } + + if (a.existing_) + { + ::bpkg::cli::parser< bool>::merge ( + this->existing_, a.existing_); + } + + if (a.wipe_) + { + ::bpkg::cli::parser< bool>::merge ( + this->wipe_, a.wipe_); + } + + if (a.host_config_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->host_config_, a.host_config_); + this->host_config_specified_ = true; + } + + if (a.no_host_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_host_config_, a.no_host_config_); + } + + if (a.build2_config_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->build2_config_, a.build2_config_); + this->build2_config_specified_ = true; + } + + if (a.no_build2_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_build2_config_, a.no_build2_config_); + } + + if (a.name_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->name_, a.name_); + this->name_specified_ = true; + } + + if (a.type_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->type_, a.type_); + this->type_specified_ = true; + } + + if (a.uuid_specified_) + { + ::bpkg::cli::parser< uuid_type>::merge ( + this->uuid_, a.uuid_); + this->uuid_specified_ = true; + } + } + + ::bpkg::cli::usage_para cfg_create_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCFG-CREATE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mdir\033[0m Create the configuration in \033[4mdir\033[0m rather than in the" << ::std::endl + << " current working directory." << ::std::endl; + + os << std::endl + << "\033[1m--existing\033[0m|\033[1m-e\033[0m Initialize a \033[1mbpkg\033[0m configuration based on an existing" << ::std::endl + << " build system configuration." << ::std::endl; + + os << std::endl + << "\033[1m--wipe\033[0m Wipe the configuration directory clean before creating" << ::std::endl + << " the new configuration. For safety, this option" << ::std::endl + << " requires that you specify the configuration directory" << ::std::endl + << " explicitly with \033[1m--directory|-d\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--host-config\033[0m \033[4mdir\033[0m Link the specified host configuration with the" << ::std::endl + << " configuration being created as if by running the" << ::std::endl + << " \033[1mbpkg-cfg-link(1)\033[0m command." << ::std::endl; + + os << std::endl + << "\033[1m--no-host-config\033[0m Ignore any specified \033[1m--host-config\033[0m options." << ::std::endl; + + os << std::endl + << "\033[1m--build2-config\033[0m \033[4mdir\033[0m Link the specified build system module configuration" << ::std::endl + << " with the configuration being created as if by running" << ::std::endl + << " the \033[1mbpkg-cfg-link(1)\033[0m command." << ::std::endl; + + os << std::endl + << "\033[1m--no-build2-config\033[0m Ignore any specified \033[1m--build2-config\033[0m options." << ::std::endl; + + os << std::endl + << "\033[1m--name\033[0m \033[4mname\033[0m The name of the configuration being created. If this" << ::std::endl + << " configuration is linked with another configuration" << ::std::endl + << " using \033[1mbpkg-cfg-link(1)\033[0m, this name will be used as the" << ::std::endl + << " link name unless overridden. By default the" << ::std::endl + << " configuration is created unnamed." << ::std::endl; + + os << std::endl + << "\033[1m--type\033[0m \033[4mtype\033[0m The type of the configuration being created. By" << ::std::endl + << " default, configuration of type \033[1mtarget\033[0m is created." << ::std::endl; + + os << std::endl + << "\033[1m--uuid\033[0m \033[4muuid\033[0m Use the specified UUID as the configuration id instead" << ::std::endl + << " of generating one automatically." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // common_options base + // + p = ::bpkg::common_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (cfg_create_options&, ::bpkg::cli::scanner&)> + _cli_cfg_create_options_map; + + static _cli_cfg_create_options_map _cli_cfg_create_options_map_; + + struct _cli_cfg_create_options_map_init + { + _cli_cfg_create_options_map_init () + { + _cli_cfg_create_options_map_["--directory"] = + &::bpkg::cli::thunk< cfg_create_options, dir_path, &cfg_create_options::directory_, + &cfg_create_options::directory_specified_ >; + _cli_cfg_create_options_map_["-d"] = + &::bpkg::cli::thunk< cfg_create_options, dir_path, &cfg_create_options::directory_, + &cfg_create_options::directory_specified_ >; + _cli_cfg_create_options_map_["--existing"] = + &::bpkg::cli::thunk< cfg_create_options, bool, &cfg_create_options::existing_ >; + _cli_cfg_create_options_map_["-e"] = + &::bpkg::cli::thunk< cfg_create_options, bool, &cfg_create_options::existing_ >; + _cli_cfg_create_options_map_["--wipe"] = + &::bpkg::cli::thunk< cfg_create_options, bool, &cfg_create_options::wipe_ >; + _cli_cfg_create_options_map_["--host-config"] = + &::bpkg::cli::thunk< cfg_create_options, dir_path, &cfg_create_options::host_config_, + &cfg_create_options::host_config_specified_ >; + _cli_cfg_create_options_map_["--no-host-config"] = + &::bpkg::cli::thunk< cfg_create_options, bool, &cfg_create_options::no_host_config_ >; + _cli_cfg_create_options_map_["--build2-config"] = + &::bpkg::cli::thunk< cfg_create_options, dir_path, &cfg_create_options::build2_config_, + &cfg_create_options::build2_config_specified_ >; + _cli_cfg_create_options_map_["--no-build2-config"] = + &::bpkg::cli::thunk< cfg_create_options, bool, &cfg_create_options::no_build2_config_ >; + _cli_cfg_create_options_map_["--name"] = + &::bpkg::cli::thunk< cfg_create_options, string, &cfg_create_options::name_, + &cfg_create_options::name_specified_ >; + _cli_cfg_create_options_map_["--type"] = + &::bpkg::cli::thunk< cfg_create_options, string, &cfg_create_options::type_, + &cfg_create_options::type_specified_ >; + _cli_cfg_create_options_map_["--uuid"] = + &::bpkg::cli::thunk< cfg_create_options, uuid_type, &cfg_create_options::uuid_, + &cfg_create_options::uuid_specified_ >; + } + }; + + static _cli_cfg_create_options_map_init _cli_cfg_create_options_map_init_; + + bool cfg_create_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_cfg_create_options_map::const_iterator i (_cli_cfg_create_options_map_.find (o)); + + if (i != _cli_cfg_create_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool cfg_create_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_create_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg cfg-create\033[0m|\033[1mcreate\033[0m [\033[4moptions\033[0m] [\033[4mcfg-args\033[0m]" << ::std::endl + << "\033[1mbpkg cfg-create\033[0m|\033[1mcreate\033[0m [\033[4moptions\033[0m] \033[1m--existing|-e\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[4mcfg-args\033[0m = (\033[4mmodule\033[0m | \033[4mcfg-var\033[0m)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mcfg-create\033[0m command creates a new \033[1mbpkg\033[0m configuration with the specified" << ::std::endl + << "\033[1mbuild2\033[0m modules and configuration variables (the first form) or initializes one" << ::std::endl + << "based on an existing build system configuration (the second form). The \033[1mbpkg\033[0m" << ::std::endl + << "configuration itself is a build system configuration; see build system driver" << ::std::endl + << "(\033[1mb(1)\033[0m) \033[1mcreate\033[0m meta-operation for details." << ::std::endl + << ::std::endl + << "Unless the \033[1m--existing|-e\033[0m or \033[1m--wipe\033[0m option is specified, \033[1mcfg-create\033[0m expects the" << ::std::endl + << "configuration directory to be empty or to not exist (in which case it will be" << ::std::endl + << "created)." << ::std::endl + << ::std::endl + << "By default, the configuration created with the first form loads the \033[1mconfig\033[0m," << ::std::endl + << "\033[1mtest\033[0m, \033[1mdist\033[0m, and \033[1minstall\033[0m modules. However, additional modules and, if required," << ::std::endl + << "their configuration variables can be specified as the \033[1mcfg-create\033[0m arguments. For" << ::std::endl + << "example:" << ::std::endl + << ::std::endl + << "bpkg create cxx config.cxx=clang++ config.install.root=/usr/local" << ::std::endl + << ::std::endl + << "By default, \033[1mbpkg\033[0m appends \033[1m.config\033[0m to the names of the modules that you specify" << ::std::endl + << "so that only their configurations are loaded. You can override this behavior by" << ::std::endl + << "specifying the period (\033[1m.\033[0m) after the module name. You can also instruct \033[1mbpkg\033[0m to" << ::std::endl + << "use the optional module load by prefixing the module name with the question" << ::std::endl + << "mark (\033[1m?\033[0m). For example:" << ::std::endl + << ::std::endl + << "bpkg create cxx. \"?cli\"" << ::std::endl + << ::std::endl + << "Configurations can be linked with each other to allow a package to be built in" << ::std::endl + << "one configuration while its dependencies in one or more linked configurations." << ::std::endl + << "This can be used to create a \"base\" configuration with common dependencies that" << ::std::endl + << "are shared between multiple configurations. This mechanism is also used to" << ::std::endl + << "provide a host configuration that is used to build build-time dependencies." << ::std::endl + << ::std::endl + << "Each configuration is assigned an automatically-generated UUID unless one is" << ::std::endl + << "specified with the \033[1m--uuid\033[0m option. This UUID is used to check the integrity of" << ::std::endl + << "configuration links. For convenience of referring to linked configurations, a" << ::std::endl + << "configuration can also be assigned a name with the \033[1m--name\033[0m option." << ::std::endl + << ::std::endl + << "A configuration also has a type specified with the \033[1m--type\033[0m option. Three" << ::std::endl + << "predefined types are \033[1mtarget\033[0m, \033[1mhost\033[0m, and \033[1mbuild2\033[0m. If the type is not specified" << ::std::endl + << "explicitly, then \033[1mtarget\033[0m is assumed. When satisfying a dependency of one package" << ::std::endl + << "on another, a linked configuration will only be considered if (1) it has the" << ::std::endl + << "same type as the other configuration for run-time dependencies, (2) it has the" << ::std::endl + << "\033[1mhost\033[0m type for regular build-time dependencies, and (3) it has the \033[1mbuild2\033[0m type" << ::std::endl + << "for build system module build-time dependencies. Note that a host configuration" << ::std::endl + << "is a target configuration for the host machine. So to create a self-hosted" << ::std::endl + << "configuration, use type \033[1mhost\033[0m." << ::std::endl + << ::std::endl + << "To link a configuration we use the \033[1mbpkg-cfg-link(1)\033[0m command. As a shortcut," << ::std::endl + << "host and build system module configurations can also be linked during the" << ::std::endl + << "configuration creation with the \033[1m--host-config\033[0m and \033[1m--build2-config\033[0m options," << ::std::endl + << "respectively. If a build-time dependency is encountered in a configuration that" << ::std::endl + << "has no linked configuration of a suitable type (\033[1mhost\033[0m or \033[1mbuild2\033[0m, nor is itself" << ::std::endl + << "of a suitable type), then a private host or build system module configuration" << ::std::endl + << "named \033[1mhost\033[0m or \033[1mbuild2\033[0m, respectively, is created automatically inside the" << ::std::endl + << "configuration's .bpkg/\033[0m subdirectory." << ::std::endl; + + p = ::bpkg::cfg_create_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mcfg-create\033[0m command the search start directory is the parent directory" << ::std::endl + << "of the new configuration. The following options files are searched for in each" << ::std::endl + << "directory and, if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-cfg-create.options" << ::std::endl + << ::std::endl + << "The following \033[1mcfg-create\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl + << "--wipe" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/cfg-create-options.hxx b/bpkg/cfg-create-options.hxx new file mode 100644 index 0000000..f47594d --- /dev/null +++ b/bpkg/cfg-create-options.hxx @@ -0,0 +1,173 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_CFG_CREATE_OPTIONS_HXX +#define BPKG_CFG_CREATE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class cfg_create_options: public ::bpkg::common_options + { + public: + cfg_create_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cfg_create_options&); + + // Option accessors. + // + const dir_path& + directory () const; + + bool + directory_specified () const; + + const bool& + existing () const; + + const bool& + wipe () const; + + const dir_path& + host_config () const; + + bool + host_config_specified () const; + + const bool& + no_host_config () const; + + const dir_path& + build2_config () const; + + bool + build2_config_specified () const; + + const bool& + no_build2_config () const; + + const string& + name () const; + + bool + name_specified () const; + + const string& + type () const; + + bool + type_specified () const; + + const uuid_type& + uuid () const; + + bool + uuid_specified () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + dir_path directory_; + bool directory_specified_; + bool existing_; + bool wipe_; + dir_path host_config_; + bool host_config_specified_; + bool no_host_config_; + dir_path build2_config_; + bool build2_config_specified_; + bool no_build2_config_; + string name_; + bool name_specified_; + string type_; + bool type_specified_; + uuid_type uuid_; + bool uuid_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_create_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/cfg-create-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_CFG_CREATE_OPTIONS_HXX diff --git a/bpkg/cfg-create-options.ixx b/bpkg/cfg-create-options.ixx new file mode 100644 index 0000000..9e8b1f6 --- /dev/null +++ b/bpkg/cfg-create-options.ixx @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // cfg_create_options + // + + inline const dir_path& cfg_create_options:: + directory () const + { + return this->directory_; + } + + inline bool cfg_create_options:: + directory_specified () const + { + return this->directory_specified_; + } + + inline const bool& cfg_create_options:: + existing () const + { + return this->existing_; + } + + inline const bool& cfg_create_options:: + wipe () const + { + return this->wipe_; + } + + inline const dir_path& cfg_create_options:: + host_config () const + { + return this->host_config_; + } + + inline bool cfg_create_options:: + host_config_specified () const + { + return this->host_config_specified_; + } + + inline const bool& cfg_create_options:: + no_host_config () const + { + return this->no_host_config_; + } + + inline const dir_path& cfg_create_options:: + build2_config () const + { + return this->build2_config_; + } + + inline bool cfg_create_options:: + build2_config_specified () const + { + return this->build2_config_specified_; + } + + inline const bool& cfg_create_options:: + no_build2_config () const + { + return this->no_build2_config_; + } + + inline const string& cfg_create_options:: + name () const + { + return this->name_; + } + + inline bool cfg_create_options:: + name_specified () const + { + return this->name_specified_; + } + + inline const string& cfg_create_options:: + type () const + { + return this->type_; + } + + inline bool cfg_create_options:: + type_specified () const + { + return this->type_specified_; + } + + inline const uuid_type& cfg_create_options:: + uuid () const + { + return this->uuid_; + } + + inline bool cfg_create_options:: + uuid_specified () const + { + return this->uuid_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/cfg-info-options.cxx b/bpkg/cfg-info-options.cxx new file mode 100644 index 0000000..1a56f00 --- /dev/null +++ b/bpkg/cfg-info-options.cxx @@ -0,0 +1,656 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/cfg-info-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // cfg_info_options + // + + cfg_info_options:: + cfg_info_options () + : link_ (), + backlink_ (), + dangling_ (), + recursive_ () + { + } + + bool cfg_info_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_info_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_info_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_info_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_info_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cfg_info_options:: + merge (const cfg_info_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.link_) + { + ::bpkg::cli::parser< bool>::merge ( + this->link_, a.link_); + } + + if (a.backlink_) + { + ::bpkg::cli::parser< bool>::merge ( + this->backlink_, a.backlink_); + } + + if (a.dangling_) + { + ::bpkg::cli::parser< bool>::merge ( + this->dangling_, a.dangling_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + } + + ::bpkg::cli::usage_para cfg_info_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCFG-INFO OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--link\033[0m Print linked configurations." << ::std::endl; + + os << std::endl + << "\033[1m--backlink\033[0m Print implicitly backlinked configurations." << ::std::endl; + + os << std::endl + << "\033[1m--dangling\033[0m Print dangling implicit backlinks." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m Print linked configurations recursively." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // configuration_options base + // + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (cfg_info_options&, ::bpkg::cli::scanner&)> + _cli_cfg_info_options_map; + + static _cli_cfg_info_options_map _cli_cfg_info_options_map_; + + struct _cli_cfg_info_options_map_init + { + _cli_cfg_info_options_map_init () + { + _cli_cfg_info_options_map_["--link"] = + &::bpkg::cli::thunk< cfg_info_options, bool, &cfg_info_options::link_ >; + _cli_cfg_info_options_map_["--backlink"] = + &::bpkg::cli::thunk< cfg_info_options, bool, &cfg_info_options::backlink_ >; + _cli_cfg_info_options_map_["--dangling"] = + &::bpkg::cli::thunk< cfg_info_options, bool, &cfg_info_options::dangling_ >; + _cli_cfg_info_options_map_["--recursive"] = + &::bpkg::cli::thunk< cfg_info_options, bool, &cfg_info_options::recursive_ >; + } + }; + + static _cli_cfg_info_options_map_init _cli_cfg_info_options_map_init_; + + bool cfg_info_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_cfg_info_options_map::const_iterator i (_cli_cfg_info_options_map_.find (o)); + + if (i != _cli_cfg_info_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool cfg_info_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_info_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg cfg-info\033[0m [\033[4moptions\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mcfg-info\033[0m command prints the current configuration's absolute path, id," << ::std::endl + << "type, and name. If the \033[1m--link\033[0m and/or \033[1m--backlink\033[0m options are specified, then" << ::std::endl + << "this information is also printed for each linked and/or implicitly backlinked" << ::std::endl + << "configuration, if any. Note that the dangling implicit backlinks are silently" << ::std::endl + << "skipped, unless \033[1m--dangling\033[0m is specified, in which case this information is also" << ::std::endl + << "printed for them. Note that the information is written to \033[1mstdout\033[0m, not \033[1mstderr\033[0m." << ::std::endl + << ::std::endl + << "If the \033[1m--recursive\033[0m option is specified together with \033[1m--link\033[0m and/or \033[1m--backlink\033[0m," << ::std::endl + << "then this information is printed for linked and/or implicitly backlinked" << ::std::endl + << "configuration, recursively." << ::std::endl + << ::std::endl + << "The output format is regular with each value printed on a separate line and" << ::std::endl + << "prefixed with the value name. If the \033[1m--link\033[0m, \033[1m--backlink\033[0m, and/or \033[1m--dangling\033[0m" << ::std::endl + << "options are specified, then information blocks corresponding to linked" << ::std::endl + << "configurations are separated with blank lines. For example:" << ::std::endl + << ::std::endl + << "path: /path/to/cfg/" << ::std::endl + << "uuid: 8d439f03-7342-4502-8b1c-74b173869478" << ::std::endl + << "type: target" << ::std::endl + << "name: foo" << ::std::endl + << ::std::endl + << "path: /path/to/host-cfg/" << ::std::endl + << "uuid: 7ee4dab3-07d9-4163-81c0-3779166a7213" << ::std::endl + << "type: host" << ::std::endl + << "name: tools" << ::std::endl + << ::std::endl + << "path: /path/to/build2-cfg/" << ::std::endl + << "uuid: d453aa2a-92c4-4066-87e4-c8672eed06e1" << ::std::endl + << "type: build2" << ::std::endl + << "name: modules" << ::std::endl; + + p = ::bpkg::cfg_info_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mcfg-info\033[0m command the search start directory is the configuration" << ::std::endl + << "directory. The following options files are searched for in each directory and," << ::std::endl + << "if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-cfg-info.options" << ::std::endl + << ::std::endl + << "The following \033[1mcfg-info\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/cfg-info-options.hxx b/bpkg/cfg-info-options.hxx new file mode 100644 index 0000000..2024bf6 --- /dev/null +++ b/bpkg/cfg-info-options.hxx @@ -0,0 +1,125 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_CFG_INFO_OPTIONS_HXX +#define BPKG_CFG_INFO_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class cfg_info_options: public ::bpkg::configuration_options + { + public: + cfg_info_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cfg_info_options&); + + // Option accessors. + // + const bool& + link () const; + + const bool& + backlink () const; + + const bool& + dangling () const; + + const bool& + recursive () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + bool link_; + bool backlink_; + bool dangling_; + bool recursive_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_info_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/cfg-info-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_CFG_INFO_OPTIONS_HXX diff --git a/bpkg/cfg-info-options.ixx b/bpkg/cfg-info-options.ixx new file mode 100644 index 0000000..3eb43b3 --- /dev/null +++ b/bpkg/cfg-info-options.ixx @@ -0,0 +1,45 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // cfg_info_options + // + + inline const bool& cfg_info_options:: + link () const + { + return this->link_; + } + + inline const bool& cfg_info_options:: + backlink () const + { + return this->backlink_; + } + + inline const bool& cfg_info_options:: + dangling () const + { + return this->dangling_; + } + + inline const bool& cfg_info_options:: + recursive () const + { + return this->recursive_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/cfg-link-options.cxx b/bpkg/cfg-link-options.cxx new file mode 100644 index 0000000..77805f5 --- /dev/null +++ b/bpkg/cfg-link-options.cxx @@ -0,0 +1,626 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/cfg-link-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // cfg_link_options + // + + cfg_link_options:: + cfg_link_options () + : name_ (), + name_specified_ (false), + relative_ () + { + } + + bool cfg_link_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_link_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_link_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_link_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_link_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cfg_link_options:: + merge (const cfg_link_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.name_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->name_, a.name_); + this->name_specified_ = true; + } + + if (a.relative_) + { + ::bpkg::cli::parser< bool>::merge ( + this->relative_, a.relative_); + } + } + + ::bpkg::cli::usage_para cfg_link_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCFG-LINK OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--name\033[0m \033[4mname\033[0m Alternative link name. If this option is not" << ::std::endl + << " specified, then the configuration name is used as the" << ::std::endl + << " link name (see \033[1mbpkg-cfg-create(1)\033[0m for details)." << ::std::endl; + + os << std::endl + << "\033[1m--relative\033[0m Rebase the absolute linked configuration path relative" << ::std::endl + << " to the current configuration directory." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // configuration_options base + // + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (cfg_link_options&, ::bpkg::cli::scanner&)> + _cli_cfg_link_options_map; + + static _cli_cfg_link_options_map _cli_cfg_link_options_map_; + + struct _cli_cfg_link_options_map_init + { + _cli_cfg_link_options_map_init () + { + _cli_cfg_link_options_map_["--name"] = + &::bpkg::cli::thunk< cfg_link_options, string, &cfg_link_options::name_, + &cfg_link_options::name_specified_ >; + _cli_cfg_link_options_map_["--relative"] = + &::bpkg::cli::thunk< cfg_link_options, bool, &cfg_link_options::relative_ >; + } + }; + + static _cli_cfg_link_options_map_init _cli_cfg_link_options_map_init_; + + bool cfg_link_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_cfg_link_options_map::const_iterator i (_cli_cfg_link_options_map_.find (o)); + + if (i != _cli_cfg_link_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool cfg_link_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_link_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg cfg-link\033[0m [\033[4moptions\033[0m] \033[4mdir\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mcfg-link\033[0m command links the specified \033[1mbpkg\033[0m configuration with the current" << ::std::endl + << "configuration. Note that it also establishes an implicit backlink from the" << ::std::endl + << "specified to the current configuration. See \033[1mbpkg-cfg-create(1)\033[0m for background" << ::std::endl + << "on linked configurations. To unlink previously linked configurations use" << ::std::endl + << "\033[1mbpkg-cfg-unlink(1)\033[0m." << ::std::endl + << ::std::endl + << "The linked configurations are normally referred to using names when specified" << ::std::endl + << "on the \033[1mbpkg\033[0m command line. Unless overridden with the \033[1m--name\033[0m option, the" << ::std::endl + << "original configuration name is used to name the link. If the link is unnamed," << ::std::endl + << "then it can be referred to using the numeric id that is automatically assigned" << ::std::endl + << "when establishing the link or using the configuration UUID." << ::std::endl + << ::std::endl + << "If the specified configuration path is relative, then it is rebased relative to" << ::std::endl + << "the current configuration directory. This way, when the linked configurations" << ::std::endl + << "are moved around together, the stored relative paths remain valid. If the" << ::std::endl + << "specified directory path is absolute, then it is stored as absolute unless the" << ::std::endl + << "\033[1m--relative\033[0m option is specified in which case it is also rebased relative to the" << ::std::endl + << "current configuration directory." << ::std::endl; + + p = ::bpkg::cfg_link_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mcfg-link\033[0m command the search start directory is the configuration" << ::std::endl + << "directory. The following options files are searched for in each directory and," << ::std::endl + << "if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-cfg-link.options" << ::std::endl + << ::std::endl + << "The following \033[1mcfg-link\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/cfg-link-options.hxx b/bpkg/cfg-link-options.hxx new file mode 100644 index 0000000..9c506ce --- /dev/null +++ b/bpkg/cfg-link-options.hxx @@ -0,0 +1,121 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_CFG_LINK_OPTIONS_HXX +#define BPKG_CFG_LINK_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class cfg_link_options: public ::bpkg::configuration_options + { + public: + cfg_link_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cfg_link_options&); + + // Option accessors. + // + const string& + name () const; + + bool + name_specified () const; + + const bool& + relative () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + string name_; + bool name_specified_; + bool relative_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_link_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/cfg-link-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_CFG_LINK_OPTIONS_HXX diff --git a/bpkg/cfg-link-options.ixx b/bpkg/cfg-link-options.ixx new file mode 100644 index 0000000..685f89e --- /dev/null +++ b/bpkg/cfg-link-options.ixx @@ -0,0 +1,39 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // cfg_link_options + // + + inline const string& cfg_link_options:: + name () const + { + return this->name_; + } + + inline bool cfg_link_options:: + name_specified () const + { + return this->name_specified_; + } + + inline const bool& cfg_link_options:: + relative () const + { + return this->relative_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/cfg-unlink-options.cxx b/bpkg/cfg-unlink-options.cxx new file mode 100644 index 0000000..31c7f92 --- /dev/null +++ b/bpkg/cfg-unlink-options.cxx @@ -0,0 +1,643 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/cfg-unlink-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // cfg_unlink_options + // + + cfg_unlink_options:: + cfg_unlink_options () + : name_ (), + name_specified_ (false), + id_ (), + id_specified_ (false), + uuid_ (), + uuid_specified_ (false), + dangling_ () + { + } + + bool cfg_unlink_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_unlink_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool cfg_unlink_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_unlink_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool cfg_unlink_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void cfg_unlink_options:: + merge (const cfg_unlink_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.name_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->name_, a.name_); + this->name_specified_ = true; + } + + if (a.id_specified_) + { + ::bpkg::cli::parser< uint64_t>::merge ( + this->id_, a.id_); + this->id_specified_ = true; + } + + if (a.uuid_specified_) + { + ::bpkg::cli::parser< uuid_type>::merge ( + this->uuid_, a.uuid_); + this->uuid_specified_ = true; + } + + if (a.dangling_) + { + ::bpkg::cli::parser< bool>::merge ( + this->dangling_, a.dangling_); + } + } + + ::bpkg::cli::usage_para cfg_unlink_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCFG-UNLINK OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--name\033[0m \033[4mname\033[0m Name of the configuration to unlink." << ::std::endl; + + os << std::endl + << "\033[1m--id\033[0m \033[4mid\033[0m Numeric id of the configuration to unlink." << ::std::endl; + + os << std::endl + << "\033[1m--uuid\033[0m \033[4muuid\033[0m UUID of the configuration to unlink." << ::std::endl; + + os << std::endl + << "\033[1m--dangling\033[0m Remove dangling implicit backlinks." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // configuration_options base + // + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (cfg_unlink_options&, ::bpkg::cli::scanner&)> + _cli_cfg_unlink_options_map; + + static _cli_cfg_unlink_options_map _cli_cfg_unlink_options_map_; + + struct _cli_cfg_unlink_options_map_init + { + _cli_cfg_unlink_options_map_init () + { + _cli_cfg_unlink_options_map_["--name"] = + &::bpkg::cli::thunk< cfg_unlink_options, string, &cfg_unlink_options::name_, + &cfg_unlink_options::name_specified_ >; + _cli_cfg_unlink_options_map_["--id"] = + &::bpkg::cli::thunk< cfg_unlink_options, uint64_t, &cfg_unlink_options::id_, + &cfg_unlink_options::id_specified_ >; + _cli_cfg_unlink_options_map_["--uuid"] = + &::bpkg::cli::thunk< cfg_unlink_options, uuid_type, &cfg_unlink_options::uuid_, + &cfg_unlink_options::uuid_specified_ >; + _cli_cfg_unlink_options_map_["--dangling"] = + &::bpkg::cli::thunk< cfg_unlink_options, bool, &cfg_unlink_options::dangling_ >; + } + }; + + static _cli_cfg_unlink_options_map_init _cli_cfg_unlink_options_map_init_; + + bool cfg_unlink_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_cfg_unlink_options_map::const_iterator i (_cli_cfg_unlink_options_map_.find (o)); + + if (i != _cli_cfg_unlink_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool cfg_unlink_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_unlink_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg cfg-unlink\033[0m [\033[4moptions\033[0m] [\033[4mdir\033[0m]" << ::std::endl + << "\033[1mbpkg cfg-unlink\033[0m [\033[4moptions\033[0m] \033[1m--dangling\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mcfg-unlink\033[0m command unlinks the specified \033[1mbpkg\033[0m configuration from the" << ::std::endl + << "current configuration (the first form) or removes dangling implicit backlinks" << ::std::endl + << "(the second form). See \033[1mbpkg-cfg-create(1)\033[0m for background on linked" << ::std::endl + << "configurations." << ::std::endl + << ::std::endl + << "In the first form the configuration to unlink can be specified either as" << ::std::endl + << "configuration directory (\033[4mdir\033[0m), name (\033[1m--name\033[0m), id (\033[1m--id\033[0m), or UUID (\033[1m--uuid\033[0m)." << ::std::endl; + + p = ::bpkg::cfg_unlink_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mcfg-unlink\033[0m command the search start directory is the configuration" << ::std::endl + << "directory. The following options files are searched for in each directory and," << ::std::endl + << "if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-cfg-unlink.options" << ::std::endl + << ::std::endl + << "The following \033[1mcfg-unlink\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/cfg-unlink-options.hxx b/bpkg/cfg-unlink-options.hxx new file mode 100644 index 0000000..14c9aa4 --- /dev/null +++ b/bpkg/cfg-unlink-options.hxx @@ -0,0 +1,137 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_CFG_UNLINK_OPTIONS_HXX +#define BPKG_CFG_UNLINK_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class cfg_unlink_options: public ::bpkg::configuration_options + { + public: + cfg_unlink_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const cfg_unlink_options&); + + // Option accessors. + // + const string& + name () const; + + bool + name_specified () const; + + const uint64_t& + id () const; + + bool + id_specified () const; + + const uuid_type& + uuid () const; + + bool + uuid_specified () const; + + const bool& + dangling () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + string name_; + bool name_specified_; + uint64_t id_; + bool id_specified_; + uuid_type uuid_; + bool uuid_specified_; + bool dangling_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_cfg_unlink_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/cfg-unlink-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_CFG_UNLINK_OPTIONS_HXX diff --git a/bpkg/cfg-unlink-options.ixx b/bpkg/cfg-unlink-options.ixx new file mode 100644 index 0000000..7d9d63c --- /dev/null +++ b/bpkg/cfg-unlink-options.ixx @@ -0,0 +1,63 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // cfg_unlink_options + // + + inline const string& cfg_unlink_options:: + name () const + { + return this->name_; + } + + inline bool cfg_unlink_options:: + name_specified () const + { + return this->name_specified_; + } + + inline const uint64_t& cfg_unlink_options:: + id () const + { + return this->id_; + } + + inline bool cfg_unlink_options:: + id_specified () const + { + return this->id_specified_; + } + + inline const uuid_type& cfg_unlink_options:: + uuid () const + { + return this->uuid_; + } + + inline bool cfg_unlink_options:: + uuid_specified () const + { + return this->uuid_specified_; + } + + inline const bool& cfg_unlink_options:: + dangling () const + { + return this->dangling_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/common-options.cxx b/bpkg/common-options.cxx new file mode 100644 index 0000000..dedb6de --- /dev/null +++ b/bpkg/common-options.cxx @@ -0,0 +1,2002 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/common-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> +#include <fstream> + +namespace bpkg +{ + namespace cli + { + // unknown_option + // + unknown_option:: + ~unknown_option () throw () + { + } + + void unknown_option:: + print (::std::ostream& os) const + { + os << "unknown option '" << option ().c_str () << "'"; + } + + const char* unknown_option:: + what () const throw () + { + return "unknown option"; + } + + // unknown_argument + // + unknown_argument:: + ~unknown_argument () throw () + { + } + + void unknown_argument:: + print (::std::ostream& os) const + { + os << "unknown argument '" << argument ().c_str () << "'"; + } + + const char* unknown_argument:: + what () const throw () + { + return "unknown argument"; + } + + // missing_value + // + missing_value:: + ~missing_value () throw () + { + } + + void missing_value:: + print (::std::ostream& os) const + { + os << "missing value for option '" << option ().c_str () << "'"; + } + + const char* missing_value:: + what () const throw () + { + return "missing option value"; + } + + // invalid_value + // + invalid_value:: + ~invalid_value () throw () + { + } + + void invalid_value:: + print (::std::ostream& os) const + { + os << "invalid value '" << value ().c_str () << "' for option '" + << option ().c_str () << "'"; + + if (!message ().empty ()) + os << ": " << message ().c_str (); + } + + const char* invalid_value:: + what () const throw () + { + return "invalid option value"; + } + + // eos_reached + // + void eos_reached:: + print (::std::ostream& os) const + { + os << what (); + } + + const char* eos_reached:: + what () const throw () + { + return "end of argument stream reached"; + } + + // file_io_failure + // + file_io_failure:: + ~file_io_failure () throw () + { + } + + void file_io_failure:: + print (::std::ostream& os) const + { + os << "unable to open file '" << file ().c_str () << "' or read failure"; + } + + const char* file_io_failure:: + what () const throw () + { + return "unable to open file or read failure"; + } + + // unmatched_quote + // + unmatched_quote:: + ~unmatched_quote () throw () + { + } + + void unmatched_quote:: + print (::std::ostream& os) const + { + os << "unmatched quote in argument '" << argument ().c_str () << "'"; + } + + const char* unmatched_quote:: + what () const throw () + { + return "unmatched quote"; + } + + // unexpected_group + // + unexpected_group:: + ~unexpected_group () throw () + { + } + + void unexpected_group:: + print (::std::ostream& os) const + { + os << "unexpected grouped argument '" << group_ << "' " + << "for argument '" << argument_ << "'"; + } + + const char* unexpected_group:: + what () const throw () + { + return "unexpected grouped argument"; + } + + // group_separator + // + group_separator:: + ~group_separator () throw () + { + } + + void group_separator:: + print (::std::ostream& os) const + { + bool ex (!expected_.empty ()); + bool en (!encountered_.empty ()); + + if (ex) + { + os << "expected group separator '" << expected_ << "'"; + if (en) + os << " instead of '" << encountered_ << "'"; + } + else + os << "unexpected group separator '" << encountered_ << "'"; + + if (en) + os << ", use '\\" << encountered_ << "' to escape"; + } + + const char* group_separator:: + what () const throw () + { + bool ex (!expected_.empty ()); + bool en (!encountered_.empty ()); + + return en + ? ex ? "wrong group separator" : "unexpected group separator" + : ex ? "expected group separator" : ""; + } + + // scanner + // + scanner:: + ~scanner () + { + } + + // argv_scanner + // + bool argv_scanner:: + more () + { + return i_ < argc_; + } + + const char* argv_scanner:: + peek () + { + if (i_ < argc_) + return argv_[i_]; + else + throw eos_reached (); + } + + const char* argv_scanner:: + next () + { + if (i_ < argc_) + { + const char* r (argv_[i_]); + + if (erase_) + { + for (int i (i_ + 1); i < argc_; ++i) + argv_[i - 1] = argv_[i]; + + --argc_; + argv_[argc_] = 0; + } + else + ++i_; + + ++start_position_; + return r; + } + else + throw eos_reached (); + } + + void argv_scanner:: + skip () + { + if (i_ < argc_) + { + ++i_; + ++start_position_; + } + else + throw eos_reached (); + } + + std::size_t argv_scanner:: + position () + { + return start_position_; + } + + // vector_scanner + // + bool vector_scanner:: + more () + { + return i_ < v_.size (); + } + + const char* vector_scanner:: + peek () + { + if (i_ < v_.size ()) + return v_[i_].c_str (); + else + throw eos_reached (); + } + + const char* vector_scanner:: + next () + { + if (i_ < v_.size ()) + return v_[i_++].c_str (); + else + throw eos_reached (); + } + + void vector_scanner:: + skip () + { + if (i_ < v_.size ()) + ++i_; + else + throw eos_reached (); + } + + std::size_t vector_scanner:: + position () + { + return start_position_ + i_; + } + + // argv_file_scanner + // + int argv_file_scanner::zero_argc_ = 0; + std::string argv_file_scanner::empty_string_; + + bool argv_file_scanner:: + more () + { + if (!args_.empty ()) + return true; + + while (base::more ()) + { + // See if the next argument is the file option. + // + const char* a (base::peek ()); + const option_info* oi = 0; + const char* ov = 0; + + if (!skip_) + { + if ((oi = find (a)) != 0) + { + base::next (); + + if (!base::more ()) + throw missing_value (a); + + ov = base::next (); + } + else if (std::strncmp (a, "-", 1) == 0) + { + if ((ov = std::strchr (a, '=')) != 0) + { + std::string o (a, 0, ov - a); + if ((oi = find (o.c_str ())) != 0) + { + base::next (); + ++ov; + } + } + } + } + + if (oi != 0) + { + if (oi->search_func != 0) + { + std::string f (oi->search_func (ov, oi->arg)); + + if (!f.empty ()) + load (f); + } + else + load (ov); + + if (!args_.empty ()) + return true; + } + else + { + if (!skip_) + skip_ = (std::strcmp (a, "--") == 0); + + return true; + } + } + + return false; + } + + const char* argv_file_scanner:: + peek () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? base::peek () : args_.front ().value.c_str (); + } + + const std::string& argv_file_scanner:: + peek_file () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? empty_string_ : *args_.front ().file; + } + + std::size_t argv_file_scanner:: + peek_line () + { + if (!more ()) + throw eos_reached (); + + return args_.empty () ? 0 : args_.front ().line; + } + + const char* argv_file_scanner:: + next () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::next (); + else + { + hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value); + args_.pop_front (); + ++start_position_; + return hold_[i_].c_str (); + } + } + + void argv_file_scanner:: + skip () + { + if (!more ()) + throw eos_reached (); + + if (args_.empty ()) + return base::skip (); + else + { + args_.pop_front (); + ++start_position_; + } + } + + const argv_file_scanner::option_info* argv_file_scanner:: + find (const char* a) const + { + for (std::size_t i (0); i < options_count_; ++i) + if (std::strcmp (a, options_[i].option) == 0) + return &options_[i]; + + return 0; + } + + std::size_t argv_file_scanner:: + position () + { + return start_position_; + } + + void argv_file_scanner:: + load (const std::string& file) + { + using namespace std; + + ifstream is (file.c_str ()); + + if (!is.is_open ()) + throw file_io_failure (file); + + files_.push_back (file); + + arg a; + a.file = &*files_.rbegin (); + + for (a.line = 1; !is.eof (); ++a.line) + { + string line; + getline (is, line); + + if (is.fail () && !is.eof ()) + throw file_io_failure (file); + + string::size_type n (line.size ()); + + // Trim the line from leading and trailing whitespaces. + // + if (n != 0) + { + const char* f (line.c_str ()); + const char* l (f + n); + + const char* of (f); + while (f < l && (*f == ' ' || *f == '\t' || *f == '\r')) + ++f; + + --l; + + const char* ol (l); + while (l > f && (*l == ' ' || *l == '\t' || *l == '\r')) + --l; + + if (f != of || l != ol) + line = f <= l ? string (f, l - f + 1) : string (); + } + + // Ignore empty lines, those that start with #. + // + if (line.empty () || line[0] == '#') + continue; + + string::size_type p (string::npos); + if (line.compare (0, 1, "-") == 0) + { + p = line.find (' '); + + string::size_type q (line.find ('=')); + if (q != string::npos && q < p) + p = q; + } + + string s1; + if (p != string::npos) + { + s1.assign (line, 0, p); + + // Skip leading whitespaces in the argument. + // + if (line[p] == '=') + ++p; + else + { + n = line.size (); + for (++p; p < n; ++p) + { + char c (line[p]); + if (c != ' ' && c != '\t' && c != '\r') + break; + } + } + } + else if (!skip_) + skip_ = (line == "--"); + + string s2 (line, p != string::npos ? p : 0); + + // If the string (which is an option value or argument) is + // wrapped in quotes, remove them. + // + n = s2.size (); + char cf (s2[0]), cl (s2[n - 1]); + + if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'') + { + if (n == 1 || cf != cl) + throw unmatched_quote (s2); + + s2 = string (s2, 1, n - 2); + } + + if (!s1.empty ()) + { + // See if this is another file option. + // + const option_info* oi; + if (!skip_ && (oi = find (s1.c_str ()))) + { + if (s2.empty ()) + throw missing_value (oi->option); + + if (oi->search_func != 0) + { + string f (oi->search_func (s2.c_str (), oi->arg)); + if (!f.empty ()) + load (f); + } + else + { + // If the path of the file being parsed is not simple and the + // path of the file that needs to be loaded is relative, then + // complete the latter using the former as a base. + // +#ifndef _WIN32 + string::size_type p (file.find_last_of ('/')); + bool c (p != string::npos && s2[0] != '/'); +#else + string::size_type p (file.find_last_of ("/\\")); + bool c (p != string::npos && s2[1] != ':'); +#endif + if (c) + s2.insert (0, file, 0, p + 1); + + load (s2); + } + + continue; + } + + a.value = s1; + args_.push_back (a); + } + + a.value = s2; + args_.push_back (a); + } + } + + // group_scanner + // + bool group_scanner:: + more () + { + // We don't want to call scan_group() here since that + // would invalidate references to previous arguments. + // But we do need to check that the previous group was + // handled. + // + if (state_ == scanned) + { + if (group_scan_.end () != group_.size ()) + throw unexpected_group (arg_[i_][j_], group_scan_.next ()); + } + + return j_ != 0 || scan_.more (); + } + + const char* group_scanner:: + peek () + { + if (state_ != peeked) + { + scan_group (); + state_ = peeked; + } + + // Return unescaped. + return arg_[i_][j_ - 1].c_str (); + } + + const char* group_scanner:: + next () + { + if (state_ != peeked) + scan_group (); + state_ = scanned; + // Return unescaped. + return arg_[i_][--j_].c_str (); + } + + void group_scanner:: + skip () + { + if (state_ != peeked) + scan_group (); + state_ = skipped; + --j_; + } + + std::size_t group_scanner:: + position () + { + return j_ == 0 ? scan_.position () : pos_ + (arg_[i_].size () - j_); + } + + void group_scanner:: + scan_group () + { + // If the previous argument has been scanned, then make + // sure the group has been scanned (handled) as well. + // + if (state_ == scanned) + { + if (group_scan_.end () != group_.size ()) + throw unexpected_group (arg_[i_][j_], group_scan_.next ()); + } + + // If we still have arguments in the pack, rewind the group. + // + if (j_ != 0) + { + group_scan_.reset (); + return; + } + + i_ += (i_ == 0 ? 1 : -1); + group_.clear (); + group_scan_.reset (); + pos_ = scan_.position (); + + // Note: using group_ won't cover empty groups and using + // j_ won't cover single-argument packs. + // + bool group (false), pack (false); + + do + { + const char* a (scan_.next ()); + size_t i (*a == '\\' ? 1 : 0); + separator s (sense (a + i)); + + if (s == none || i != 0) + { + if (arg_[i_].size () != 1) + arg_[i_].resize (1); + + arg_[i_][0] = a + (s != none ? i : 0); + j_ = 1; + break; + } + + // Start of a leading group for the next argument or + // argument pack. We will only know which once we see + // the closing separator. + // + if (s != open) + throw group_separator (a, ""); + + size_t n (group_.size ()); + + // Scan the group until the closing separator. + // + s = none; + while (s == none && scan_.more ()) + { + a = scan_.next (); + i = (*a == '\\' ? 1 : 0); + s = sense (a + i); + + if (s == none || i != 0) + { + group_.push_back (a + (s != none ? i : 0)); + s = none; + } + } + + if (s == close) + { + size_t m (group_.size ()); + + j_ = m - n; + if (j_ == 0) + throw group_separator ("{", ""); + + if (arg_[i_].size () != j_) + arg_[i_].resize (j_); + + // Move from group_ to arg_. Add in reverse for ease + // of iteration. + // + for (size_t j (0); j != j_; ++j) + arg_[i_][j] = group_[m - j - 1]; + group_.resize (n); + + pack = true; + break; + } + else if (s == close_plus) + group = true; + else + throw group_separator ((s != none ? a : ""), "}+"); + } + while (scan_.more ()); + + // Handle the case where we have seen the leading group + // but there are no more arguments. + // + if (group && j_ == 0) + throw group_separator ("{", ""); + + // Handle trailing groups, if any. + // + while (scan_.more ()) + { + const char* a (scan_.peek ()); + size_t i (*a == '\\' ? 1 : 0); + separator s (sense (a + i)); + + // Next argument, argument pack, or leading group. + // + if (s == none || s == open || i != 0) + break; + + if (s != open_plus) + throw group_separator (a, ""); + + group = true; + + // Scan the group until the closing separator. + // + scan_.next (); + s = none; + while (s == none && scan_.more ()) + { + a = scan_.next (); + i = (*a == '\\' ? 1 : 0); + s = sense (a + i); + + if (s == none || i != 0) + { + group_.push_back (a + (s != none ? i : 0)); + s = none; + } + } + + if (s != close) + throw group_separator ((s != none ? a : ""), "}"); + } + + // Handle the case where we have seen the argument pack + // without leading or trailing group. + // + if (pack && !group) + throw group_separator ("{", ""); + } + + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // common_options + // + + common_options:: + common_options () + : v_ (), + V_ (), + quiet_ (), + verbose_ (1), + verbose_specified_ (false), + stdout_format_ (bpkg::stdout_format::lines), + stdout_format_specified_ (false), + jobs_ (), + jobs_specified_ (false), + no_result_ (), + progress_ (), + no_progress_ (), + build_ (), + build_specified_ (false), + build_option_ (), + build_option_specified_ (false), + fetch_ (), + fetch_specified_ (false), + fetch_option_ (), + fetch_option_specified_ (false), + fetch_timeout_ (), + fetch_timeout_specified_ (false), + pkg_proxy_ (), + pkg_proxy_specified_ (false), + git_ ("git"), + git_specified_ (false), + git_option_ (), + git_option_specified_ (false), + sha256_ (), + sha256_specified_ (false), + sha256_option_ (), + sha256_option_specified_ (false), + tar_ (), + tar_specified_ (false), + tar_option_ (), + tar_option_specified_ (false), + openssl_ ("openssl"), + openssl_specified_ (false), + openssl_option_ (), + openssl_option_specified_ (false), + auth_ (bpkg::auth::remote), + auth_specified_ (false), + trust_ (), + trust_specified_ (false), + trust_yes_ (), + trust_no_ (), + pager_ (), + pager_specified_ (false), + pager_option_ (), + pager_option_specified_ (false), + options_file_ (), + options_file_specified_ (false), + default_options_ (), + default_options_specified_ (false), + no_default_options_ () + { + } + + void common_options:: + merge (const common_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.v_) + { + ::bpkg::cli::parser< bool>::merge ( + this->v_, a.v_); + } + + if (a.V_) + { + ::bpkg::cli::parser< bool>::merge ( + this->V_, a.V_); + } + + if (a.quiet_) + { + ::bpkg::cli::parser< bool>::merge ( + this->quiet_, a.quiet_); + } + + if (a.verbose_specified_) + { + ::bpkg::cli::parser< uint16_t>::merge ( + this->verbose_, a.verbose_); + this->verbose_specified_ = true; + } + + if (a.stdout_format_specified_) + { + ::bpkg::cli::parser< bpkg::stdout_format>::merge ( + this->stdout_format_, a.stdout_format_); + this->stdout_format_specified_ = true; + } + + if (a.jobs_specified_) + { + ::bpkg::cli::parser< size_t>::merge ( + this->jobs_, a.jobs_); + this->jobs_specified_ = true; + } + + if (a.no_result_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_result_, a.no_result_); + } + + if (a.progress_) + { + ::bpkg::cli::parser< bool>::merge ( + this->progress_, a.progress_); + } + + if (a.no_progress_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_progress_, a.no_progress_); + } + + if (a.build_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->build_, a.build_); + this->build_specified_ = true; + } + + if (a.build_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->build_option_, a.build_option_); + this->build_option_specified_ = true; + } + + if (a.fetch_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->fetch_, a.fetch_); + this->fetch_specified_ = true; + } + + if (a.fetch_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fetch_option_, a.fetch_option_); + this->fetch_option_specified_ = true; + } + + if (a.fetch_timeout_specified_) + { + ::bpkg::cli::parser< size_t>::merge ( + this->fetch_timeout_, a.fetch_timeout_); + this->fetch_timeout_specified_ = true; + } + + if (a.pkg_proxy_specified_) + { + ::bpkg::cli::parser< butl::url>::merge ( + this->pkg_proxy_, a.pkg_proxy_); + this->pkg_proxy_specified_ = true; + } + + if (a.git_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->git_, a.git_); + this->git_specified_ = true; + } + + if (a.git_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->git_option_, a.git_option_); + this->git_option_specified_ = true; + } + + if (a.sha256_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->sha256_, a.sha256_); + this->sha256_specified_ = true; + } + + if (a.sha256_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->sha256_option_, a.sha256_option_); + this->sha256_option_specified_ = true; + } + + if (a.tar_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->tar_, a.tar_); + this->tar_specified_ = true; + } + + if (a.tar_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->tar_option_, a.tar_option_); + this->tar_option_specified_ = true; + } + + if (a.openssl_specified_) + { + ::bpkg::cli::parser< qualified_option<openssl_commands, path>>::merge ( + this->openssl_, a.openssl_); + this->openssl_specified_ = true; + } + + if (a.openssl_option_specified_) + { + ::bpkg::cli::parser< qualified_option<openssl_commands, strings>>::merge ( + this->openssl_option_, a.openssl_option_); + this->openssl_option_specified_ = true; + } + + if (a.auth_specified_) + { + ::bpkg::cli::parser< bpkg::auth>::merge ( + this->auth_, a.auth_); + this->auth_specified_ = true; + } + + if (a.trust_specified_) + { + ::bpkg::cli::parser< std::set<string, icase_compare_string>>::merge ( + this->trust_, a.trust_); + this->trust_specified_ = true; + } + + if (a.trust_yes_) + { + ::bpkg::cli::parser< bool>::merge ( + this->trust_yes_, a.trust_yes_); + } + + if (a.trust_no_) + { + ::bpkg::cli::parser< bool>::merge ( + this->trust_no_, a.trust_no_); + } + + if (a.pager_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->pager_, a.pager_); + this->pager_specified_ = true; + } + + if (a.pager_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->pager_option_, a.pager_option_); + this->pager_option_specified_ = true; + } + + if (a.options_file_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->options_file_, a.options_file_); + this->options_file_specified_ = true; + } + + if (a.default_options_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->default_options_, a.default_options_); + this->default_options_specified_ = true; + } + + if (a.no_default_options_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_default_options_, a.no_default_options_); + } + } + + ::bpkg::cli::usage_para common_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMON OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "The common options are summarized below with a more detailed description" << ::std::endl + << "available in \033[1mbpkg-common-options(1)\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m-v\033[0m Print essential underlying commands being executed." << ::std::endl; + + os << "\033[1m-V\033[0m Print all underlying commands being executed." << ::std::endl; + + os << "\033[1m--quiet\033[0m|\033[1m-q\033[0m Run quietly, only printing error messages." << ::std::endl; + + os << "\033[1m--verbose\033[0m \033[4mlevel\033[0m Set the diagnostics verbosity to \033[4mlevel\033[0m between 0 and" << ::std::endl + << " 6." << ::std::endl; + + os << "\033[1m--stdout-format\033[0m \033[4mformat\033[0m Representation format to use for printing to \033[1mstdout\033[0m." << ::std::endl; + + os << "\033[1m--jobs\033[0m|\033[1m-j\033[0m \033[4mnum\033[0m Number of jobs to perform in parallel." << ::std::endl; + + os << "\033[1m--no-result\033[0m Don't print informational messages about the outcome" << ::std::endl + << " of performing a command or some of its parts." << ::std::endl; + + os << "\033[1m--progress\033[0m Display progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << "\033[1m--no-progress\033[0m Suppress progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << "\033[1m--build\033[0m \033[4mpath\033[0m The build program to be used to build packages." << ::std::endl; + + os << "\033[1m--build-option\033[0m \033[4mopt\033[0m Additional option to be passed to the build program." << ::std::endl; + + os << "\033[1m--fetch\033[0m \033[4mpath\033[0m The fetch program to be used to download resources." << ::std::endl; + + os << "\033[1m--fetch-option\033[0m \033[4mopt\033[0m Additional option to be passed to the fetch program." << ::std::endl; + + os << "\033[1m--fetch-timeout\033[0m \033[4msec\033[0m The fetch and fetch-like (for example, \033[1mgit\033[0m) program" << ::std::endl + << " timeout." << ::std::endl; + + os << "\033[1m--pkg-proxy\033[0m \033[4murl\033[0m HTTP proxy server to use when fetching package" << ::std::endl + << " manifests and archives from remote \033[1mpkg\033[0m repositories." << ::std::endl; + + os << "\033[1m--git\033[0m \033[4mpath\033[0m The git program to be used to fetch git repositories." << ::std::endl; + + os << "\033[1m--git-option\033[0m \033[4mopt\033[0m Additional common option to be passed to the git" << ::std::endl + << " program." << ::std::endl; + + os << "\033[1m--sha256\033[0m \033[4mpath\033[0m The sha256 program to be used to calculate SHA256" << ::std::endl + << " sums." << ::std::endl; + + os << "\033[1m--sha256-option\033[0m \033[4mopt\033[0m Additional option to be passed to the sha256 program." << ::std::endl; + + os << "\033[1m--tar\033[0m \033[4mpath\033[0m The tar program to be used to extract package" << ::std::endl + << " archives." << ::std::endl; + + os << "\033[1m--tar-option\033[0m \033[4mopt\033[0m Additional option to be passed to the tar program." << ::std::endl; + + os << "\033[1m--openssl\033[0m \033[4mpath\033[0m The openssl program to be used for crypto operations." << ::std::endl; + + os << "\033[1m--openssl-option\033[0m \033[4mopt\033[0m Additional option to be passed to the openssl program." << ::std::endl; + + os << "\033[1m--auth\033[0m \033[4mtype\033[0m Types of repositories to authenticate." << ::std::endl; + + os << "\033[1m--trust\033[0m \033[4mfingerprint\033[0m Trust repository certificate with a SHA256" << ::std::endl + << " \033[4mfingerprint\033[0m." << ::std::endl; + + os << "\033[1m--trust-yes\033[0m Assume the answer to all authentication prompts is" << ::std::endl + << " \033[1myes\033[0m." << ::std::endl; + + os << "\033[1m--trust-no\033[0m Assume the answer to all authentication prompts is \033[1mno\033[0m." << ::std::endl; + + os << "\033[1m--pager\033[0m \033[4mpath\033[0m The pager program to be used to show long text." << ::std::endl; + + os << "\033[1m--pager-option\033[0m \033[4mopt\033[0m Additional option to be passed to the pager program." << ::std::endl; + + os << "\033[1m--options-file\033[0m \033[4mfile\033[0m Read additional options from \033[4mfile\033[0m." << ::std::endl; + + os << "\033[1m--default-options\033[0m \033[4mdir\033[0m The directory to load additional default options files" << ::std::endl + << " from." << ::std::endl; + + os << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + ::bpkg::cli::usage_para common_options:: + print_long_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mCOMMON OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m-v\033[0m Print essential underlying commands being executed." << ::std::endl + << " This is equivalent to \033[1m--verbose 2\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m-V\033[0m Print all underlying commands being executed. This is" << ::std::endl + << " equivalent to \033[1m--verbose 3\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--quiet\033[0m|\033[1m-q\033[0m Run quietly, only printing error messages. This is" << ::std::endl + << " equivalent to \033[1m--verbose 0\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--verbose\033[0m \033[4mlevel\033[0m Set the diagnostics verbosity to \033[4mlevel\033[0m between 0 and" << ::std::endl + << " 6. Level 0 disables any non-error messages while level" << ::std::endl + << " 6 produces lots of information, with level 1 being the" << ::std::endl + << " default. The following additional types of diagnostics" << ::std::endl + << " are produced at each level:" << ::std::endl + << ::std::endl + << " 1. High-level information messages." << ::std::endl + << " 2. Essential underlying commands being executed." << ::std::endl + << " 3. All underlying commands being executed." << ::std::endl + << " 4. Information that could be helpful to the user." << ::std::endl + << " 5. Information that could be helpful to the developer." << ::std::endl + << " 6. Even more detailed information." << ::std::endl; + + os << std::endl + << "\033[1m--stdout-format\033[0m \033[4mformat\033[0m Representation format to use for printing to \033[1mstdout\033[0m." << ::std::endl + << " Valid values for this option are \033[1mlines\033[0m (default) and" << ::std::endl + << " \033[1mjson\033[0m. See the JSON OUTPUT section below for details on" << ::std::endl + << " the \033[1mjson\033[0m format." << ::std::endl; + + os << std::endl + << "\033[1m--jobs\033[0m|\033[1m-j\033[0m \033[4mnum\033[0m Number of jobs to perform in parallel. If this option" << ::std::endl + << " is not specified or specified with the 0\033[0m value, then" << ::std::endl + << " the number of available hardware threads is used. This" << ::std::endl + << " option is also propagated when performing build system" << ::std::endl + << " operations such as \033[1mupdate\033[0m, \033[1mtest\033[0m, etc." << ::std::endl; + + os << std::endl + << "\033[1m--no-result\033[0m Don't print informational messages about the outcome" << ::std::endl + << " of performing a command or some of its parts. Note" << ::std::endl + << " that if this option is specified, then for certain" << ::std::endl + << " long-running command parts progress is displayed" << ::std::endl + << " instead, unless suppressed with \033[1m--no-progress\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--progress\033[0m Display progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl + << " If printing to a terminal the progress is displayed by" << ::std::endl + << " default for low verbosity levels. Use \033[1m--no-progress\033[0m to" << ::std::endl + << " suppress." << ::std::endl; + + os << std::endl + << "\033[1m--no-progress\033[0m Suppress progress indicators for long-lasting" << ::std::endl + << " operations, such as network transfers, building, etc." << ::std::endl; + + os << std::endl + << "\033[1m--build\033[0m \033[4mpath\033[0m The build program to be used to build packages. This" << ::std::endl + << " should be the path to the build2 \033[1mb\033[0m executable. You can" << ::std::endl + << " also specify additional options that should be passed" << ::std::endl + << " to the build program with \033[1m--build-option\033[0m." << ::std::endl + << ::std::endl + << " If the build program is not explicitly specified, then" << ::std::endl + << " \033[1mbpkg\033[0m will by default use \033[1mb\033[0m plus an executable suffix" << ::std::endl + << " if one was specified when building \033[1mbpkg\033[0m. So, for" << ::std::endl + << " example, if \033[1mbpkg\033[0m name was set to \033[1mbpkg-1.0\033[0m, then it" << ::std::endl + << " will look for \033[1mb-1.0\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--build-option\033[0m \033[4mopt\033[0m Additional option to be passed to the build program." << ::std::endl + << " See \033[1m--build\033[0m for more information on the build program." << ::std::endl + << " Repeat this option to specify multiple build options." << ::std::endl; + + os << std::endl + << "\033[1m--fetch\033[0m \033[4mpath\033[0m The fetch program to be used to download resources." << ::std::endl + << " Currently, \033[1mbpkg\033[0m recognizes \033[1mcurl\033[0m, \033[1mwget\033[0m, and \033[1mfetch\033[0m. Note" << ::std::endl + << " that the last component of \033[4mpath\033[0m must contain one of" << ::std::endl + << " these names as a substring in order for \033[1mbpkg\033[0m to" << ::std::endl + << " recognize which program is being used. You can also" << ::std::endl + << " specify additional options that should be passed to" << ::std::endl + << " the fetch program with \033[1m--fetch-option\033[0m." << ::std::endl + << ::std::endl + << " If the fetch program is not specified, then \033[1mbpkg\033[0m will" << ::std::endl + << " try to discover if one of the above programs is" << ::std::endl + << " available and use that. Currently, \033[1mbpkg\033[0m has the" << ::std::endl + << " following preference order: \033[1mwget\033[0m 1.16 or higher" << ::std::endl + << " (supports \033[1m--show-progress\033[0m), \033[1mcurl\033[0m, \033[1mwget\033[0m, and \033[1mfetch\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--fetch-option\033[0m \033[4mopt\033[0m Additional option to be passed to the fetch program." << ::std::endl + << " See \033[1m--fetch\033[0m for more information on the fetch program." << ::std::endl + << " Repeat this option to specify multiple fetch options." << ::std::endl; + + os << std::endl + << "\033[1m--fetch-timeout\033[0m \033[4msec\033[0m The fetch and fetch-like (for example, \033[1mgit\033[0m) program" << ::std::endl + << " timeout. While the exact semantics of the value" << ::std::endl + << " depends on the program used, at a minimum it specifies" << ::std::endl + << " in seconds the maximum time that can be spent without" << ::std::endl + << " any network activity." << ::std::endl + << ::std::endl + << " Specifically, it is translated to the \033[1m--max-time\033[0m" << ::std::endl + << " option for \033[1mcurl\033[0m and to the \033[1m--timeout\033[0m option for \033[1mwget\033[0m" << ::std::endl + << " and \033[1mfetch\033[0m. For \033[1mgit\033[0m over HTTP/HTTPS this semantics is" << ::std::endl + << " achieved using the \033[1mhttp.lowSpeedLimit\033[0m=\033[4m1\033[0m" << ::std::endl + << " \033[1mhttp.lowSpeedTime\033[0m=\033[4msec\033[0m configuration values (the" << ::std::endl + << " \033[1mgit://\033[0m and \033[1mssh://\033[0m protocols currently do not support" << ::std::endl + << " timeouts)." << ::std::endl + << ::std::endl + << " See \033[1m--fetch\033[0m and \033[1m--git\033[0m for more information on the" << ::std::endl + << " fetch programs." << ::std::endl; + + os << std::endl + << "\033[1m--pkg-proxy\033[0m \033[4murl\033[0m HTTP proxy server to use when fetching package" << ::std::endl + << " manifests and archives from remote \033[1mpkg\033[0m repositories." << ::std::endl + << " If specified, the proxy \033[4murl\033[0m must be in the" << ::std::endl + << " \033[1mhttp://\033[0m\033[4mhost\033[0m[\033[1m:\033[0m\033[4mport\033[0m]\033[0m form. If \033[4mport\033[0m is omitted, 80 is" << ::std::endl + << " used by default." << ::std::endl + << ::std::endl + << " Note that to allow caching, the proxied \033[1mhttps://\033[0m URLs" << ::std::endl + << " are converted to \033[1mhttp://\033[0m in order to prevent the fetch" << ::std::endl + << " program from tunneling (which is the standard approach" << ::std::endl + << " for proxying HTTPS). If both HTTP and HTTPS" << ::std::endl + << " repositories are used, it is assumed that the proxy" << ::std::endl + << " server can figure out which URLs need to be converted" << ::std::endl + << " back to \033[1mhttps://\033[0m based on the request information (for" << ::std::endl + << " example, host name). For security, this mechanism" << ::std::endl + << " should only be used with signed repositories or when" << ::std::endl + << " the proxy is located inside a trusted network." << ::std::endl; + + os << std::endl + << "\033[1m--git\033[0m \033[4mpath\033[0m The git program to be used to fetch git repositories." << ::std::endl + << " You can also specify additional options that should be" << ::std::endl + << " passed to the git program with \033[1m--git-option\033[0m." << ::std::endl + << ::std::endl + << " If the git program is not explicitly specified, then" << ::std::endl + << " \033[1mbpkg\033[0m will use \033[1mgit\033[0m by default." << ::std::endl; + + os << std::endl + << "\033[1m--git-option\033[0m \033[4mopt\033[0m Additional common option to be passed to the git" << ::std::endl + << " program. Note that the common options are the ones" << ::std::endl + << " that precede the \033[1mgit\033[0m command. See \033[1m--git\033[0m for more" << ::std::endl + << " information on the git program. Repeat this option to" << ::std::endl + << " specify multiple git options." << ::std::endl; + + os << std::endl + << "\033[1m--sha256\033[0m \033[4mpath\033[0m The sha256 program to be used to calculate SHA256" << ::std::endl + << " sums. Currently, \033[1mbpkg\033[0m recognizes \033[1msha256\033[0m, \033[1msha256sum\033[0m," << ::std::endl + << " and \033[1mshasum\033[0m. Note that the last component of \033[4mpath\033[0m must" << ::std::endl + << " contain one of these names as a substring in order for" << ::std::endl + << " \033[1mbpkg\033[0m to recognize which program is being used. You can" << ::std::endl + << " also specify additional options that should be passed" << ::std::endl + << " to the sha256 program with \033[1m--sha256-option\033[0m." << ::std::endl + << ::std::endl + << " If the sha256 program is not specified, then \033[1mbpkg\033[0m will" << ::std::endl + << " try to discover if one of the above programs is" << ::std::endl + << " available and use that. Currently, \033[1mbpkg\033[0m has the" << ::std::endl + << " following preference order: \033[1msha256\033[0m, \033[1msha256sum\033[0m, and" << ::std::endl + << " \033[1mshasum\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--sha256-option\033[0m \033[4mopt\033[0m Additional option to be passed to the sha256 program." << ::std::endl + << " See \033[1m--sha256\033[0m for more information on the sha256" << ::std::endl + << " program. Repeat this option to specify multiple sha256" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--tar\033[0m \033[4mpath\033[0m The tar program to be used to extract package" << ::std::endl + << " archives. For example, \033[1mgtar\033[0m or \033[1mbsdtar\033[0m. You can also" << ::std::endl + << " specify additional options that should be passed to" << ::std::endl + << " the tar program with \033[1m--tar-option\033[0m. If the tar program" << ::std::endl + << " is not explicitly specified, then \033[1mbpkg\033[0m will use \033[1mtar\033[0m by" << ::std::endl + << " default." << ::std::endl; + + os << std::endl + << "\033[1m--tar-option\033[0m \033[4mopt\033[0m Additional option to be passed to the tar program. See" << ::std::endl + << " \033[1m--tar\033[0m for more information on the tar program. Repeat" << ::std::endl + << " this option to specify multiple tar options." << ::std::endl; + + os << std::endl + << "\033[1m--openssl\033[0m \033[4mpath\033[0m The openssl program to be used for crypto operations." << ::std::endl + << " You can also specify additional options that should be" << ::std::endl + << " passed to the openssl program with \033[1m--openssl-option\033[0m." << ::std::endl + << " If the openssl program is not explicitly specified," << ::std::endl + << " then \033[1mbpkg\033[0m will use \033[1mopenssl\033[0m by default." << ::std::endl + << ::std::endl + << " The \033[1m--openssl*\033[0m values can be optionally qualified with" << ::std::endl + << " the openssl command in the \033[4mcommand\033[0m\033[1m:\033[0m\033[4mvalue\033[0m\033[0m form. This" << ::std::endl + << " makes the value only applicable to the specific" << ::std::endl + << " command, for example:" << ::std::endl + << ::std::endl + << " bpkg rep-create \\" << ::std::endl + << " --openssl pkeyutl:/path/to/openssl \\" << ::std::endl + << " --openssl-option pkeyutl:-engine \\" << ::std::endl + << " --openssl-option pkeyutl:pkcs11 \\" << ::std::endl + << " ..." << ::std::endl + << ::std::endl + << " Note that for \033[1mopenssl\033[0m versions prior to \033[1m3.0.0\033[0m \033[1mbpkg\033[0m" << ::std::endl + << " uses the \033[1mrsautl\033[0m command instead of \033[1mpkeyutl\033[0m for the" << ::std::endl + << " data signing and recovery operations." << ::std::endl + << ::std::endl + << " An unqualified value that contains a colon can be" << ::std::endl + << " specified as qualified with an empty command, for" << ::std::endl + << " example, \033[1m--openssl :C:\\bin\\openssl\033[0m. To see openssl" << ::std::endl + << " commands executed by \033[1mbpkg\033[0m, use the verbose mode (\033[1m-v\033[0m" << ::std::endl + << " option)." << ::std::endl; + + os << std::endl + << "\033[1m--openssl-option\033[0m \033[4mopt\033[0m Additional option to be passed to the openssl program." << ::std::endl + << " See \033[1m--openssl\033[0m for more information on the openssl" << ::std::endl + << " program. The values can be optionally qualified with" << ::std::endl + << " the openssl command, as discussed in \033[1m--openssl\033[0m. Repeat" << ::std::endl + << " this option to specify multiple openssl options." << ::std::endl; + + os << std::endl + << "\033[1m--auth\033[0m \033[4mtype\033[0m Types of repositories to authenticate. Valid values" << ::std::endl + << " for this option are \033[1mnone\033[0m, \033[1mremote\033[0m, \033[1mall\033[0m. By default only" << ::std::endl + << " remote repositories are authenticated. You can request" << ::std::endl + << " authentication of local repositories by passing \033[1mall\033[0m or" << ::std::endl + << " disable authentication completely by passing \033[1mnone\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--trust\033[0m \033[4mfingerprint\033[0m Trust repository certificate with a SHA256" << ::std::endl + << " \033[4mfingerprint\033[0m. Such a certificate is trusted" << ::std::endl + << " automatically, without prompting the user for a" << ::std::endl + << " confirmation. Repeat this option to trust multiple" << ::std::endl + << " certificates." << ::std::endl + << ::std::endl + << " Note that by default \033[1mopenssl\033[0m prints a SHA1 fingerprint" << ::std::endl + << " and to obtain a SHA256 one you will need to pass the" << ::std::endl + << " \033[1m-sha256\033[0m option, for example:" << ::std::endl + << ::std::endl + << " openssl x509 -sha256 -fingerprint -noout -in cert.pem" << ::std::endl; + + os << std::endl + << "\033[1m--trust-yes\033[0m Assume the answer to all authentication prompts is" << ::std::endl + << " \033[1myes\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--trust-no\033[0m Assume the answer to all authentication prompts is \033[1mno\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--pager\033[0m \033[4mpath\033[0m The pager program to be used to show long text." << ::std::endl + << " Commonly used pager programs are \033[1mless\033[0m and \033[1mmore\033[0m. You" << ::std::endl + << " can also specify additional options that should be" << ::std::endl + << " passed to the pager program with \033[1m--pager-option\033[0m. If an" << ::std::endl + << " empty string is specified as the pager program, then" << ::std::endl + << " no pager will be used. If the pager program is not" << ::std::endl + << " explicitly specified, then \033[1mbpkg\033[0m will try to use \033[1mless\033[0m." << ::std::endl + << " If it is not available, then no pager will be used." << ::std::endl; + + os << std::endl + << "\033[1m--pager-option\033[0m \033[4mopt\033[0m Additional option to be passed to the pager program." << ::std::endl + << " See \033[1m--pager\033[0m for more information on the pager program." << ::std::endl + << " Repeat this option to specify multiple pager options." << ::std::endl; + + os << std::endl + << "\033[1m--options-file\033[0m \033[4mfile\033[0m Read additional options from \033[4mfile\033[0m. Each option should" << ::std::endl + << " appear on a separate line optionally followed by space" << ::std::endl + << " or equal sign (\033[1m=\033[0m) and an option value. Empty lines and" << ::std::endl + << " lines starting with \033[1m#\033[0m are ignored. Option values can" << ::std::endl + << " be enclosed in double (\033[1m\"\033[0m) or single (\033[1m'\033[0m) quotes to" << ::std::endl + << " preserve leading and trailing whitespaces as well as" << ::std::endl + << " to specify empty values. If the value itself contains" << ::std::endl + << " trailing or leading quotes, enclose it with an extra" << ::std::endl + << " pair of quotes, for example \033[1m'\"x\"'\033[0m. Non-leading and" << ::std::endl + << " non-trailing quotes are interpreted as being part of" << ::std::endl + << " the option value." << ::std::endl + << ::std::endl + << " The semantics of providing options in a file is" << ::std::endl + << " equivalent to providing the same set of options in the" << ::std::endl + << " same order on the command line at the point where the" << ::std::endl + << " \033[1m--options-file\033[0m option is specified except that the" << ::std::endl + << " shell escaping and quoting is not required. Repeat" << ::std::endl + << " this option to specify more than one options file." << ::std::endl; + + os << std::endl + << "\033[1m--default-options\033[0m \033[4mdir\033[0m The directory to load additional default options files" << ::std::endl + << " from." << ::std::endl; + + os << std::endl + << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (common_options&, ::bpkg::cli::scanner&)> + _cli_common_options_map; + + static _cli_common_options_map _cli_common_options_map_; + + struct _cli_common_options_map_init + { + _cli_common_options_map_init () + { + _cli_common_options_map_["-v"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::v_ >; + _cli_common_options_map_["-V"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::V_ >; + _cli_common_options_map_["--quiet"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::quiet_ >; + _cli_common_options_map_["-q"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::quiet_ >; + _cli_common_options_map_["--verbose"] = + &::bpkg::cli::thunk< common_options, uint16_t, &common_options::verbose_, + &common_options::verbose_specified_ >; + _cli_common_options_map_["--stdout-format"] = + &::bpkg::cli::thunk< common_options, bpkg::stdout_format, &common_options::stdout_format_, + &common_options::stdout_format_specified_ >; + _cli_common_options_map_["--jobs"] = + &::bpkg::cli::thunk< common_options, size_t, &common_options::jobs_, + &common_options::jobs_specified_ >; + _cli_common_options_map_["-j"] = + &::bpkg::cli::thunk< common_options, size_t, &common_options::jobs_, + &common_options::jobs_specified_ >; + _cli_common_options_map_["--no-result"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::no_result_ >; + _cli_common_options_map_["--progress"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::progress_ >; + _cli_common_options_map_["--no-progress"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::no_progress_ >; + _cli_common_options_map_["--build"] = + &::bpkg::cli::thunk< common_options, path, &common_options::build_, + &common_options::build_specified_ >; + _cli_common_options_map_["--build-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::build_option_, + &common_options::build_option_specified_ >; + _cli_common_options_map_["--fetch"] = + &::bpkg::cli::thunk< common_options, path, &common_options::fetch_, + &common_options::fetch_specified_ >; + _cli_common_options_map_["--fetch-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::fetch_option_, + &common_options::fetch_option_specified_ >; + _cli_common_options_map_["--fetch-timeout"] = + &::bpkg::cli::thunk< common_options, size_t, &common_options::fetch_timeout_, + &common_options::fetch_timeout_specified_ >; + _cli_common_options_map_["--pkg-proxy"] = + &::bpkg::cli::thunk< common_options, butl::url, &common_options::pkg_proxy_, + &common_options::pkg_proxy_specified_ >; + _cli_common_options_map_["--git"] = + &::bpkg::cli::thunk< common_options, path, &common_options::git_, + &common_options::git_specified_ >; + _cli_common_options_map_["--git-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::git_option_, + &common_options::git_option_specified_ >; + _cli_common_options_map_["--sha256"] = + &::bpkg::cli::thunk< common_options, path, &common_options::sha256_, + &common_options::sha256_specified_ >; + _cli_common_options_map_["--sha256-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::sha256_option_, + &common_options::sha256_option_specified_ >; + _cli_common_options_map_["--tar"] = + &::bpkg::cli::thunk< common_options, path, &common_options::tar_, + &common_options::tar_specified_ >; + _cli_common_options_map_["--tar-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::tar_option_, + &common_options::tar_option_specified_ >; + _cli_common_options_map_["--openssl"] = + &::bpkg::cli::thunk< common_options, qualified_option<openssl_commands, path>, &common_options::openssl_, + &common_options::openssl_specified_ >; + _cli_common_options_map_["--openssl-option"] = + &::bpkg::cli::thunk< common_options, qualified_option<openssl_commands, strings>, &common_options::openssl_option_, + &common_options::openssl_option_specified_ >; + _cli_common_options_map_["--auth"] = + &::bpkg::cli::thunk< common_options, bpkg::auth, &common_options::auth_, + &common_options::auth_specified_ >; + _cli_common_options_map_["--trust"] = + &::bpkg::cli::thunk< common_options, std::set<string, icase_compare_string>, &common_options::trust_, + &common_options::trust_specified_ >; + _cli_common_options_map_["--trust-yes"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::trust_yes_ >; + _cli_common_options_map_["--trust-no"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::trust_no_ >; + _cli_common_options_map_["--pager"] = + &::bpkg::cli::thunk< common_options, string, &common_options::pager_, + &common_options::pager_specified_ >; + _cli_common_options_map_["--pager-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::pager_option_, + &common_options::pager_option_specified_ >; + _cli_common_options_map_["--options-file"] = + &::bpkg::cli::thunk< common_options, string, &common_options::options_file_, + &common_options::options_file_specified_ >; + _cli_common_options_map_["--default-options"] = + &::bpkg::cli::thunk< common_options, dir_path, &common_options::default_options_, + &common_options::default_options_specified_ >; + _cli_common_options_map_["--no-default-options"] = + &::bpkg::cli::thunk< common_options, bool, &common_options::no_default_options_ >; + } + }; + + static _cli_common_options_map_init _cli_common_options_map_init_; + + bool common_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_common_options_map::const_iterator i (_cli_common_options_map_.find (o)); + + if (i != _cli_common_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_common_options_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg\033[0m [\033[4mcommon-options\033[0m] ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The common options control behavior that is common to all or most of the \033[1mbpkg\033[0m" << ::std::endl + << "commands. They can be specified either before the command or after, together" << ::std::endl + << "with the command-specific options." << ::std::endl; + + p = ::bpkg::common_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mJSON OUTPUT\033[0m" << ::std::endl + << ::std::endl + << "Commands that support the JSON output specify their formats as a serialized" << ::std::endl + << "representation of a C++ \033[1mstruct\033[0m or an array thereof. For example:" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct configuration" << ::std::endl + << "{" << ::std::endl + << " uint64_t id;" << ::std::endl + << " string path;" << ::std::endl + << " optional<string> name;" << ::std::endl + << " bool default;" << ::std::endl + << " vector<package> packages;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "An example of the serialized JSON representation of \033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"," << ::std::endl + << " \"name\": \"gcc\"," << ::std::endl + << " \"default\": true," << ::std::endl + << " \"packages\": [" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"hello\"" << ::std::endl + << " }" << ::std::endl + << " ]" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "This sections provides details on the overall properties of such formats and" << ::std::endl + << "the semantics of the \033[1mstruct\033[0m serialization." << ::std::endl + << ::std::endl + << "The order of members in a JSON object is fixed as specified in the" << ::std::endl + << "corresponding \033[1mstruct\033[0m. While new members may be added in the future (and should" << ::std::endl + << "be ignored by older consumers), the semantics of the existing members" << ::std::endl + << "(including whether the top-level entry is an object or array) may not change." << ::std::endl + << ::std::endl + << "An object member is required unless its type is \033[1moptional<>\033[0m, \033[1mbool\033[0m, or \033[1mvector<>\033[0m" << ::std::endl + << "(array). For \033[1mbool\033[0m members absent means \033[1mfalse\033[0m. For \033[1mvector<>\033[0m members absent means" << ::std::endl + << "empty. An empty top-level array is always present." << ::std::endl + << ::std::endl + << "For example, the following JSON text is a possible serialization of the above" << ::std::endl + << "\033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"" << ::std::endl + << "}" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } + + ::bpkg::cli::usage_para + print_bpkg_common_options_long_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg\033[0m [\033[4mcommon-options\033[0m] ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The common options control behavior that is common to all or most of the \033[1mbpkg\033[0m" << ::std::endl + << "commands. They can be specified either before the command or after, together" << ::std::endl + << "with the command-specific options." << ::std::endl; + + p = ::bpkg::common_options::print_long_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mJSON OUTPUT\033[0m" << ::std::endl + << ::std::endl + << "Commands that support the JSON output specify their formats as a serialized" << ::std::endl + << "representation of a C++ \033[1mstruct\033[0m or an array thereof. For example:" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct configuration" << ::std::endl + << "{" << ::std::endl + << " uint64_t id;" << ::std::endl + << " string path;" << ::std::endl + << " optional<string> name;" << ::std::endl + << " bool default;" << ::std::endl + << " vector<package> packages;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "An example of the serialized JSON representation of \033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"," << ::std::endl + << " \"name\": \"gcc\"," << ::std::endl + << " \"default\": true," << ::std::endl + << " \"packages\": [" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"hello\"" << ::std::endl + << " }" << ::std::endl + << " ]" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "This sections provides details on the overall properties of such formats and" << ::std::endl + << "the semantics of the \033[1mstruct\033[0m serialization." << ::std::endl + << ::std::endl + << "The order of members in a JSON object is fixed as specified in the" << ::std::endl + << "corresponding \033[1mstruct\033[0m. While new members may be added in the future (and should" << ::std::endl + << "be ignored by older consumers), the semantics of the existing members" << ::std::endl + << "(including whether the top-level entry is an object or array) may not change." << ::std::endl + << ::std::endl + << "An object member is required unless its type is \033[1moptional<>\033[0m, \033[1mbool\033[0m, or \033[1mvector<>\033[0m" << ::std::endl + << "(array). For \033[1mbool\033[0m members absent means \033[1mfalse\033[0m. For \033[1mvector<>\033[0m members absent means" << ::std::endl + << "empty. An empty top-level array is always present." << ::std::endl + << ::std::endl + << "For example, the following JSON text is a possible serialization of the above" << ::std::endl + << "\033[1mstruct\033[0m \033[1mconfiguration\033[0m:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"id\": 1," << ::std::endl + << " \"path\": \"/tmp/hello-gcc\"" << ::std::endl + << "}" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/common-options.hxx b/bpkg/common-options.hxx new file mode 100644 index 0000000..6b4d1a8 --- /dev/null +++ b/bpkg/common-options.hxx @@ -0,0 +1,1137 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_COMMON_OPTIONS_HXX +#define BPKG_COMMON_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <list> +#include <deque> +#include <vector> +#include <iosfwd> +#include <string> +#include <cstddef> +#include <exception> + +#ifndef CLI_POTENTIALLY_UNUSED +# if defined(_MSC_VER) || defined(__xlC__) +# define CLI_POTENTIALLY_UNUSED(x) (void*)&x +# else +# define CLI_POTENTIALLY_UNUSED(x) (void)x +# endif +#endif + +namespace bpkg +{ + namespace cli + { + class usage_para + { + public: + enum value + { + none, + text, + option + }; + + usage_para (value); + + operator value () const + { + return v_; + } + + private: + value v_; + }; + + class unknown_mode + { + public: + enum value + { + skip, + stop, + fail + }; + + unknown_mode (value); + + operator value () const + { + return v_; + } + + private: + value v_; + }; + + // Exceptions. + // + + class exception: public std::exception + { + public: + virtual void + print (::std::ostream&) const = 0; + }; + + ::std::ostream& + operator<< (::std::ostream&, const exception&); + + class unknown_option: public exception + { + public: + virtual + ~unknown_option () throw (); + + unknown_option (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + }; + + class unknown_argument: public exception + { + public: + virtual + ~unknown_argument () throw (); + + unknown_argument (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string argument_; + }; + + class missing_value: public exception + { + public: + virtual + ~missing_value () throw (); + + missing_value (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + }; + + class invalid_value: public exception + { + public: + virtual + ~invalid_value () throw (); + + invalid_value (const std::string& option, + const std::string& value, + const std::string& message = std::string ()); + + const std::string& + option () const; + + const std::string& + value () const; + + const std::string& + message () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string option_; + std::string value_; + std::string message_; + }; + + class eos_reached: public exception + { + public: + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + }; + + class file_io_failure: public exception + { + public: + virtual + ~file_io_failure () throw (); + + file_io_failure (const std::string& file); + + const std::string& + file () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string file_; + }; + + class unmatched_quote: public exception + { + public: + virtual + ~unmatched_quote () throw (); + + unmatched_quote (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string argument_; + }; + + class unexpected_group: public exception + { + public: + virtual + ~unexpected_group () throw (); + + unexpected_group (const std::string& argument, + const std::string& group); + + const std::string& + argument () const; + + const std::string& + group () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string argument_; + std::string group_; + }; + + class group_separator: public exception + { + public: + virtual + ~group_separator () throw (); + + // Note: either (but not both) can be empty. + // + group_separator (const std::string& encountered, + const std::string& expected); + + const std::string& + encountered () const; + + const std::string& + expected () const; + + virtual void + print (std::ostream&) const; + + virtual const char* + what () const throw (); + + private: + std::string encountered_; + std::string expected_; + }; + + // Command line argument scanner interface. + // + // The values returned by next() are guaranteed to be valid + // for the two previous arguments up until a call to a third + // peek() or next(). + // + // The position() function returns a monotonically-increasing + // number which, if stored, can later be used to determine the + // relative position of the argument returned by the following + // call to next(). Note that if multiple scanners are used to + // extract arguments from multiple sources, then the end + // position of the previous scanner should be used as the + // start position of the next. + // + class scanner + { + public: + virtual + ~scanner (); + + virtual bool + more () = 0; + + virtual const char* + peek () = 0; + + virtual const char* + next () = 0; + + virtual void + skip () = 0; + + virtual std::size_t + position () = 0; + }; + + class argv_scanner: public scanner + { + public: + argv_scanner (int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + argv_scanner (int start, + int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + int + end () const; + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + protected: + std::size_t start_position_; + int i_; + int& argc_; + char** argv_; + bool erase_; + }; + + class vector_scanner: public scanner + { + public: + vector_scanner (const std::vector<std::string>&, + std::size_t start = 0, + std::size_t start_position = 0); + + std::size_t + end () const; + + void + reset (std::size_t start = 0, std::size_t start_position = 0); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + private: + std::size_t start_position_; + const std::vector<std::string>& v_; + std::size_t i_; + }; + + class argv_file_scanner: public argv_scanner + { + public: + argv_file_scanner (int& argc, + char** argv, + const std::string& option, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (int start, + int& argc, + char** argv, + const std::string& option, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (const std::string& file, + const std::string& option, + std::size_t start_position = 0); + + struct option_info + { + // If search_func is not NULL, it is called, with the arg + // value as the second argument, to locate the options file. + // If it returns an empty string, then the file is ignored. + // + const char* option; + std::string (*search_func) (const char*, void* arg); + void* arg; + }; + + argv_file_scanner (int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (int start, + int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase = false, + std::size_t start_position = 0); + + argv_file_scanner (const std::string& file, + const option_info* options = 0, + std::size_t options_count = 0, + std::size_t start_position = 0); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + // Return the file path if the peeked at argument came from a file and + // the empty string otherwise. The reference is guaranteed to be valid + // till the end of the scanner lifetime. + // + const std::string& + peek_file (); + + // Return the 1-based line number if the peeked at argument came from + // a file and zero otherwise. + // + std::size_t + peek_line (); + + private: + const option_info* + find (const char*) const; + + void + load (const std::string& file); + + typedef argv_scanner base; + + const std::string option_; + option_info option_info_; + const option_info* options_; + std::size_t options_count_; + + struct arg + { + std::string value; + const std::string* file; + std::size_t line; + }; + + std::deque<arg> args_; + std::list<std::string> files_; + + // Circular buffer of two arguments. + // + std::string hold_[2]; + std::size_t i_; + + bool skip_; + + static int zero_argc_; + static std::string empty_string_; + }; + + class group_scanner: public scanner + { + public: + group_scanner (scanner&); + + virtual bool + more (); + + virtual const char* + peek (); + + virtual const char* + next (); + + virtual void + skip (); + + virtual std::size_t + position (); + + // The group is only available after the call to next() + // (and skip() -- in case one needs to make sure the group + // was empty, or some such) and is only valid (and must be + // handled) until the next call to any of the scanner + // functions (including more()). + // + // Note also that argument positions within each group start + // from 0. + // + scanner& + group (); + + // Escape an argument that is a group separator. Return the + // passed string if no escaping is required. + // + static const char* + escape (const char*); + + private: + enum state + { + peeked, // Argument peeked at with peek(). + scanned, // Argument scanned with next(). + skipped, // Argument skipped with skip()/initial. + }; + + enum separator + { + none, + open, // { + close, // } + open_plus, // +{ + close_plus // }+ + }; + + static separator + sense (const char*); + + // Scan the leading groups, the next argument/argument pack, + // and the trailing groups. + // + void + scan_group (); + + scanner& scan_; + state state_; + + // Circular buffer of two arguments. + // + std::vector<std::string> arg_[2]; + std::size_t i_, j_, pos_; + + std::vector<std::string> group_; + vector_scanner group_scan_; + }; + + template <typename X> + struct parser; + } +} + +#include <set> + +#include <bpkg/types.hxx> + +#include <bpkg/options-types.hxx> + +namespace bpkg +{ + class common_options + { + public: + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const common_options&); + + // Option accessors and modifiers. + // + const bool& + v () const; + + bool& + v (); + + void + v (const bool&); + + const bool& + V () const; + + bool& + V (); + + void + V (const bool&); + + const bool& + quiet () const; + + bool& + quiet (); + + void + quiet (const bool&); + + const uint16_t& + verbose () const; + + uint16_t& + verbose (); + + void + verbose (const uint16_t&); + + bool + verbose_specified () const; + + void + verbose_specified (bool); + + const bpkg::stdout_format& + stdout_format () const; + + bpkg::stdout_format& + stdout_format (); + + void + stdout_format (const bpkg::stdout_format&); + + bool + stdout_format_specified () const; + + void + stdout_format_specified (bool); + + const size_t& + jobs () const; + + size_t& + jobs (); + + void + jobs (const size_t&); + + bool + jobs_specified () const; + + void + jobs_specified (bool); + + const bool& + no_result () const; + + bool& + no_result (); + + void + no_result (const bool&); + + const bool& + progress () const; + + bool& + progress (); + + void + progress (const bool&); + + const bool& + no_progress () const; + + bool& + no_progress (); + + void + no_progress (const bool&); + + const path& + build () const; + + path& + build (); + + void + build (const path&); + + bool + build_specified () const; + + void + build_specified (bool); + + const strings& + build_option () const; + + strings& + build_option (); + + void + build_option (const strings&); + + bool + build_option_specified () const; + + void + build_option_specified (bool); + + const path& + fetch () const; + + path& + fetch (); + + void + fetch (const path&); + + bool + fetch_specified () const; + + void + fetch_specified (bool); + + const strings& + fetch_option () const; + + strings& + fetch_option (); + + void + fetch_option (const strings&); + + bool + fetch_option_specified () const; + + void + fetch_option_specified (bool); + + const size_t& + fetch_timeout () const; + + size_t& + fetch_timeout (); + + void + fetch_timeout (const size_t&); + + bool + fetch_timeout_specified () const; + + void + fetch_timeout_specified (bool); + + const butl::url& + pkg_proxy () const; + + butl::url& + pkg_proxy (); + + void + pkg_proxy (const butl::url&); + + bool + pkg_proxy_specified () const; + + void + pkg_proxy_specified (bool); + + const path& + git () const; + + path& + git (); + + void + git (const path&); + + bool + git_specified () const; + + void + git_specified (bool); + + const strings& + git_option () const; + + strings& + git_option (); + + void + git_option (const strings&); + + bool + git_option_specified () const; + + void + git_option_specified (bool); + + const path& + sha256 () const; + + path& + sha256 (); + + void + sha256 (const path&); + + bool + sha256_specified () const; + + void + sha256_specified (bool); + + const strings& + sha256_option () const; + + strings& + sha256_option (); + + void + sha256_option (const strings&); + + bool + sha256_option_specified () const; + + void + sha256_option_specified (bool); + + const path& + tar () const; + + path& + tar (); + + void + tar (const path&); + + bool + tar_specified () const; + + void + tar_specified (bool); + + const strings& + tar_option () const; + + strings& + tar_option (); + + void + tar_option (const strings&); + + bool + tar_option_specified () const; + + void + tar_option_specified (bool); + + const qualified_option<openssl_commands, path>& + openssl () const; + + qualified_option<openssl_commands, path>& + openssl (); + + void + openssl (const qualified_option<openssl_commands, path>&); + + bool + openssl_specified () const; + + void + openssl_specified (bool); + + const qualified_option<openssl_commands, strings>& + openssl_option () const; + + qualified_option<openssl_commands, strings>& + openssl_option (); + + void + openssl_option (const qualified_option<openssl_commands, strings>&); + + bool + openssl_option_specified () const; + + void + openssl_option_specified (bool); + + const bpkg::auth& + auth () const; + + bpkg::auth& + auth (); + + void + auth (const bpkg::auth&); + + bool + auth_specified () const; + + void + auth_specified (bool); + + const std::set<string, icase_compare_string>& + trust () const; + + std::set<string, icase_compare_string>& + trust (); + + void + trust (const std::set<string, icase_compare_string>&); + + bool + trust_specified () const; + + void + trust_specified (bool); + + const bool& + trust_yes () const; + + bool& + trust_yes (); + + void + trust_yes (const bool&); + + const bool& + trust_no () const; + + bool& + trust_no (); + + void + trust_no (const bool&); + + const string& + pager () const; + + string& + pager (); + + void + pager (const string&); + + bool + pager_specified () const; + + void + pager_specified (bool); + + const strings& + pager_option () const; + + strings& + pager_option (); + + void + pager_option (const strings&); + + bool + pager_option_specified () const; + + void + pager_option_specified (bool); + + const string& + options_file () const; + + string& + options_file (); + + void + options_file (const string&); + + bool + options_file_specified () const; + + void + options_file_specified (bool); + + const dir_path& + default_options () const; + + dir_path& + default_options (); + + void + default_options (const dir_path&); + + bool + default_options_specified () const; + + void + default_options_specified (bool); + + const bool& + no_default_options () const; + + bool& + no_default_options (); + + void + no_default_options (const bool&); + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + static ::bpkg::cli::usage_para + print_long_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + common_options (); + + bool + _parse (const char*, ::bpkg::cli::scanner&); + + public: + bool v_; + bool V_; + bool quiet_; + uint16_t verbose_; + bool verbose_specified_; + bpkg::stdout_format stdout_format_; + bool stdout_format_specified_; + size_t jobs_; + bool jobs_specified_; + bool no_result_; + bool progress_; + bool no_progress_; + path build_; + bool build_specified_; + strings build_option_; + bool build_option_specified_; + path fetch_; + bool fetch_specified_; + strings fetch_option_; + bool fetch_option_specified_; + size_t fetch_timeout_; + bool fetch_timeout_specified_; + butl::url pkg_proxy_; + bool pkg_proxy_specified_; + path git_; + bool git_specified_; + strings git_option_; + bool git_option_specified_; + path sha256_; + bool sha256_specified_; + strings sha256_option_; + bool sha256_option_specified_; + path tar_; + bool tar_specified_; + strings tar_option_; + bool tar_option_specified_; + qualified_option<openssl_commands, path> openssl_; + bool openssl_specified_; + qualified_option<openssl_commands, strings> openssl_option_; + bool openssl_option_specified_; + bpkg::auth auth_; + bool auth_specified_; + std::set<string, icase_compare_string> trust_; + bool trust_specified_; + bool trust_yes_; + bool trust_no_; + string pager_; + bool pager_specified_; + strings pager_option_; + bool pager_option_specified_; + string options_file_; + bool options_file_specified_; + dir_path default_options_; + bool default_options_specified_; + bool no_default_options_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_common_options_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + ::bpkg::cli::usage_para + print_bpkg_common_options_long_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/common-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_COMMON_OPTIONS_HXX diff --git a/bpkg/common-options.ixx b/bpkg/common-options.ixx new file mode 100644 index 0000000..b9eae20 --- /dev/null +++ b/bpkg/common-options.ixx @@ -0,0 +1,1262 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +#include <cassert> + +namespace bpkg +{ + namespace cli + { + // usage_para + // + inline usage_para:: + usage_para (value v) + : v_ (v) + { + } + + // unknown_mode + // + inline unknown_mode:: + unknown_mode (value v) + : v_ (v) + { + } + + // exception + // + inline ::std::ostream& + operator<< (::std::ostream& os, const exception& e) + { + e.print (os); + return os; + } + + // unknown_option + // + inline unknown_option:: + unknown_option (const std::string& option) + : option_ (option) + { + } + + inline const std::string& unknown_option:: + option () const + { + return option_; + } + + // unknown_argument + // + inline unknown_argument:: + unknown_argument (const std::string& argument) + : argument_ (argument) + { + } + + inline const std::string& unknown_argument:: + argument () const + { + return argument_; + } + + // missing_value + // + inline missing_value:: + missing_value (const std::string& option) + : option_ (option) + { + } + + inline const std::string& missing_value:: + option () const + { + return option_; + } + + // invalid_value + // + inline invalid_value:: + invalid_value (const std::string& option, + const std::string& value, + const std::string& message) + : option_ (option), + value_ (value), + message_ (message) + { + } + + inline const std::string& invalid_value:: + option () const + { + return option_; + } + + inline const std::string& invalid_value:: + value () const + { + return value_; + } + + inline const std::string& invalid_value:: + message () const + { + return message_; + } + + // file_io_failure + // + inline file_io_failure:: + file_io_failure (const std::string& file) + : file_ (file) + { + } + + inline const std::string& file_io_failure:: + file () const + { + return file_; + } + + // unmatched_quote + // + inline unmatched_quote:: + unmatched_quote (const std::string& argument) + : argument_ (argument) + { + } + + inline const std::string& unmatched_quote:: + argument () const + { + return argument_; + } + + // unexpected_group + // + inline unexpected_group:: + unexpected_group (const std::string& argument, + const std::string& group) + : argument_ (argument), group_ (group) + { + } + + inline const std::string& unexpected_group:: + argument () const + { + return argument_; + } + + inline const std::string& unexpected_group:: + group () const + { + return group_; + } + + // group_separator + // + inline group_separator:: + group_separator (const std::string& encountered, + const std::string& expected) + : encountered_ (encountered), expected_ (expected) + { + } + + inline const std::string& group_separator:: + encountered () const + { + return encountered_; + } + + inline const std::string& group_separator:: + expected () const + { + return expected_; + } + + // argv_scanner + // + inline argv_scanner:: + argv_scanner (int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + 1), + i_ (1), + argc_ (argc), + argv_ (argv), + erase_ (erase) + { + } + + inline argv_scanner:: + argv_scanner (int start, + int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + static_cast<std::size_t> (start)), + i_ (start), + argc_ (argc), + argv_ (argv), + erase_ (erase) + { + } + + inline int argv_scanner:: + end () const + { + return i_; + } + + // vector_scanner + // + inline vector_scanner:: + vector_scanner (const std::vector<std::string>& v, + std::size_t i, + std::size_t sp) + : start_position_ (sp), v_ (v), i_ (i) + { + } + + inline std::size_t vector_scanner:: + end () const + { + return i_; + } + + inline void vector_scanner:: + reset (std::size_t i, std::size_t sp) + { + i_ = i; + start_position_ = sp; + } + + // argv_file_scanner + // + inline argv_file_scanner:: + argv_file_scanner (int& argc, + char** argv, + const std::string& option, + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), + option_ (option), + options_ (&option_info_), + options_count_ (1), + i_ (1), + skip_ (false) + { + option_info_.option = option_.c_str (); + option_info_.search_func = 0; + } + + inline argv_file_scanner:: + argv_file_scanner (int start, + int& argc, + char** argv, + const std::string& option, + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), + option_ (option), + options_ (&option_info_), + options_count_ (1), + i_ (1), + skip_ (false) + { + option_info_.option = option_.c_str (); + option_info_.search_func = 0; + } + + inline argv_file_scanner:: + argv_file_scanner (const std::string& file, + const std::string& option, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), + option_ (option), + options_ (&option_info_), + options_count_ (1), + i_ (1), + skip_ (false) + { + option_info_.option = option_.c_str (); + option_info_.search_func = 0; + + load (file); + } + + inline argv_file_scanner:: + argv_file_scanner (int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), + options_ (options), + options_count_ (options_count), + i_ (1), + skip_ (false) + { + } + + inline argv_file_scanner:: + argv_file_scanner (int start, + int& argc, + char** argv, + const option_info* options, + std::size_t options_count, + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), + options_ (options), + options_count_ (options_count), + i_ (1), + skip_ (false) + { + } + + inline argv_file_scanner:: + argv_file_scanner (const std::string& file, + const option_info* options, + std::size_t options_count, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), + options_ (options), + options_count_ (options_count), + i_ (1), + skip_ (false) + { + load (file); + } + + // group_scanner + // + inline group_scanner:: + group_scanner (scanner& s) + : scan_ (s), state_ (skipped), i_ (1), j_ (0), group_scan_ (group_) + { + } + + inline scanner& group_scanner:: + group () + { + assert (state_ == scanned || state_ == skipped); + return group_scan_; + } + + inline const char* group_scanner:: + escape (const char* a) + { + switch (sense (a)) + { + case separator::none: break; + case separator::open: return "\\{"; + case separator::close: return "\\}"; + case separator::open_plus: return "\\+{"; + case separator::close_plus: return "\\}+"; + } + + return a; + } + + inline group_scanner::separator group_scanner:: + sense (const char* s) + { + switch (s[0]) + { + case '{': return s[1] == '\0' ? open : none; + case '}': + { + switch (s[1]) + { + case '+': return s[2] == '\0' ? close_plus : none; + default: return s[1] == '\0' ? close : none; + } + } + case '+': + { + switch (s[1]) + { + case '{': return s[2] == '\0' ? open_plus : none; + default: return none; + } + } + } + + return none; + } + } +} + +namespace bpkg +{ + // common_options + // + + inline const bool& common_options:: + v () const + { + return this->v_; + } + + inline bool& common_options:: + v () + { + return this->v_; + } + + inline void common_options:: + v (const bool& x) + { + this->v_ = x; + } + + inline const bool& common_options:: + V () const + { + return this->V_; + } + + inline bool& common_options:: + V () + { + return this->V_; + } + + inline void common_options:: + V (const bool& x) + { + this->V_ = x; + } + + inline const bool& common_options:: + quiet () const + { + return this->quiet_; + } + + inline bool& common_options:: + quiet () + { + return this->quiet_; + } + + inline void common_options:: + quiet (const bool& x) + { + this->quiet_ = x; + } + + inline const uint16_t& common_options:: + verbose () const + { + return this->verbose_; + } + + inline uint16_t& common_options:: + verbose () + { + return this->verbose_; + } + + inline void common_options:: + verbose (const uint16_t& x) + { + this->verbose_ = x; + } + + inline bool common_options:: + verbose_specified () const + { + return this->verbose_specified_; + } + + inline void common_options:: + verbose_specified (bool x) + { + this->verbose_specified_ = x; + } + + inline const bpkg::stdout_format& common_options:: + stdout_format () const + { + return this->stdout_format_; + } + + inline bpkg::stdout_format& common_options:: + stdout_format () + { + return this->stdout_format_; + } + + inline void common_options:: + stdout_format (const bpkg::stdout_format& x) + { + this->stdout_format_ = x; + } + + inline bool common_options:: + stdout_format_specified () const + { + return this->stdout_format_specified_; + } + + inline void common_options:: + stdout_format_specified (bool x) + { + this->stdout_format_specified_ = x; + } + + inline const size_t& common_options:: + jobs () const + { + return this->jobs_; + } + + inline size_t& common_options:: + jobs () + { + return this->jobs_; + } + + inline void common_options:: + jobs (const size_t& x) + { + this->jobs_ = x; + } + + inline bool common_options:: + jobs_specified () const + { + return this->jobs_specified_; + } + + inline void common_options:: + jobs_specified (bool x) + { + this->jobs_specified_ = x; + } + + inline const bool& common_options:: + no_result () const + { + return this->no_result_; + } + + inline bool& common_options:: + no_result () + { + return this->no_result_; + } + + inline void common_options:: + no_result (const bool& x) + { + this->no_result_ = x; + } + + inline const bool& common_options:: + progress () const + { + return this->progress_; + } + + inline bool& common_options:: + progress () + { + return this->progress_; + } + + inline void common_options:: + progress (const bool& x) + { + this->progress_ = x; + } + + inline const bool& common_options:: + no_progress () const + { + return this->no_progress_; + } + + inline bool& common_options:: + no_progress () + { + return this->no_progress_; + } + + inline void common_options:: + no_progress (const bool& x) + { + this->no_progress_ = x; + } + + inline const path& common_options:: + build () const + { + return this->build_; + } + + inline path& common_options:: + build () + { + return this->build_; + } + + inline void common_options:: + build (const path& x) + { + this->build_ = x; + } + + inline bool common_options:: + build_specified () const + { + return this->build_specified_; + } + + inline void common_options:: + build_specified (bool x) + { + this->build_specified_ = x; + } + + inline const strings& common_options:: + build_option () const + { + return this->build_option_; + } + + inline strings& common_options:: + build_option () + { + return this->build_option_; + } + + inline void common_options:: + build_option (const strings& x) + { + this->build_option_ = x; + } + + inline bool common_options:: + build_option_specified () const + { + return this->build_option_specified_; + } + + inline void common_options:: + build_option_specified (bool x) + { + this->build_option_specified_ = x; + } + + inline const path& common_options:: + fetch () const + { + return this->fetch_; + } + + inline path& common_options:: + fetch () + { + return this->fetch_; + } + + inline void common_options:: + fetch (const path& x) + { + this->fetch_ = x; + } + + inline bool common_options:: + fetch_specified () const + { + return this->fetch_specified_; + } + + inline void common_options:: + fetch_specified (bool x) + { + this->fetch_specified_ = x; + } + + inline const strings& common_options:: + fetch_option () const + { + return this->fetch_option_; + } + + inline strings& common_options:: + fetch_option () + { + return this->fetch_option_; + } + + inline void common_options:: + fetch_option (const strings& x) + { + this->fetch_option_ = x; + } + + inline bool common_options:: + fetch_option_specified () const + { + return this->fetch_option_specified_; + } + + inline void common_options:: + fetch_option_specified (bool x) + { + this->fetch_option_specified_ = x; + } + + inline const size_t& common_options:: + fetch_timeout () const + { + return this->fetch_timeout_; + } + + inline size_t& common_options:: + fetch_timeout () + { + return this->fetch_timeout_; + } + + inline void common_options:: + fetch_timeout (const size_t& x) + { + this->fetch_timeout_ = x; + } + + inline bool common_options:: + fetch_timeout_specified () const + { + return this->fetch_timeout_specified_; + } + + inline void common_options:: + fetch_timeout_specified (bool x) + { + this->fetch_timeout_specified_ = x; + } + + inline const butl::url& common_options:: + pkg_proxy () const + { + return this->pkg_proxy_; + } + + inline butl::url& common_options:: + pkg_proxy () + { + return this->pkg_proxy_; + } + + inline void common_options:: + pkg_proxy (const butl::url& x) + { + this->pkg_proxy_ = x; + } + + inline bool common_options:: + pkg_proxy_specified () const + { + return this->pkg_proxy_specified_; + } + + inline void common_options:: + pkg_proxy_specified (bool x) + { + this->pkg_proxy_specified_ = x; + } + + inline const path& common_options:: + git () const + { + return this->git_; + } + + inline path& common_options:: + git () + { + return this->git_; + } + + inline void common_options:: + git (const path& x) + { + this->git_ = x; + } + + inline bool common_options:: + git_specified () const + { + return this->git_specified_; + } + + inline void common_options:: + git_specified (bool x) + { + this->git_specified_ = x; + } + + inline const strings& common_options:: + git_option () const + { + return this->git_option_; + } + + inline strings& common_options:: + git_option () + { + return this->git_option_; + } + + inline void common_options:: + git_option (const strings& x) + { + this->git_option_ = x; + } + + inline bool common_options:: + git_option_specified () const + { + return this->git_option_specified_; + } + + inline void common_options:: + git_option_specified (bool x) + { + this->git_option_specified_ = x; + } + + inline const path& common_options:: + sha256 () const + { + return this->sha256_; + } + + inline path& common_options:: + sha256 () + { + return this->sha256_; + } + + inline void common_options:: + sha256 (const path& x) + { + this->sha256_ = x; + } + + inline bool common_options:: + sha256_specified () const + { + return this->sha256_specified_; + } + + inline void common_options:: + sha256_specified (bool x) + { + this->sha256_specified_ = x; + } + + inline const strings& common_options:: + sha256_option () const + { + return this->sha256_option_; + } + + inline strings& common_options:: + sha256_option () + { + return this->sha256_option_; + } + + inline void common_options:: + sha256_option (const strings& x) + { + this->sha256_option_ = x; + } + + inline bool common_options:: + sha256_option_specified () const + { + return this->sha256_option_specified_; + } + + inline void common_options:: + sha256_option_specified (bool x) + { + this->sha256_option_specified_ = x; + } + + inline const path& common_options:: + tar () const + { + return this->tar_; + } + + inline path& common_options:: + tar () + { + return this->tar_; + } + + inline void common_options:: + tar (const path& x) + { + this->tar_ = x; + } + + inline bool common_options:: + tar_specified () const + { + return this->tar_specified_; + } + + inline void common_options:: + tar_specified (bool x) + { + this->tar_specified_ = x; + } + + inline const strings& common_options:: + tar_option () const + { + return this->tar_option_; + } + + inline strings& common_options:: + tar_option () + { + return this->tar_option_; + } + + inline void common_options:: + tar_option (const strings& x) + { + this->tar_option_ = x; + } + + inline bool common_options:: + tar_option_specified () const + { + return this->tar_option_specified_; + } + + inline void common_options:: + tar_option_specified (bool x) + { + this->tar_option_specified_ = x; + } + + inline const qualified_option<openssl_commands, path>& common_options:: + openssl () const + { + return this->openssl_; + } + + inline qualified_option<openssl_commands, path>& common_options:: + openssl () + { + return this->openssl_; + } + + inline void common_options:: + openssl (const qualified_option<openssl_commands, path>& x) + { + this->openssl_ = x; + } + + inline bool common_options:: + openssl_specified () const + { + return this->openssl_specified_; + } + + inline void common_options:: + openssl_specified (bool x) + { + this->openssl_specified_ = x; + } + + inline const qualified_option<openssl_commands, strings>& common_options:: + openssl_option () const + { + return this->openssl_option_; + } + + inline qualified_option<openssl_commands, strings>& common_options:: + openssl_option () + { + return this->openssl_option_; + } + + inline void common_options:: + openssl_option (const qualified_option<openssl_commands, strings>& x) + { + this->openssl_option_ = x; + } + + inline bool common_options:: + openssl_option_specified () const + { + return this->openssl_option_specified_; + } + + inline void common_options:: + openssl_option_specified (bool x) + { + this->openssl_option_specified_ = x; + } + + inline const bpkg::auth& common_options:: + auth () const + { + return this->auth_; + } + + inline bpkg::auth& common_options:: + auth () + { + return this->auth_; + } + + inline void common_options:: + auth (const bpkg::auth& x) + { + this->auth_ = x; + } + + inline bool common_options:: + auth_specified () const + { + return this->auth_specified_; + } + + inline void common_options:: + auth_specified (bool x) + { + this->auth_specified_ = x; + } + + inline const std::set<string, icase_compare_string>& common_options:: + trust () const + { + return this->trust_; + } + + inline std::set<string, icase_compare_string>& common_options:: + trust () + { + return this->trust_; + } + + inline void common_options:: + trust (const std::set<string, icase_compare_string>& x) + { + this->trust_ = x; + } + + inline bool common_options:: + trust_specified () const + { + return this->trust_specified_; + } + + inline void common_options:: + trust_specified (bool x) + { + this->trust_specified_ = x; + } + + inline const bool& common_options:: + trust_yes () const + { + return this->trust_yes_; + } + + inline bool& common_options:: + trust_yes () + { + return this->trust_yes_; + } + + inline void common_options:: + trust_yes (const bool& x) + { + this->trust_yes_ = x; + } + + inline const bool& common_options:: + trust_no () const + { + return this->trust_no_; + } + + inline bool& common_options:: + trust_no () + { + return this->trust_no_; + } + + inline void common_options:: + trust_no (const bool& x) + { + this->trust_no_ = x; + } + + inline const string& common_options:: + pager () const + { + return this->pager_; + } + + inline string& common_options:: + pager () + { + return this->pager_; + } + + inline void common_options:: + pager (const string& x) + { + this->pager_ = x; + } + + inline bool common_options:: + pager_specified () const + { + return this->pager_specified_; + } + + inline void common_options:: + pager_specified (bool x) + { + this->pager_specified_ = x; + } + + inline const strings& common_options:: + pager_option () const + { + return this->pager_option_; + } + + inline strings& common_options:: + pager_option () + { + return this->pager_option_; + } + + inline void common_options:: + pager_option (const strings& x) + { + this->pager_option_ = x; + } + + inline bool common_options:: + pager_option_specified () const + { + return this->pager_option_specified_; + } + + inline void common_options:: + pager_option_specified (bool x) + { + this->pager_option_specified_ = x; + } + + inline const string& common_options:: + options_file () const + { + return this->options_file_; + } + + inline string& common_options:: + options_file () + { + return this->options_file_; + } + + inline void common_options:: + options_file (const string& x) + { + this->options_file_ = x; + } + + inline bool common_options:: + options_file_specified () const + { + return this->options_file_specified_; + } + + inline void common_options:: + options_file_specified (bool x) + { + this->options_file_specified_ = x; + } + + inline const dir_path& common_options:: + default_options () const + { + return this->default_options_; + } + + inline dir_path& common_options:: + default_options () + { + return this->default_options_; + } + + inline void common_options:: + default_options (const dir_path& x) + { + this->default_options_ = x; + } + + inline bool common_options:: + default_options_specified () const + { + return this->default_options_specified_; + } + + inline void common_options:: + default_options_specified (bool x) + { + this->default_options_specified_ = x; + } + + inline const bool& common_options:: + no_default_options () const + { + return this->no_default_options_; + } + + inline bool& common_options:: + no_default_options () + { + return this->no_default_options_; + } + + inline void common_options:: + no_default_options (const bool& x) + { + this->no_default_options_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/configuration-options.cxx b/bpkg/configuration-options.cxx new file mode 100644 index 0000000..de581d0 --- /dev/null +++ b/bpkg/configuration-options.cxx @@ -0,0 +1,564 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // configuration_options + // + + configuration_options:: + configuration_options () + : directory_ ("."), + directory_specified_ (false) + { + } + + bool configuration_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool configuration_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool configuration_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool configuration_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool configuration_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void configuration_options:: + merge (const configuration_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.directory_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->directory_, a.directory_); + this->directory_specified_ = true; + } + } + + ::bpkg::cli::usage_para configuration_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mdir\033[0m Assume configuration is in \033[4mdir\033[0m rather than in the" << ::std::endl + << " current working directory." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + // common_options base + // + p = ::bpkg::common_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (configuration_options&, ::bpkg::cli::scanner&)> + _cli_configuration_options_map; + + static _cli_configuration_options_map _cli_configuration_options_map_; + + struct _cli_configuration_options_map_init + { + _cli_configuration_options_map_init () + { + _cli_configuration_options_map_["--directory"] = + &::bpkg::cli::thunk< configuration_options, dir_path, &configuration_options::directory_, + &configuration_options::directory_specified_ >; + _cli_configuration_options_map_["-d"] = + &::bpkg::cli::thunk< configuration_options, dir_path, &configuration_options::directory_, + &configuration_options::directory_specified_ >; + } + }; + + static _cli_configuration_options_map_init _cli_configuration_options_map_init_; + + bool configuration_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_configuration_options_map::const_iterator i (_cli_configuration_options_map_.find (o)); + + if (i != _cli_configuration_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool configuration_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_configuration_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/configuration-options.hxx b/bpkg/configuration-options.hxx new file mode 100644 index 0000000..d7a61db --- /dev/null +++ b/bpkg/configuration-options.hxx @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_CONFIGURATION_OPTIONS_HXX +#define BPKG_CONFIGURATION_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class configuration_options: public ::bpkg::common_options + { + public: + configuration_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const configuration_options&); + + // Option accessors. + // + const dir_path& + directory () const; + + bool + directory_specified () const; + + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + dir_path directory_; + bool directory_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_configuration_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/configuration-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_CONFIGURATION_OPTIONS_HXX diff --git a/bpkg/configuration-options.ixx b/bpkg/configuration-options.ixx new file mode 100644 index 0000000..294a431 --- /dev/null +++ b/bpkg/configuration-options.ixx @@ -0,0 +1,33 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // configuration_options + // + + inline const dir_path& configuration_options:: + directory () const + { + return this->directory_; + } + + inline bool configuration_options:: + directory_specified () const + { + return this->directory_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/default-options-files.cxx b/bpkg/default-options-files.cxx new file mode 100644 index 0000000..ccdc161 --- /dev/null +++ b/bpkg/default-options-files.cxx @@ -0,0 +1,92 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/default-options-files.hxx> + +#include <map> +#include <cstring> + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_default_options_files_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg\033[0m \033[4mcommand\033[0m [\033[4mmode-options\033[0m] ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "Instead of having a separate config file format for tool configuration, the" << ::std::endl + << "\033[1mbuild2\033[0m toolchain uses \033[4mdefault options files\033[0m which contain the same options as" << ::std::endl + << "what can be specified on the command line. The default options files are like" << ::std::endl + << "options files that one can specify with \033[1m--options-file\033[0m (\033[1mbpkg-common-options(1)\033[0m)" << ::std::endl + << "except that they are loaded by default." << ::std::endl + << ::std::endl + << "The default options files are searched for in the \033[1m.build2/\033[0m and \033[1m.build2/local/\033[0m" << ::std::endl + << "subdirectories of each outer directory beginning from the \033[4mstart directory\033[0m and" << ::std::endl + << "until reaching either the home directory or the filesystem root directory (both" << ::std::endl + << "excluding). Then in the \033[1m.build2/\033[0m subdirectory of the home directory and finally" << ::std::endl + << "in the system directory (for example, \033[1m/etc/build2/\033[0m) if configured." << ::std::endl + << ::std::endl + << "Once the search is complete, the files are loaded in the reverse order, that" << ::std::endl + << "is, beginning from the system directory (if any), followed by the home" << ::std::endl + << "directory, ending with the start directory, and finishing off with the options" << ::std::endl + << "specified on the command line. In other words, the files are loaded from the" << ::std::endl + << "more generic to the more specific with the command line options having the" << ::std::endl + << "ability to override any values specified in the default options files." << ::std::endl + << ::std::endl + << "The start directory, the names of the default options files, and in which order" << ::std::endl + << "they are loaded within each directory are determined by the \033[4mcommand\033[0m and" << ::std::endl + << "potentially its \033[4mmode-options\033[0m. See each command's DEFAULT OPTIONS FILES section" << ::std::endl + << "for details." << ::std::endl + << ::std::endl + << "If a default options file contains \033[1m--no-default-options\033[0m, then the search is" << ::std::endl + << "stopped at the directory containing this file and no outer files are loaded. If" << ::std::endl + << "this option is specified on the command line, then none of the default options" << ::std::endl + << "files are searched for or loaded." << ::std::endl + << ::std::endl + << "An additional directory containing default options files can be specified with" << ::std::endl + << "\033[1m--default-options\033[0m. If such a directory is a subdirectory of the start directory" << ::std::endl + << "or is between the start directory and the end of the outer search, then its" << ::std::endl + << "configuration files are loaded at the corresponding point in the directory" << ::std::endl + << "hierarchy. Otherwise, they are loaded after the home directory." << ::std::endl + << ::std::endl + << "The presence of the \033[1m.git\033[0m filesystem entry causes the default options files in" << ::std::endl + << "this directory and any of its subdirectories to be considered remote. Depending" << ::std::endl + << "on the command, some security-sensitive options may be disallowed or trigger a" << ::std::endl + << "prompt when specified in remote options files (in the current implementation" << ::std::endl + << "this is the case even for files from the \033[1m.build2/local/\033[0m subdirectory since the" << ::std::endl + << "mere location is not a sufficient ground to definitively conclude that the file" << ::std::endl + << "is not remote; to be sure we would need to query the version control system)." << ::std::endl + << "Note that additional default options files specified with \033[1m--default-options\033[0m are" << ::std::endl + << "never considered remote." << ::std::endl + << ::std::endl + << "The order in which default options files are loaded is traced at the verbosity" << ::std::endl + << "level 3 (\033[1m-V\033[0m option) or higher." << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/default-options-files.hxx b/bpkg/default-options-files.hxx new file mode 100644 index 0000000..a26c600 --- /dev/null +++ b/bpkg/default-options-files.hxx @@ -0,0 +1,31 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_DEFAULT_OPTIONS_FILES_HXX +#define BPKG_DEFAULT_OPTIONS_FILES_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_default_options_files_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_DEFAULT_OPTIONS_FILES_HXX diff --git a/bpkg/help-options.cxx b/bpkg/help-options.cxx new file mode 100644 index 0000000..419bfc1 --- /dev/null +++ b/bpkg/help-options.cxx @@ -0,0 +1,568 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +#include <bpkg/types-parsers.hxx> +// +// End prologue. + +#include <bpkg/help-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> + +namespace bpkg +{ + namespace cli + { + template <typename X> + struct parser + { + static void + parse (X& x, bool& xs, scanner& s) + { + using namespace std; + + const char* o (s.next ()); + if (s.more ()) + { + string v (s.next ()); + istringstream is (v); + if (!(is >> x && is.peek () == istringstream::traits_type::eof ())) + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (X& b, const X& a) + { + b = a; + } + }; + + template <> + struct parser<bool> + { + static void + parse (bool& x, scanner& s) + { + s.next (); + x = true; + } + + static void + merge (bool& b, const bool&) + { + b = true; + } + }; + + template <> + struct parser<std::string> + { + static void + parse (std::string& x, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + x = s.next (); + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::string& b, const std::string& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + + static void + merge (std::pair<X, std::size_t>& b, const std::pair<X, std::size_t>& a) + { + b = a; + } + }; + + template <typename X> + struct parser<std::vector<X> > + { + static void + parse (std::vector<X>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.push_back (x); + xs = true; + } + + static void + merge (std::vector<X>& b, const std::vector<X>& a) + { + b.insert (b.end (), a.begin (), a.end ()); + } + }; + + template <typename X, typename C> + struct parser<std::set<X, C> > + { + static void + parse (std::set<X, C>& c, bool& xs, scanner& s) + { + X x; + bool dummy; + parser<X>::parse (x, dummy, s); + c.insert (x); + xs = true; + } + + static void + merge (std::set<X, C>& b, const std::set<X, C>& a) + { + b.insert (a.begin (), a.end ()); + } + }; + + template <typename K, typename V, typename C> + struct parser<std::map<K, V, C> > + { + static void + parse (std::map<K, V, C>& m, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + std::size_t pos (s.position ()); + std::string ov (s.next ()); + std::string::size_type p = ov.find ('='); + + K k = K (); + V v = V (); + std::string kstr (ov, 0, p); + std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ())); + + int ac (2); + char* av[] = + { + const_cast<char*> (o), + 0 + }; + + bool dummy; + if (!kstr.empty ()) + { + av[1] = const_cast<char*> (kstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<K>::parse (k, dummy, s); + } + + if (!vstr.empty ()) + { + av[1] = const_cast<char*> (vstr.c_str ()); + argv_scanner s (0, ac, av, false, pos); + parser<V>::parse (v, dummy, s); + } + + m[k] = v; + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::map<K, V, C>& b, const std::map<K, V, C>& a) + { + for (typename std::map<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b[i->first] = i->second; + } + }; + + template <typename X, typename T, T X::*M> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, s); + } + + template <typename X, typename T, T X::*M, bool X::*S> + void + thunk (X& x, scanner& s) + { + parser<T>::parse (x.*M, x.*S, s); + } + } +} + +#include <map> +#include <cstring> + +namespace bpkg +{ + // help_options + // + + help_options:: + help_options () + { + } + + bool help_options:: + parse (int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool help_options:: + parse (int start, + int& argc, + char** argv, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + return r; + } + + bool help_options:: + parse (int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool help_options:: + parse (int start, + int& argc, + char** argv, + int& end, + bool erase, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + ::bpkg::cli::argv_scanner s (start, argc, argv, erase); + bool r = _parse (s, opt, arg); + end = s.end (); + return r; + } + + bool help_options:: + parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt, + ::bpkg::cli::unknown_mode arg) + { + bool r = _parse (s, opt, arg); + return r; + } + + void help_options:: + merge (const help_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + } + + ::bpkg::cli::usage_para help_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + // common_options base + // + p = ::bpkg::common_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (help_options&, ::bpkg::cli::scanner&)> + _cli_help_options_map; + + static _cli_help_options_map _cli_help_options_map_; + + struct _cli_help_options_map_init + { + _cli_help_options_map_init () + { + } + }; + + static _cli_help_options_map_init _cli_help_options_map_init_; + + bool help_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_help_options_map::const_iterator i (_cli_help_options_map_.find (o)); + + if (i != _cli_help_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool help_options:: + _parse (::bpkg::cli::scanner& s, + ::bpkg::cli::unknown_mode opt_mode, + ::bpkg::cli::unknown_mode arg_mode) + { + // Can't skip combined flags (--no-combined-flags). + // + assert (opt_mode != ::bpkg::cli::unknown_mode::skip); + + bool r = false; + bool opt = true; + + while (s.more ()) + { + const char* o = s.peek (); + + if (std::strcmp (o, "--") == 0) + { + opt = false; + } + + if (opt) + { + if (_parse (o, s)) + { + r = true; + continue; + } + + if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0') + { + // Handle combined option values. + // + std::string co; + if (const char* v = std::strchr (o, '=')) + { + co.assign (o, 0, v - o); + ++v; + + int ac (2); + char* av[] = + { + const_cast<char*> (co.c_str ()), + const_cast<char*> (v) + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (_parse (co.c_str (), ns)) + { + // Parsed the option but not its value? + // + if (ns.end () != 2) + throw ::bpkg::cli::invalid_value (co, v); + + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = co.c_str (); + } + } + + // Handle combined flags. + // + char cf[3]; + { + const char* p = o + 1; + for (; *p != '\0'; ++p) + { + if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9'))) + break; + } + + if (*p == '\0') + { + for (p = o + 1; *p != '\0'; ++p) + { + std::strcpy (cf, "-"); + cf[1] = *p; + cf[2] = '\0'; + + int ac (1); + char* av[] = + { + cf + }; + + ::bpkg::cli::argv_scanner ns (0, ac, av); + + if (!_parse (cf, ns)) + break; + } + + if (*p == '\0') + { + // All handled. + // + s.next (); + r = true; + continue; + } + else + { + // Set the unknown option and fall through. + // + o = cf; + } + } + } + + switch (opt_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_option (o); + } + } + + break; + } + } + + switch (arg_mode) + { + case ::bpkg::cli::unknown_mode::skip: + { + s.skip (); + r = true; + continue; + } + case ::bpkg::cli::unknown_mode::stop: + { + break; + } + case ::bpkg::cli::unknown_mode::fail: + { + throw ::bpkg::cli::unknown_argument (o); + } + } + + break; + } + + return r; + } +} + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_help_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSYNOPSIS\033[0m" << ::std::endl + << ::std::endl + << "\033[1mbpkg help\033[0m [\033[4mcommand\033[0m | \033[4mtopic\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "Show the detailed help for \033[4mcommand\033[0m or help \033[4mtopic\033[0m or a summary of available" << ::std::endl + << "commands and topics if none was specified." << ::std::endl; + + p = ::bpkg::help_options::print_usage (os, ::bpkg::cli::usage_para::text); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mDEFAULT OPTIONS FILES\033[0m" << ::std::endl + << ::std::endl + << "See \033[1mbpkg-default-options-files(1)\033[0m for an overview of the default options files." << ::std::endl + << "For the \033[1mhelp\033[0m command the following options files are searched for only in the" << ::std::endl + << "predefined directories (home, system, etc) and, if found, loaded in the order" << ::std::endl + << "listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-help.options" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/help-options.hxx b/bpkg/help-options.hxx new file mode 100644 index 0000000..9c67dee --- /dev/null +++ b/bpkg/help-options.hxx @@ -0,0 +1,109 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_HELP_OPTIONS_HXX +#define BPKG_HELP_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class help_options: public ::bpkg::common_options + { + public: + help_options (); + + // Return true if anything has been parsed. + // + bool + parse (int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (int start, + int& argc, + char** argv, + int& end, + bool erase = false, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + bool + parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option = ::bpkg::cli::unknown_mode::fail, + ::bpkg::cli::unknown_mode argument = ::bpkg::cli::unknown_mode::stop); + + // Merge options from the specified instance appending/overriding + // them as if they appeared after options in this instance. + // + void + merge (const help_options&); + + // Option accessors. + // + // Print usage information. + // + static ::bpkg::cli::usage_para + print_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); + + // Implementation details. + // + protected: + bool + _parse (const char*, ::bpkg::cli::scanner&); + + private: + bool + _parse (::bpkg::cli::scanner&, + ::bpkg::cli::unknown_mode option, + ::bpkg::cli::unknown_mode argument); + + public: + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_help_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/help-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_HELP_OPTIONS_HXX diff --git a/bpkg/help-options.ixx b/bpkg/help-options.ixx new file mode 100644 index 0000000..91f5bfd --- /dev/null +++ b/bpkg/help-options.ixx @@ -0,0 +1,21 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // help_options + // +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/package-odb.cxx b/bpkg/package-odb.cxx new file mode 100644 index 0000000..3eba050 --- /dev/null +++ b/bpkg/package-odb.cxx @@ -0,0 +1,17091 @@ +// -*- C++ -*- +// +// This file was generated by ODB, object-relational mapping (ORM) +// compiler for C++. +// + +#include <odb/pre.hxx> + +#include <bpkg/package-odb.hxx> + +#include <cassert> +#include <cstring> // std::memcpy + +#include <odb/schema-catalog-impl.hxx> + +#include <odb/sqlite/traits.hxx> +#include <odb/sqlite/database.hxx> +#include <odb/sqlite/transaction.hxx> +#include <odb/sqlite/connection.hxx> +#include <odb/sqlite/statement.hxx> +#include <odb/sqlite/statement-cache.hxx> +#include <odb/sqlite/simple-object-statements.hxx> +#include <odb/sqlite/view-statements.hxx> +#include <odb/sqlite/container-statements.hxx> +#include <odb/sqlite/exceptions.hxx> +#include <odb/sqlite/prepared-query.hxx> +#include <odb/sqlite/simple-object-result.hxx> +#include <odb/sqlite/view-result.hxx> + +namespace odb +{ + // _version + // + + bool access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // epoch + // + t[0UL] = false; + + // canonical_upstream + // + if (t[1UL]) + { + i.canonical_upstream_value.capacity (i.canonical_upstream_size); + grew = true; + } + + // canonical_release + // + if (t[2UL]) + { + i.canonical_release_value.capacity (i.canonical_release_size); + grew = true; + } + + // revision + // + t[3UL] = false; + + // iteration + // + t[4UL] = false; + + // upstream + // + if (t[5UL]) + { + i.upstream_value.capacity (i.upstream_size); + grew = true; + } + + // release + // + if (t[6UL]) + { + i.release_value.capacity (i.release_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // epoch + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.epoch_value; + b[n].is_null = &i.epoch_null; + n++; + + // canonical_upstream + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.canonical_upstream_value.data (); + b[n].size = &i.canonical_upstream_size; + b[n].capacity = i.canonical_upstream_value.capacity (); + b[n].is_null = &i.canonical_upstream_null; + n++; + + // canonical_release + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.canonical_release_value.data (); + b[n].size = &i.canonical_release_size; + b[n].capacity = i.canonical_release_value.capacity (); + b[n].is_null = &i.canonical_release_null; + n++; + + // revision + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.revision_value; + b[n].is_null = &i.revision_null; + n++; + + // iteration + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.iteration_value; + b[n].is_null = &i.iteration_null; + n++; + + // upstream + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.upstream_value.data (); + b[n].size = &i.upstream_size; + b[n].capacity = i.upstream_value.capacity (); + b[n].is_null = &i.upstream_null; + n++; + + // release + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.release_value.data (); + b[n].size = &i.release_size; + b[n].capacity = i.release_value.capacity (); + b[n].is_null = &i.release_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // epoch + // + { + ::uint16_t const& v = + o.epoch; + + bool is_null (false); + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_image ( + i.epoch_value, + is_null, + v); + i.epoch_null = is_null; + } + + // canonical_upstream + // + { + ::std::string const& v = + o.canonical_upstream; + + bool is_null (false); + std::size_t cap (i.canonical_upstream_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.canonical_upstream_value, + i.canonical_upstream_size, + is_null, + v); + i.canonical_upstream_null = is_null; + grew = grew || (cap != i.canonical_upstream_value.capacity ()); + } + + // canonical_release + // + { + ::std::string const& v = + o.canonical_release; + + bool is_null (false); + std::size_t cap (i.canonical_release_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.canonical_release_value, + i.canonical_release_size, + is_null, + v); + i.canonical_release_null = is_null; + grew = grew || (cap != i.canonical_release_value.capacity ()); + } + + // revision + // + { + ::butl::optional< short unsigned int > const& v = + o.revision; + + bool is_null (true); + sqlite::value_traits< + ::butl::optional< short unsigned int >, + sqlite::id_integer >::set_image ( + i.revision_value, + is_null, + v); + i.revision_null = is_null; + } + + // iteration + // + { + ::uint32_t const& v = + o.iteration; + + bool is_null (false); + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::set_image ( + i.iteration_value, + is_null, + v); + i.iteration_null = is_null; + } + + // upstream + // + { + ::std::string const& v = + o.upstream; + + bool is_null (false); + std::size_t cap (i.upstream_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.upstream_value, + i.upstream_size, + is_null, + v); + i.upstream_null = is_null; + grew = grew || (cap != i.upstream_value.capacity ()); + } + + // release + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.release; + + bool is_null (true); + std::size_t cap (i.release_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.release_value, + i.release_size, + is_null, + v); + i.release_null = is_null; + grew = grew || (cap != i.release_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // epoch + // + { + ::uint16_t& v = + o.epoch; + + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_value ( + v, + i.epoch_value, + i.epoch_null); + } + + // canonical_upstream + // + { + ::std::string& v = + o.canonical_upstream; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.canonical_upstream_value, + i.canonical_upstream_size, + i.canonical_upstream_null); + } + + // canonical_release + // + { + ::std::string& v = + o.canonical_release; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.canonical_release_value, + i.canonical_release_size, + i.canonical_release_null); + } + + // revision + // + { + ::butl::optional< short unsigned int >& v = + o.revision; + + sqlite::value_traits< + ::butl::optional< short unsigned int >, + sqlite::id_integer >::set_value ( + v, + i.revision_value, + i.revision_null); + } + + // iteration + // + { + ::uint32_t& v = + o.iteration; + + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::set_value ( + v, + i.iteration_value, + i.iteration_null); + } + + // upstream + // + { + ::std::string& v = + o.upstream; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.upstream_value, + i.upstream_size, + i.upstream_null); + } + + // release + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.release; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.release_value, + i.release_size, + i.release_null); + } + } + + // version_constraint + // + + bool access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // min_version + // + if (composite_value_traits< ::bpkg::_version, id_sqlite >::grow ( + i.min_version_value, t + 0UL)) + grew = true; + + // max_version + // + if (composite_value_traits< ::bpkg::_version, id_sqlite >::grow ( + i.max_version_value, t + 7UL)) + grew = true; + + // min_open + // + t[14UL] = false; + + // max_open + // + t[15UL] = false; + + return grew; + } + + void access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // min_version + // + composite_value_traits< ::bpkg::_version, id_sqlite >::bind ( + b + n, i.min_version_value, sk); + n += 7UL; + + // max_version + // + composite_value_traits< ::bpkg::_version, id_sqlite >::bind ( + b + n, i.max_version_value, sk); + n += 7UL; + + // min_open + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.min_open_value; + b[n].is_null = &i.min_open_null; + n++; + + // max_open + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.max_open_value; + b[n].is_null = &i.max_open_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // min_version + // + { + ::butl::optional< ::bpkg::version > const& v = + o.min_version; + + // From package.hxx:320:14 + ::bpkg::_optional_version const& vt = + (v) ? bpkg::_version + { + (v)->epoch, (v)->canonical_upstream, (v)->canonical_release, (v)->revision, (v)->iteration, (v)->upstream, (v)->release + } : bpkg::_optional_version (); + + if (wrapper_traits< ::bpkg::_optional_version >::get_null (vt)) + composite_value_traits< ::bpkg::_version, id_sqlite >::set_null ( + i.min_version_value, sk); + else + { + const::bpkg::_version& vw = + wrapper_traits< ::bpkg::_optional_version >::get_ref (vt); + + if (composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + i.min_version_value, + vw, + sk)) + grew = true; + } + } + + // max_version + // + { + ::butl::optional< ::bpkg::version > const& v = + o.max_version; + + // From package.hxx:320:14 + ::bpkg::_optional_version const& vt = + (v) ? bpkg::_version + { + (v)->epoch, (v)->canonical_upstream, (v)->canonical_release, (v)->revision, (v)->iteration, (v)->upstream, (v)->release + } : bpkg::_optional_version (); + + if (wrapper_traits< ::bpkg::_optional_version >::get_null (vt)) + composite_value_traits< ::bpkg::_version, id_sqlite >::set_null ( + i.max_version_value, sk); + else + { + const::bpkg::_version& vw = + wrapper_traits< ::bpkg::_optional_version >::get_ref (vt); + + if (composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + i.max_version_value, + vw, + sk)) + grew = true; + } + } + + // min_open + // + { + bool const& v = + o.min_open; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.min_open_value, + is_null, + v); + i.min_open_null = is_null; + } + + // max_open + // + { + bool const& v = + o.max_open; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.max_open_value, + is_null, + v); + i.max_open_null = is_null; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // min_version + // + { + ::butl::optional< ::bpkg::version >& v = + o.min_version; + + ::bpkg::_optional_version vt; + + if (composite_value_traits< ::bpkg::_version, id_sqlite >::get_null ( + i.min_version_value)) + wrapper_traits< ::bpkg::_optional_version >::set_null (vt); + else + { + ::bpkg::_version& vw = + wrapper_traits< ::bpkg::_optional_version >::set_ref (vt); + + composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + vw, + i.min_version_value, + db); + } + + // From package.hxx:320:14 + v = (vt) ? bpkg::version ((vt)->epoch, std::move ((vt)->upstream), std::move ((vt)->release), (vt)->revision, (vt)->iteration) : bpkg::optional_version (); + } + + // max_version + // + { + ::butl::optional< ::bpkg::version >& v = + o.max_version; + + ::bpkg::_optional_version vt; + + if (composite_value_traits< ::bpkg::_version, id_sqlite >::get_null ( + i.max_version_value)) + wrapper_traits< ::bpkg::_optional_version >::set_null (vt); + else + { + ::bpkg::_version& vw = + wrapper_traits< ::bpkg::_optional_version >::set_ref (vt); + + composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + vw, + i.max_version_value, + db); + } + + // From package.hxx:320:14 + v = (vt) ? bpkg::version ((vt)->epoch, std::move ((vt)->upstream), std::move ((vt)->release), (vt)->revision, (vt)->iteration) : bpkg::optional_version (); + } + + // min_open + // + { + bool& v = + o.min_open; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.min_open_value, + i.min_open_null); + } + + // max_open + // + { + bool& v = + o.max_open; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.max_open_value, + i.max_open_null); + } + } + + // dependency + // + + bool access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // name + // + if (t[0UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // constraint + // + if (composite_value_traits< ::bpkg::version_constraint, id_sqlite >::grow ( + i.constraint_value, t + 1UL)) + grew = true; + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // name + // + b[n].type = sqlite::image_traits< + ::bpkg::package_name, + sqlite::id_text>::bind_value; + b[n].buffer = i.name_value.data (); + b[n].size = &i.name_size; + b[n].capacity = i.name_value.capacity (); + b[n].is_null = &i.name_null; + n++; + + // constraint + // + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::bind ( + b + n, i.constraint_value, sk); + n += 16UL; + } + + bool access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // name + // + { + ::bpkg::package_name const& v = + o.name; + + bool is_null (false); + std::size_t cap (i.name_value.capacity ()); + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_image ( + i.name_value, + i.name_size, + is_null, + v); + i.name_null = is_null; + grew = grew || (cap != i.name_value.capacity ()); + } + + // constraint + // + { + ::butl::optional< ::bpkg::version_constraint > const& v = + o.constraint; + + if (wrapper_traits< ::butl::optional< ::bpkg::version_constraint > >::get_null (v)) + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::set_null ( + i.constraint_value, sk); + else + { + const::bpkg::version_constraint& vw = + wrapper_traits< ::butl::optional< ::bpkg::version_constraint > >::get_ref (v); + + if (composite_value_traits< ::bpkg::version_constraint, id_sqlite >::init ( + i.constraint_value, + vw, + sk)) + grew = true; + } + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // name + // + { + ::bpkg::package_name& v = + o.name; + + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_value ( + v, + i.name_value, + i.name_size, + i.name_null); + } + + // constraint + // + { + ::butl::optional< ::bpkg::version_constraint >& v = + o.constraint; + + if (composite_value_traits< ::bpkg::version_constraint, id_sqlite >::get_null ( + i.constraint_value)) + wrapper_traits< ::butl::optional< ::bpkg::version_constraint > >::set_null (v); + else + { + ::bpkg::version_constraint& vw = + wrapper_traits< ::butl::optional< ::bpkg::version_constraint > >::set_ref (v); + + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::init ( + vw, + i.constraint_value, + db); + } + } + } + + // dependency_alternative + // + + bool access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // enable + // + if (t[0UL]) + { + i.enable_value.capacity (i.enable_size); + grew = true; + } + + // reflect + // + if (t[1UL]) + { + i.reflect_value.capacity (i.reflect_size); + grew = true; + } + + // prefer + // + if (t[2UL]) + { + i.prefer_value.capacity (i.prefer_size); + grew = true; + } + + // accept + // + if (t[3UL]) + { + i.accept_value.capacity (i.accept_size); + grew = true; + } + + // require + // + if (t[4UL]) + { + i.require_value.capacity (i.require_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // enable + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.enable_value.data (); + b[n].size = &i.enable_size; + b[n].capacity = i.enable_value.capacity (); + b[n].is_null = &i.enable_null; + n++; + + // reflect + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.reflect_value.data (); + b[n].size = &i.reflect_size; + b[n].capacity = i.reflect_value.capacity (); + b[n].is_null = &i.reflect_null; + n++; + + // prefer + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.prefer_value.data (); + b[n].size = &i.prefer_size; + b[n].capacity = i.prefer_value.capacity (); + b[n].is_null = &i.prefer_null; + n++; + + // accept + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.accept_value.data (); + b[n].size = &i.accept_size; + b[n].capacity = i.accept_value.capacity (); + b[n].is_null = &i.accept_null; + n++; + + // require + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.require_value.data (); + b[n].size = &i.require_size; + b[n].capacity = i.require_value.capacity (); + b[n].is_null = &i.require_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // enable + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.enable; + + bool is_null (true); + std::size_t cap (i.enable_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.enable_value, + i.enable_size, + is_null, + v); + i.enable_null = is_null; + grew = grew || (cap != i.enable_value.capacity ()); + } + + // reflect + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.reflect; + + bool is_null (true); + std::size_t cap (i.reflect_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.reflect_value, + i.reflect_size, + is_null, + v); + i.reflect_null = is_null; + grew = grew || (cap != i.reflect_value.capacity ()); + } + + // prefer + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.prefer; + + bool is_null (true); + std::size_t cap (i.prefer_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.prefer_value, + i.prefer_size, + is_null, + v); + i.prefer_null = is_null; + grew = grew || (cap != i.prefer_value.capacity ()); + } + + // accept + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.accept; + + bool is_null (true); + std::size_t cap (i.accept_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.accept_value, + i.accept_size, + is_null, + v); + i.accept_null = is_null; + grew = grew || (cap != i.accept_value.capacity ()); + } + + // require + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.require; + + bool is_null (true); + std::size_t cap (i.require_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.require_value, + i.require_size, + is_null, + v); + i.require_null = is_null; + grew = grew || (cap != i.require_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // enable + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.enable; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.enable_value, + i.enable_size, + i.enable_null); + } + + // reflect + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.reflect; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.reflect_value, + i.reflect_size, + i.reflect_null); + } + + // prefer + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.prefer; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.prefer_value, + i.prefer_size, + i.prefer_null); + } + + // accept + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.accept; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.accept_value, + i.accept_size, + i.accept_null); + } + + // require + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.require; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.require_value, + i.require_size, + i.require_null); + } + } + + // dependency_alternatives + // + + bool access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // buildtime + // + t[0UL] = false; + + // comment + // + if (t[1UL]) + { + i.comment_value.capacity (i.comment_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // buildtime + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.buildtime_value; + b[n].is_null = &i.buildtime_null; + n++; + + // comment + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.comment_value.data (); + b[n].size = &i.comment_size; + b[n].capacity = i.comment_value.capacity (); + b[n].is_null = &i.comment_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // buildtime + // + { + bool const& v = + o.buildtime; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.buildtime_value, + is_null, + v); + i.buildtime_null = is_null; + } + + // comment + // + { + ::std::string const& v = + o.comment; + + bool is_null (false); + std::size_t cap (i.comment_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.comment_value, + i.comment_size, + is_null, + v); + i.comment_null = is_null; + grew = grew || (cap != i.comment_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // buildtime + // + { + bool& v = + o.buildtime; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.buildtime_value, + i.buildtime_null); + } + + // comment + // + { + ::std::string& v = + o.comment; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.comment_value, + i.comment_size, + i.comment_null); + } + } + + // test_dependency + // + + bool access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // dependency base + // + if (composite_value_traits< ::bpkg::dependency, id_sqlite >::grow ( + i, t + 0UL)) + grew = true; + + // type + // + if (t[17UL]) + { + i.type_value.capacity (i.type_size); + grew = true; + } + + // buildtime + // + t[18UL] = false; + + // reflect + // + if (t[19UL]) + { + i.reflect_value.capacity (i.reflect_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // dependency base + // + composite_value_traits< ::bpkg::dependency, id_sqlite >::bind (b + n, i, sk); + n += 17UL; + + // type + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.type_value.data (); + b[n].size = &i.type_size; + b[n].capacity = i.type_value.capacity (); + b[n].is_null = &i.type_null; + n++; + + // buildtime + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.buildtime_value; + b[n].is_null = &i.buildtime_null; + n++; + + // reflect + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.reflect_value.data (); + b[n].size = &i.reflect_size; + b[n].capacity = i.reflect_value.capacity (); + b[n].is_null = &i.reflect_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // dependency base + // + if (composite_value_traits< ::bpkg::dependency, id_sqlite >::init (i, o, sk)) + grew = true; + + // type + // + { + ::bpkg::test_dependency_type const& v = + o.type; + + // From package.hxx:613:14 + ::std::string const& vt = + to_string (v); + + bool is_null (false); + std::size_t cap (i.type_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.type_value, + i.type_size, + is_null, + vt); + i.type_null = is_null; + grew = grew || (cap != i.type_value.capacity ()); + } + + // buildtime + // + { + bool const& v = + o.buildtime; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.buildtime_value, + is_null, + v); + i.buildtime_null = is_null; + } + + // reflect + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.reflect; + + bool is_null (true); + std::size_t cap (i.reflect_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.reflect_value, + i.reflect_size, + is_null, + v); + i.reflect_null = is_null; + grew = grew || (cap != i.reflect_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // dependency base + // + composite_value_traits< ::bpkg::dependency, id_sqlite >::init (o, i, db); + + // type + // + { + ::bpkg::test_dependency_type& v = + o.type; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.type_value, + i.type_size, + i.type_null); + + // From package.hxx:613:14 + v = bpkg::to_test_dependency_type (vt); + } + + // buildtime + // + { + bool& v = + o.buildtime; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.buildtime_value, + i.buildtime_null); + } + + // reflect + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.reflect; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.reflect_value, + i.reflect_size, + i.reflect_null); + } + } + + // configuration + // + + struct access::object_traits_impl< ::bpkg::configuration, id_sqlite >::extra_statement_cache_type + { + extra_statement_cache_type ( + sqlite::connection&, + image_type&, + id_image_type&, + sqlite::binding&, + sqlite::binding&) + { + } + }; + + access::object_traits_impl< ::bpkg::configuration, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + id (const id_image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + sqlite::value_traits< + ::bpkg::optional_uint64_t, + sqlite::id_integer >::set_value ( + id, + i.id_value, + i.id_null); + } + + return id; + } + + access::object_traits_impl< ::bpkg::configuration, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + id (const image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + sqlite::value_traits< + ::bpkg::optional_uint64_t, + sqlite::id_integer >::set_value ( + id, + i.id_value, + i.id_null); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // id + // + t[0UL] = false; + + // uuid + // + if (t[1UL]) + { + i.uuid_value.capacity (i.uuid_size); + grew = true; + } + + // name + // + if (t[2UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // type + // + if (t[3UL]) + { + i.type_value.capacity (i.type_size); + grew = true; + } + + // path + // + if (t[4UL]) + { + i.path_value.capacity (i.path_size); + grew = true; + } + + // expl + // + t[5UL] = false; + + return grew; + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + + // id + // + if (sk != statement_update) + { + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.id_value; + b[n].is_null = &i.id_null; + n++; + } + + // uuid + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.uuid_value.data (); + b[n].size = &i.uuid_size; + b[n].capacity = i.uuid_value.capacity (); + b[n].is_null = &i.uuid_null; + n++; + + // name + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.name_value.data (); + b[n].size = &i.name_size; + b[n].capacity = i.name_value.capacity (); + b[n].is_null = &i.name_null; + n++; + + // type + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.type_value.data (); + b[n].size = &i.type_size; + b[n].capacity = i.type_value.capacity (); + b[n].is_null = &i.type_null; + n++; + + // path + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.path_value.data (); + b[n].size = &i.path_size; + b[n].capacity = i.path_value.capacity (); + b[n].is_null = &i.path_null; + n++; + + // expl + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.expl_value; + b[n].is_null = &i.expl_null; + n++; + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + bind (sqlite::bind* b, id_image_type& i) + { + std::size_t n (0); + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.id_value; + b[n].is_null = &i.id_null; + } + + bool access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + init (image_type& i, + const object_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // id + // + if (sk == statement_insert) + { + ::bpkg::optional_uint64_t const& v = + o.id; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::optional_uint64_t, + sqlite::id_integer >::set_image ( + i.id_value, + is_null, + v); + i.id_null = is_null; + } + + // uuid + // + { + ::bpkg::configuration::uuid_type const& v = + o.uuid; + + // From package.hxx:61:14 + ::std::string const& vt = + (v).string (); + + bool is_null (false); + std::size_t cap (i.uuid_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.uuid_value, + i.uuid_size, + is_null, + vt); + i.uuid_null = is_null; + grew = grew || (cap != i.uuid_value.capacity ()); + } + + // name + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.name; + + bool is_null (true); + std::size_t cap (i.name_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.name_value, + i.name_size, + is_null, + v); + i.name_null = is_null; + grew = grew || (cap != i.name_value.capacity ()); + } + + // type + // + { + ::std::string const& v = + o.type; + + bool is_null (false); + std::size_t cap (i.type_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.type_value, + i.type_size, + is_null, + v); + i.type_null = is_null; + grew = grew || (cap != i.type_value.capacity ()); + } + + // path + // + { + ::butl::dir_path const& v = + o.path; + + // From package.hxx:52:14 + ::std::string const& vt = + (v).string (); + + bool is_null (false); + std::size_t cap (i.path_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.path_value, + i.path_size, + is_null, + vt); + i.path_null = is_null; + grew = grew || (cap != i.path_value.capacity ()); + } + + // expl + // + { + bool const& v = + o.expl; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.expl_value, + is_null, + v); + i.expl_null = is_null; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + init (object_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // id + // + { + ::bpkg::optional_uint64_t& v = + o.id; + + sqlite::value_traits< + ::bpkg::optional_uint64_t, + sqlite::id_integer >::set_value ( + v, + i.id_value, + i.id_null); + } + + // uuid + // + { + ::bpkg::configuration::uuid_type& v = + o.uuid; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.uuid_value, + i.uuid_size, + i.uuid_null); + + // From package.hxx:61:14 + v = bpkg::uuid (vt); + } + + // name + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.name; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.name_value, + i.name_size, + i.name_null); + } + + // type + // + { + ::std::string& v = + o.type; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.type_value, + i.type_size, + i.type_null); + } + + // path + // + { + ::butl::dir_path& v = + o.path; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.path_value, + i.path_size, + i.path_null); + + // From package.hxx:52:14 + v = bpkg::dir_path (vt); + } + + // expl + // + { + bool& v = + o.expl; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.expl_value, + i.expl_null); + } + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + init (id_image_type& i, const id_type& id) + { + { + bool is_null (false); + sqlite::value_traits< + ::bpkg::optional_uint64_t, + sqlite::id_integer >::set_image ( + i.id_value, + is_null, + id); + i.id_null = is_null; + } + } + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"configuration\" " + "(\"id\", " + "\"uuid\", " + "\"name\", " + "\"type\", " + "\"path\", " + "\"explicit\") " + "VALUES " + "(?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"configuration\".\"id\", " + "\"main\".\"configuration\".\"uuid\", " + "\"main\".\"configuration\".\"name\", " + "\"main\".\"configuration\".\"type\", " + "\"main\".\"configuration\".\"path\", " + "\"main\".\"configuration\".\"explicit\" " + "FROM \"main\".\"configuration\" " + "WHERE \"main\".\"configuration\".\"id\"=?"; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"configuration\" " + "SET " + "\"uuid\"=?, " + "\"name\"=?, " + "\"type\"=?, " + "\"path\"=?, " + "\"explicit\"=? " + "WHERE \"id\"=?"; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"configuration\" " + "WHERE \"id\"=?"; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"configuration\".\"id\", " + "\"main\".\"configuration\".\"uuid\", " + "\"main\".\"configuration\".\"name\", " + "\"main\".\"configuration\".\"type\", " + "\"main\".\"configuration\".\"path\", " + "\"main\".\"configuration\".\"explicit\" " + "FROM \"main\".\"configuration\""; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"configuration\""; + + const char access::object_traits_impl< ::bpkg::configuration, id_sqlite >::table_name[] = + "\"main\".\"configuration\""; + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + persist (database& db, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + callback (db, + static_cast<const object_type&> (obj), + callback_event::pre_persist); + + image_type& im (sts.image ()); + binding& imb (sts.insert_image_binding ()); + + if (init (im, obj, statement_insert)) + im.version++; + + if (im.version != sts.insert_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_insert); + sts.insert_image_version (im.version); + imb.version++; + } + + { + id_image_type& i (sts.id_image ()); + binding& b (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || b.version == 0) + { + bind (b.bind, i); + sts.id_image_version (i.version); + b.version++; + } + } + + insert_statement& st (sts.persist_statement ()); + if (!st.execute ()) + throw object_already_persistent (); + + obj.id = id (sts.id_image ()); + + callback (db, + static_cast<const object_type&> (obj), + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + update (database& db, const object_type& obj) + { + ODB_POTENTIALLY_UNUSED (db); + + using namespace sqlite; + using sqlite::update_statement; + + callback (db, obj, callback_event::pre_update); + + sqlite::transaction& tr (sqlite::transaction::current ()); + sqlite::connection& conn (tr.connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& idi (sts.id_image ()); + init (idi, id (obj)); + + image_type& im (sts.image ()); + if (init (im, obj, statement_update)) + im.version++; + + bool u (false); + binding& imb (sts.update_image_binding ()); + if (im.version != sts.update_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_update); + sts.update_image_version (im.version); + imb.version++; + u = true; + } + + binding& idb (sts.id_image_binding ()); + if (idi.version != sts.update_id_image_version () || + idb.version == 0) + { + if (idi.version != sts.id_image_version () || + idb.version == 0) + { + bind (idb.bind, idi); + sts.id_image_version (idi.version); + idb.version++; + } + + sts.update_id_image_version (idi.version); + + if (!u) + imb.version++; + } + + update_statement& st (sts.update_statement ()); + if (st.execute () == 0) + throw object_not_persistent (); + + callback (db, obj, callback_event::post_update); + pointer_cache_traits::update (db, obj); + } + + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + erase (database& db, const id_type& id) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& i (sts.id_image ()); + init (i, id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + if (sts.erase_statement ().execute () != 1) + throw object_not_persistent (); + + pointer_cache_traits::erase (db, id); + } + + access::object_traits_impl< ::bpkg::configuration, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + find (database& db, const id_type& id) + { + using namespace sqlite; + + { + pointer_type p (pointer_cache_traits::find (db, id)); + + if (!pointer_traits::null_ptr (p)) + return p; + } + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + + if (l.locked ()) + { + if (!find_ (sts, &id)) + return pointer_type (); + } + + pointer_type p ( + access::object_factory<object_type, pointer_type>::create ()); + pointer_traits::guard pg (p); + + pointer_cache_traits::insert_guard ig ( + pointer_cache_traits::insert (db, id, p)); + + object_type& obj (pointer_traits::get_ref (p)); + + if (l.locked ()) + { + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + pointer_cache_traits::load (ig.position ()); + } + else + sts.delay_load (id, obj, ig.position ()); + + ig.release (); + pg.release (); + return p; + } + + bool access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + find (database& db, const id_type& id, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + reference_cache_traits::position_type pos ( + reference_cache_traits::insert (db, id, obj)); + reference_cache_traits::insert_guard ig (pos); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + reference_cache_traits::load (pos); + ig.release (); + return true; + } + + bool access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + reload (database& db, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + const id_type& id (object_traits_impl::id (obj)); + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, true); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + return true; + } + + bool access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + find_ (statements_type& sts, + const id_type* id) + { + using namespace sqlite; + + id_image_type& i (sts.id_image ()); + init (i, *id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + select_statement& st (sts.find_statement ()); + + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + if (grow (im, sts.select_image_truncated ())) + im.version++; + + if (im.version != sts.select_image_version ()) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + result< access::object_traits_impl< ::bpkg::configuration, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + query (database& db, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + q.init_parameters (); + shared_ptr<select_statement> st ( + new (shared) select_statement ( + conn, + text, + false, + true, + q.parameters_binding (), + imb)); + + st->execute (); + + shared_ptr< odb::object_result_impl<object_type> > r ( + new (shared) sqlite::object_result_impl<object_type> ( + q, st, sts, 0)); + + return result<object_type> (r); + } + + unsigned long long access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + erase_query (database& db, const query_base_type& q) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + std::string text (erase_query_statement); + if (!q.empty ()) + { + text += ' '; + text += q.clause (); + } + + q.init_parameters (); + delete_statement st ( + conn, + text, + q.parameters_binding ()); + + return st.execute (); + } + + odb::details::shared_ptr<prepared_query_impl> + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + prepare_query (connection& c, const char* n, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + static_cast<sqlite::connection&> (c)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + shared_ptr<sqlite::prepared_query_impl> r ( + new (shared) sqlite::prepared_query_impl (conn)); + r->name = n; + r->execute = &execute_query; + r->query = q; + r->stmt.reset ( + new (shared) select_statement ( + conn, + text, + false, + true, + r->query.parameters_binding (), + imb)); + + return r; + } + + odb::details::shared_ptr<result_impl> + access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + execute_query (prepared_query_impl& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::prepared_query_impl& pq ( + static_cast<sqlite::prepared_query_impl&> (q)); + shared_ptr<select_statement> st ( + odb::details::inc_ref ( + static_cast<select_statement*> (pq.stmt.get ()))); + + sqlite::transaction& tr (sqlite::transaction::current ()); + + // The connection used by the current transaction and the + // one used to prepare this statement must be the same. + // + assert (q.verify_connection (tr)); + + statements_type& sts ( + st->connection ().statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + pq.query.init_parameters (); + st->execute (); + + return shared_ptr<result_impl> ( + new (shared) sqlite::object_result_impl<object_type> ( + pq.query, st, sts, 0)); + } + + // canonical_version + // + + bool access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // epoch + // + t[0UL] = false; + + // canonical_upstream + // + if (t[1UL]) + { + i.canonical_upstream_value.capacity (i.canonical_upstream_size); + grew = true; + } + + // canonical_release + // + if (t[2UL]) + { + i.canonical_release_value.capacity (i.canonical_release_size); + grew = true; + } + + // revision + // + t[3UL] = false; + + // iteration + // + t[4UL] = false; + + return grew; + } + + void access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // epoch + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.epoch_value; + b[n].is_null = &i.epoch_null; + n++; + + // canonical_upstream + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.canonical_upstream_value.data (); + b[n].size = &i.canonical_upstream_size; + b[n].capacity = i.canonical_upstream_value.capacity (); + b[n].is_null = &i.canonical_upstream_null; + n++; + + // canonical_release + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.canonical_release_value.data (); + b[n].size = &i.canonical_release_size; + b[n].capacity = i.canonical_release_value.capacity (); + b[n].is_null = &i.canonical_release_null; + n++; + + // revision + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.revision_value; + b[n].is_null = &i.revision_null; + n++; + + // iteration + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.iteration_value; + b[n].is_null = &i.iteration_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // epoch + // + { + ::uint16_t const& v = + o.epoch; + + bool is_null (false); + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_image ( + i.epoch_value, + is_null, + v); + i.epoch_null = is_null; + } + + // canonical_upstream + // + { + ::std::string const& v = + o.canonical_upstream; + + bool is_null (false); + std::size_t cap (i.canonical_upstream_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.canonical_upstream_value, + i.canonical_upstream_size, + is_null, + v); + i.canonical_upstream_null = is_null; + grew = grew || (cap != i.canonical_upstream_value.capacity ()); + } + + // canonical_release + // + { + ::std::string const& v = + o.canonical_release; + + bool is_null (false); + std::size_t cap (i.canonical_release_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.canonical_release_value, + i.canonical_release_size, + is_null, + v); + i.canonical_release_null = is_null; + grew = grew || (cap != i.canonical_release_value.capacity ()); + } + + // revision + // + { + ::uint16_t const& v = + o.revision; + + bool is_null (false); + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_image ( + i.revision_value, + is_null, + v); + i.revision_null = is_null; + } + + // iteration + // + { + ::uint32_t const& v = + o.iteration; + + bool is_null (false); + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::set_image ( + i.iteration_value, + is_null, + v); + i.iteration_null = is_null; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // epoch + // + { + ::uint16_t& v = + o.epoch; + + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_value ( + v, + i.epoch_value, + i.epoch_null); + } + + // canonical_upstream + // + { + ::std::string& v = + o.canonical_upstream; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.canonical_upstream_value, + i.canonical_upstream_size, + i.canonical_upstream_null); + } + + // canonical_release + // + { + ::std::string& v = + o.canonical_release; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.canonical_release_value, + i.canonical_release_size, + i.canonical_release_null); + } + + // revision + // + { + ::uint16_t& v = + o.revision; + + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::set_value ( + v, + i.revision_value, + i.revision_null); + } + + // iteration + // + { + ::uint32_t& v = + o.iteration; + + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::set_value ( + v, + i.iteration_value, + i.iteration_null); + } + } + + // upstream_version + // + + bool access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // upstream_ + // + if (t[0UL]) + { + i.upstream_value.capacity (i.upstream_size); + grew = true; + } + + // release_ + // + if (t[1UL]) + { + i.release_value.capacity (i.release_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // upstream_ + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.upstream_value.data (); + b[n].size = &i.upstream_size; + b[n].capacity = i.upstream_value.capacity (); + b[n].is_null = &i.upstream_null; + n++; + + // release_ + // + b[n].type = sqlite::image_traits< + ::bpkg::optional_string, + sqlite::id_text>::bind_value; + b[n].buffer = i.release_value.data (); + b[n].size = &i.release_size; + b[n].capacity = i.release_value.capacity (); + b[n].is_null = &i.release_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // upstream_ + // + { + // From package.hxx:271:7 + ::std::string const& v = + o.upstream; + + bool is_null (false); + std::size_t cap (i.upstream_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.upstream_value, + i.upstream_size, + is_null, + v); + i.upstream_null = is_null; + grew = grew || (cap != i.upstream_value.capacity ()); + } + + // release_ + // + { + // From package.hxx:276:7 + ::bpkg::optional_string const& v = + o.release; + + bool is_null (true); + std::size_t cap (i.release_value.capacity ()); + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_image ( + i.release_value, + i.release_size, + is_null, + v); + i.release_null = is_null; + grew = grew || (cap != i.release_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // upstream_ + // + { + // From package.hxx:272:7 + ::std::string v; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.upstream_value, + i.upstream_size, + i.upstream_null); + + // From package.hxx:272:7 + o = bpkg::version (0, std::move (v), std::string (), bpkg::nullopt, 0); + } + + // release_ + // + { + // From package.hxx:277:7 + ::bpkg::optional_string v; + + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_value ( + v, + i.release_value, + i.release_size, + i.release_null); + + // From package.hxx:277:7 + o = bpkg::version (0, std::move (o.upstream), std::move (v), bpkg::nullopt, 0); + } + } + + // _repository_location + // + + bool access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // url + // + if (t[0UL]) + { + i.url_value.capacity (i.url_size); + grew = true; + } + + // type + // + if (t[1UL]) + { + i.type_value.capacity (i.type_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // url + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.url_value.data (); + b[n].size = &i.url_size; + b[n].capacity = i.url_value.capacity (); + b[n].is_null = &i.url_null; + n++; + + // type + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.type_value.data (); + b[n].size = &i.type_size; + b[n].capacity = i.type_value.capacity (); + b[n].is_null = &i.type_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // url + // + { + ::bpkg::repository_url const& v = + o.url; + + // From package.hxx:353:14 + ::std::string const& vt = + (v).string (); + + bool is_null (false); + std::size_t cap (i.url_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.url_value, + i.url_size, + is_null, + vt); + i.url_null = is_null; + grew = grew || (cap != i.url_value.capacity ()); + } + + // type + // + { + ::bpkg::repository_type const& v = + o.type; + + // From package.hxx:357:14 + ::std::string const& vt = + to_string (v); + + bool is_null (false); + std::size_t cap (i.type_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.type_value, + i.type_size, + is_null, + vt); + i.type_null = is_null; + grew = grew || (cap != i.type_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // url + // + { + ::bpkg::repository_url& v = + o.url; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.url_value, + i.url_size, + i.url_null); + + // From package.hxx:353:14 + v = (vt).empty () ? bpkg::repository_url () : bpkg::repository_url (vt); + } + + // type + // + { + ::bpkg::repository_type& v = + o.type; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.type_value, + i.type_size, + i.type_null); + + // From package.hxx:357:14 + v = bpkg::to_repository_type (vt); + } + } + + // repository_fragment + // + + struct access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::extra_statement_cache_type + { + sqlite::container_statements_impl< complements_traits > complements; + sqlite::container_statements_impl< prerequisites_traits > prerequisites; + + extra_statement_cache_type ( + sqlite::connection& c, + image_type&, + id_image_type&, + sqlite::binding& id, + sqlite::binding&) + : complements (c, id), + prerequisites (c, id) + { + } + }; + + // complements + // + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + select_statement[] = + "SELECT " + "\"main\".\"repository_fragment_complements\".\"complement\" " + "FROM \"main\".\"repository_fragment_complements\" " + "WHERE \"main\".\"repository_fragment_complements\".\"repository_fragment\"=?"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"repository_fragment_complements\" " + "(\"repository_fragment\", " + "\"complement\") " + "VALUES " + "(?, ?)"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"repository_fragment_complements\" " + "WHERE \"repository_fragment\"=?"; + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // value + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = d.value_value.data (); + b[n].size = &d.value_size; + b[n].capacity = d.value_value.capacity (); + b[n].is_null = &d.value_null; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // value + // + if (t[0UL]) + { + i.value_value.capacity (i.value_size); + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + init (data_image_type& i, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // value + // + { + typedef object_traits< ::bpkg::repository > obj_traits; + typedef odb::pointer_traits< value_type > wptr_traits; + typedef odb::pointer_traits< wptr_traits::strong_pointer_type > ptr_traits; + + wptr_traits::strong_pointer_type sp (wptr_traits::lock (v)); + bool is_null (ptr_traits::null_ptr (sp)); + if (!is_null) + { + const obj_traits::id_type& ptr_id ( + ptr_traits::object_id< ptr_traits::element_type > (sp)); + + std::size_t cap (i.value_value.capacity ()); + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_image ( + i.value_value, + i.value_size, + is_null, + ptr_id); + i.value_null = is_null; + grew = grew || (cap != i.value_value.capacity ()); + } + else + throw null_pointer (); + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + init (value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // value + // + { + typedef object_traits< ::bpkg::repository > obj_traits; + typedef odb::pointer_traits< value_type > ptr_traits; + + if (i.value_null) + v = ptr_traits::pointer_type (); + else + { + obj_traits::id_type ptr_id; + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_value ( + ptr_id, + i.value_value, + i.value_size, + i.value_null); + + v = ptr_traits::pointer_type ( + *static_cast<sqlite::database*> (db), ptr_id); + } + } + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + insert (const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + select (value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::complements_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::erase (fs); + } + + // prerequisites + // + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + select_statement[] = + "SELECT " + "\"main\".\"repository_fragment_prerequisites\".\"prerequisite\" " + "FROM \"main\".\"repository_fragment_prerequisites\" " + "WHERE \"main\".\"repository_fragment_prerequisites\".\"repository_fragment\"=?"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"repository_fragment_prerequisites\" " + "(\"repository_fragment\", " + "\"prerequisite\") " + "VALUES " + "(?, ?)"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"repository_fragment_prerequisites\" " + "WHERE \"repository_fragment\"=?"; + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // value + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = d.value_value.data (); + b[n].size = &d.value_size; + b[n].capacity = d.value_value.capacity (); + b[n].is_null = &d.value_null; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // value + // + if (t[0UL]) + { + i.value_value.capacity (i.value_size); + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + init (data_image_type& i, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // value + // + { + typedef object_traits< ::bpkg::repository > obj_traits; + typedef odb::pointer_traits< value_type > wptr_traits; + typedef odb::pointer_traits< wptr_traits::strong_pointer_type > ptr_traits; + + wptr_traits::strong_pointer_type sp (wptr_traits::lock (v)); + bool is_null (ptr_traits::null_ptr (sp)); + if (!is_null) + { + const obj_traits::id_type& ptr_id ( + ptr_traits::object_id< ptr_traits::element_type > (sp)); + + std::size_t cap (i.value_value.capacity ()); + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_image ( + i.value_value, + i.value_size, + is_null, + ptr_id); + i.value_null = is_null; + grew = grew || (cap != i.value_value.capacity ()); + } + else + throw null_pointer (); + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + init (value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // value + // + { + typedef object_traits< ::bpkg::repository > obj_traits; + typedef odb::pointer_traits< value_type > ptr_traits; + + if (i.value_null) + v = ptr_traits::pointer_type (); + else + { + obj_traits::id_type ptr_id; + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_value ( + ptr_id, + i.value_value, + i.value_size, + i.value_null); + + v = ptr_traits::pointer_type ( + *static_cast<sqlite::database*> (db), ptr_id); + } + } + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + insert (const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + select (value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::prerequisites_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::erase (fs); + } + + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + id (const image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + id, + i.name_value, + i.name_size, + i.name_null); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // name + // + if (t[0UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // location + // + if (composite_value_traits< ::bpkg::_repository_location, id_sqlite >::grow ( + i.location_value, t + 1UL)) + grew = true; + + return grew; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + + // name + // + if (sk != statement_update) + { + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.name_value.data (); + b[n].size = &i.name_size; + b[n].capacity = i.name_value.capacity (); + b[n].is_null = &i.name_null; + n++; + } + + // location + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::bind ( + b + n, i.location_value, sk); + n += 2UL; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + bind (sqlite::bind* b, id_image_type& i) + { + std::size_t n (0); + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.id_value.data (); + b[n].size = &i.id_size; + b[n].capacity = i.id_value.capacity (); + b[n].is_null = &i.id_null; + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + init (image_type& i, + const object_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // name + // + if (sk == statement_insert) + { + ::std::string const& v = + o.name; + + bool is_null (false); + std::size_t cap (i.name_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.name_value, + i.name_size, + is_null, + v); + i.name_null = is_null; + grew = grew || (cap != i.name_value.capacity ()); + } + + // location + // + { + ::bpkg::repository_location const& v = + o.location; + + // From package.hxx:363:14 + ::bpkg::_repository_location const& vt = + bpkg::_repository_location + { + (v).url (), (v).empty () ? bpkg::repository_type::pkg : (v).type () + }; + + + if (composite_value_traits< ::bpkg::_repository_location, id_sqlite >::init ( + i.location_value, + vt, + sk)) + grew = true; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + init (object_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // name + // + { + ::std::string& v = + o.name; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.name_value, + i.name_size, + i.name_null); + } + + // location + // + { + // From package.hxx:432:7 + ::bpkg::repository_location v; + + ::bpkg::_repository_location vt; + + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::init ( + vt, + i.location_value, + db); + + // From package.hxx:363:14 + v = bpkg::repository_location (std::move ((vt).url), (vt).type); + // From package.hxx:432:7 + o.location = std::move (v); + assert (o.name == o.location.canonical_name ()); + } + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + init (id_image_type& i, const id_type& id) + { + bool grew (false); + { + bool is_null (false); + std::size_t cap (i.id_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.id_value, + i.id_size, + is_null, + id); + i.id_null = is_null; + grew = grew || (cap != i.id_value.capacity ()); + } + + if (grew) + i.version++; + } + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"repository_fragment\" " + "(\"name\", " + "\"url\", " + "\"type\") " + "VALUES " + "(?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"repository_fragment\".\"name\", " + "\"main\".\"repository_fragment\".\"url\", " + "\"main\".\"repository_fragment\".\"type\" " + "FROM \"main\".\"repository_fragment\" " + "WHERE \"main\".\"repository_fragment\".\"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"repository_fragment\" " + "SET " + "\"url\"=?, " + "\"type\"=? " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"repository_fragment\" " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"repository_fragment\".\"name\", " + "\"main\".\"repository_fragment\".\"url\", " + "\"main\".\"repository_fragment\".\"type\" " + "FROM \"main\".\"repository_fragment\""; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"repository_fragment\""; + + const char access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::table_name[] = + "\"main\".\"repository_fragment\""; + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + persist (database& db, const object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + callback (db, + obj, + callback_event::pre_persist); + + image_type& im (sts.image ()); + binding& imb (sts.insert_image_binding ()); + + if (init (im, obj, statement_insert)) + im.version++; + + if (im.version != sts.insert_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_insert); + sts.insert_image_version (im.version); + imb.version++; + } + + insert_statement& st (sts.persist_statement ()); + if (!st.execute ()) + throw object_already_persistent (); + + id_image_type& i (sts.id_image ()); + init (i, id (obj)); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // complements + // + { + ::bpkg::repository_fragment::dependencies const& v = + obj.complements; + + complements_traits::persist ( + v, + esc.complements); + } + + // prerequisites + // + { + ::bpkg::repository_fragment::dependencies const& v = + obj.prerequisites; + + prerequisites_traits::persist ( + v, + esc.prerequisites); + } + + callback (db, + obj, + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + update (database& db, const object_type& obj) + { + ODB_POTENTIALLY_UNUSED (db); + + using namespace sqlite; + using sqlite::update_statement; + + callback (db, obj, callback_event::pre_update); + + sqlite::transaction& tr (sqlite::transaction::current ()); + sqlite::connection& conn (tr.connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& idi (sts.id_image ()); + init (idi, id (obj)); + + image_type& im (sts.image ()); + if (init (im, obj, statement_update)) + im.version++; + + bool u (false); + binding& imb (sts.update_image_binding ()); + if (im.version != sts.update_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_update); + sts.update_image_version (im.version); + imb.version++; + u = true; + } + + binding& idb (sts.id_image_binding ()); + if (idi.version != sts.update_id_image_version () || + idb.version == 0) + { + if (idi.version != sts.id_image_version () || + idb.version == 0) + { + bind (idb.bind, idi); + sts.id_image_version (idi.version); + idb.version++; + } + + sts.update_id_image_version (idi.version); + + if (!u) + imb.version++; + } + + update_statement& st (sts.update_statement ()); + if (st.execute () == 0) + throw object_not_persistent (); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // complements + // + { + ::bpkg::repository_fragment::dependencies const& v = + obj.complements; + + complements_traits::update ( + v, + esc.complements); + } + + // prerequisites + // + { + ::bpkg::repository_fragment::dependencies const& v = + obj.prerequisites; + + prerequisites_traits::update ( + v, + esc.prerequisites); + } + + callback (db, obj, callback_event::post_update); + pointer_cache_traits::update (db, obj); + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + erase (database& db, const id_type& id) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& i (sts.id_image ()); + init (i, id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // complements + // + { + complements_traits::erase ( + esc.complements); + } + + // prerequisites + // + { + prerequisites_traits::erase ( + esc.prerequisites); + } + + if (sts.erase_statement ().execute () != 1) + throw object_not_persistent (); + + pointer_cache_traits::erase (db, id); + } + + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + find (database& db, const id_type& id) + { + using namespace sqlite; + + { + pointer_type p (pointer_cache_traits::find (db, id)); + + if (!pointer_traits::null_ptr (p)) + return p; + } + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + + if (l.locked ()) + { + if (!find_ (sts, &id)) + return pointer_type (); + } + + pointer_type p ( + access::object_factory<object_type, pointer_type>::create ()); + pointer_traits::guard pg (p); + + pointer_cache_traits::insert_guard ig ( + pointer_cache_traits::insert (db, id, p)); + + object_type& obj (pointer_traits::get_ref (p)); + + if (l.locked ()) + { + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + pointer_cache_traits::load (ig.position ()); + } + else + sts.delay_load (id, obj, ig.position ()); + + ig.release (); + pg.release (); + return p; + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + find (database& db, const id_type& id, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + reference_cache_traits::position_type pos ( + reference_cache_traits::insert (db, id, obj)); + reference_cache_traits::insert_guard ig (pos); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + reference_cache_traits::load (pos); + ig.release (); + return true; + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + reload (database& db, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + const id_type& id (object_traits_impl::id (obj)); + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, true); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + return true; + } + + bool access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + find_ (statements_type& sts, + const id_type* id) + { + using namespace sqlite; + + id_image_type& i (sts.id_image ()); + init (i, *id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + select_statement& st (sts.find_statement ()); + + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + if (grow (im, sts.select_image_truncated ())) + im.version++; + + if (im.version != sts.select_image_version ()) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool reload) + { + ODB_POTENTIALLY_UNUSED (reload); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // complements + // + { + ::bpkg::repository_fragment::dependencies& v = + obj.complements; + + complements_traits::load ( + v, + esc.complements); + } + + // prerequisites + // + { + ::bpkg::repository_fragment::dependencies& v = + obj.prerequisites; + + prerequisites_traits::load ( + v, + esc.prerequisites); + } + } + + result< access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + query (database& db, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + q.init_parameters (); + shared_ptr<select_statement> st ( + new (shared) select_statement ( + conn, + text, + false, + true, + q.parameters_binding (), + imb)); + + st->execute (); + + shared_ptr< odb::object_result_impl<object_type> > r ( + new (shared) sqlite::object_result_impl<object_type> ( + q, st, sts, 0)); + + return result<object_type> (r); + } + + unsigned long long access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + erase_query (database& db, const query_base_type& q) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + std::string text (erase_query_statement); + if (!q.empty ()) + { + text += ' '; + text += q.clause (); + } + + q.init_parameters (); + delete_statement st ( + conn, + text, + q.parameters_binding ()); + + return st.execute (); + } + + odb::details::shared_ptr<prepared_query_impl> + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + prepare_query (connection& c, const char* n, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + static_cast<sqlite::connection&> (c)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + shared_ptr<sqlite::prepared_query_impl> r ( + new (shared) sqlite::prepared_query_impl (conn)); + r->name = n; + r->execute = &execute_query; + r->query = q; + r->stmt.reset ( + new (shared) select_statement ( + conn, + text, + false, + true, + r->query.parameters_binding (), + imb)); + + return r; + } + + odb::details::shared_ptr<result_impl> + access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + execute_query (prepared_query_impl& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::prepared_query_impl& pq ( + static_cast<sqlite::prepared_query_impl&> (q)); + shared_ptr<select_statement> st ( + odb::details::inc_ref ( + static_cast<select_statement*> (pq.stmt.get ()))); + + sqlite::transaction& tr (sqlite::transaction::current ()); + + // The connection used by the current transaction and the + // one used to prepare this statement must be the same. + // + assert (q.verify_connection (tr)); + + statements_type& sts ( + st->connection ().statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + pq.query.init_parameters (); + st->execute (); + + return shared_ptr<result_impl> ( + new (shared) sqlite::object_result_impl<object_type> ( + pq.query, st, sts, 0)); + } + + // repository_fragment_count + // + + bool access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // result + // + t[0UL] = false; + + return grew; + } + + void access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i) + { + using namespace sqlite; + + sqlite::statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + std::size_t n (0); + + // result + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.result_value; + b[n].is_null = &i.result_null; + n++; + } + + void access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // result + // + { + ::std::size_t& v = + o.result; + + sqlite::value_traits< + ::std::size_t, + sqlite::id_integer >::set_value ( + v, + i.result_value, + i.result_null); + } + } + + access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "count(*) "); + + r += "FROM \"main\".\"repository_fragment\""; + + query_base_type c ( + // From package.hxx:447:5 + query_columns::name != "" && (q.empty () ? query_base_type::true_expr : q)); + + c.optimize (); + + if (!c.empty ()) + { + r += " "; + r += c.clause_prefix (); + r += c; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + query (database& db, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + const query_base_type& qs (query_statement (q)); + qs.init_parameters (); + shared_ptr<select_statement> st ( + new (shared) select_statement ( + conn, + qs.clause (), + false, + true, + qs.parameters_binding (), + imb)); + + st->execute (); + + shared_ptr< odb::view_result_impl<view_type> > r ( + new (shared) sqlite::view_result_impl<view_type> ( + qs, st, sts, 0)); + + return result<view_type> (r); + } + + odb::details::shared_ptr<prepared_query_impl> + access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + prepare_query (connection& c, const char* n, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + static_cast<sqlite::connection&> (c)); + statements_type& sts ( + conn.statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + shared_ptr<sqlite::prepared_query_impl> r ( + new (shared) sqlite::prepared_query_impl (conn)); + r->name = n; + r->execute = &execute_query; + r->query = query_statement (q); + r->stmt.reset ( + new (shared) select_statement ( + conn, + r->query.clause (), + false, + true, + r->query.parameters_binding (), + imb)); + + return r; + } + + odb::details::shared_ptr<result_impl> + access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >:: + execute_query (prepared_query_impl& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::prepared_query_impl& pq ( + static_cast<sqlite::prepared_query_impl&> (q)); + shared_ptr<select_statement> st ( + odb::details::inc_ref ( + static_cast<select_statement*> (pq.stmt.get ()))); + + sqlite::transaction& tr (sqlite::transaction::current ()); + + // The connection used by the current transaction and the + // one used to prepare this statement must be the same. + // + assert (q.verify_connection (tr)); + + statements_type& sts ( + st->connection ().statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + pq.query.init_parameters (); + st->execute (); + + return shared_ptr<result_impl> ( + new (shared) sqlite::view_result_impl<view_type> ( + pq.query, st, sts, 0)); + } + + // fragment_type + // + + bool access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // friendly_name + // + if (t[0UL]) + { + i.friendly_name_value.capacity (i.friendly_name_size); + grew = true; + } + + // fragment + // + if (t[1UL]) + { + i.fragment_value.capacity (i.fragment_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // friendly_name + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.friendly_name_value.data (); + b[n].size = &i.friendly_name_size; + b[n].capacity = i.friendly_name_value.capacity (); + b[n].is_null = &i.friendly_name_null; + n++; + + // fragment + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.fragment_value.data (); + b[n].size = &i.fragment_size; + b[n].capacity = i.fragment_value.capacity (); + b[n].is_null = &i.fragment_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // friendly_name + // + { + ::std::string const& v = + o.friendly_name; + + bool is_null (false); + std::size_t cap (i.friendly_name_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.friendly_name_value, + i.friendly_name_size, + is_null, + v); + i.friendly_name_null = is_null; + grew = grew || (cap != i.friendly_name_value.capacity ()); + } + + // fragment + // + { + ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > const& v = + o.fragment; + + typedef object_traits< ::bpkg::repository_fragment > obj_traits; + typedef odb::pointer_traits< ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > > ptr_traits; + + bool is_null (ptr_traits::null_ptr (v)); + if (!is_null) + { + const obj_traits::id_type& ptr_id ( + ptr_traits::object_id< ptr_traits::element_type > (v)); + + std::size_t cap (i.fragment_value.capacity ()); + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_image ( + i.fragment_value, + i.fragment_size, + is_null, + ptr_id); + i.fragment_null = is_null; + grew = grew || (cap != i.fragment_value.capacity ()); + } + else + i.fragment_null = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // friendly_name + // + { + ::std::string& v = + o.friendly_name; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.friendly_name_value, + i.friendly_name_size, + i.friendly_name_null); + } + + // fragment + // + { + ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment >& v = + o.fragment; + + typedef object_traits< ::bpkg::repository_fragment > obj_traits; + typedef odb::pointer_traits< ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > > ptr_traits; + + if (i.fragment_null) + v = ptr_traits::pointer_type (); + else + { + obj_traits::id_type ptr_id; + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_value ( + ptr_id, + i.fragment_value, + i.fragment_size, + i.fragment_null); + + v = ptr_traits::pointer_type ( + *static_cast<sqlite::database*> (db), ptr_id); + } + } + } + + // repository + // + + struct access::object_traits_impl< ::bpkg::repository, id_sqlite >::extra_statement_cache_type + { + sqlite::container_statements_impl< fragments_traits > fragments; + + extra_statement_cache_type ( + sqlite::connection& c, + image_type&, + id_image_type&, + sqlite::binding& id, + sqlite::binding&) + : fragments (c, id) + { + } + }; + + // fragments + // + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + select_statement[] = + "SELECT " + "\"main\".\"repository_fragments\".\"index\", " + "\"main\".\"repository_fragments\".\"friendly_name\", " + "\"main\".\"repository_fragments\".\"fragment\" " + "FROM \"main\".\"repository_fragments\" " + "WHERE \"main\".\"repository_fragments\".\"repository\"=? ORDER BY \"main\".\"repository_fragments\".\"index\""; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"repository_fragments\" " + "(\"repository\", " + "\"index\", " + "\"friendly_name\", " + "\"fragment\") " + "VALUES " + "(?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"repository_fragments\" " + "WHERE \"repository\"=?"; + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // index + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &d.index_value; + b[n].is_null = &d.index_null; + n++; + + // value + // + composite_value_traits< value_type, id_sqlite >::bind ( + b + n, d.value_value, sk); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // index + // + t[0UL] = false; + + // value + // + if (composite_value_traits< value_type, id_sqlite >::grow ( + i.value_value, t + 1UL)) + grew = true; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + init (data_image_type& i, + index_type* j, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // index + // + if (j != 0) + { + bool is_null (false); + sqlite::value_traits< + index_type, + sqlite::id_integer >::set_image ( + i.index_value, + is_null, + *j); + i.index_null = is_null; + } + + // value + // + { + if (composite_value_traits< value_type, id_sqlite >::init ( + i.value_value, + v, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + init (index_type& j, + value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // index + // + { + sqlite::value_traits< + index_type, + sqlite::id_integer >::set_value ( + j, + i.index_value, + i.index_null); + } + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + insert (index_type i, const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, &i, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + select (index_type& i, value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (i, v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >::fragments_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + access::object_traits_impl< ::bpkg::repository, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + id (const image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + id, + i.name_value, + i.name_size, + i.name_null); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // name + // + if (t[0UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // location + // + if (composite_value_traits< ::bpkg::_repository_location, id_sqlite >::grow ( + i.location_value, t + 1UL)) + grew = true; + + // certificate + // + if (t[3UL]) + { + i.certificate_value.capacity (i.certificate_size); + grew = true; + } + + // local + // + t[4UL] = false; + + return grew; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + + // name + // + if (sk != statement_update) + { + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.name_value.data (); + b[n].size = &i.name_size; + b[n].capacity = i.name_value.capacity (); + b[n].is_null = &i.name_null; + n++; + } + + // location + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::bind ( + b + n, i.location_value, sk); + n += 2UL; + + // certificate + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.certificate_value.data (); + b[n].size = &i.certificate_size; + b[n].capacity = i.certificate_value.capacity (); + b[n].is_null = &i.certificate_null; + n++; + + // local + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.local_value; + b[n].is_null = &i.local_null; + n++; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + bind (sqlite::bind* b, id_image_type& i) + { + std::size_t n (0); + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.id_value.data (); + b[n].size = &i.id_size; + b[n].capacity = i.id_value.capacity (); + b[n].is_null = &i.id_null; + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + init (image_type& i, + const object_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // name + // + if (sk == statement_insert) + { + ::std::string const& v = + o.name; + + bool is_null (false); + std::size_t cap (i.name_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.name_value, + i.name_size, + is_null, + v); + i.name_null = is_null; + grew = grew || (cap != i.name_value.capacity ()); + } + + // location + // + { + ::bpkg::repository_location const& v = + o.location; + + // From package.hxx:363:14 + ::bpkg::_repository_location const& vt = + bpkg::_repository_location + { + (v).url (), (v).empty () ? bpkg::repository_type::pkg : (v).type () + }; + + + if (composite_value_traits< ::bpkg::_repository_location, id_sqlite >::init ( + i.location_value, + vt, + sk)) + grew = true; + } + + // certificate + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.certificate; + + bool is_null (true); + std::size_t cap (i.certificate_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.certificate_value, + i.certificate_size, + is_null, + v); + i.certificate_null = is_null; + grew = grew || (cap != i.certificate_value.capacity ()); + } + + // local + // + { + ::butl::optional< bool > const& v = + o.local; + + bool is_null (true); + sqlite::value_traits< + ::butl::optional< bool >, + sqlite::id_integer >::set_image ( + i.local_value, + is_null, + v); + i.local_null = is_null; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + init (object_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // name + // + { + ::std::string& v = + o.name; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.name_value, + i.name_size, + i.name_null); + } + + // location + // + { + // From package.hxx:496:7 + ::bpkg::repository_location v; + + ::bpkg::_repository_location vt; + + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::init ( + vt, + i.location_value, + db); + + // From package.hxx:363:14 + v = bpkg::repository_location (std::move ((vt).url), (vt).type); + // From package.hxx:496:7 + o.location = std::move (v); + assert (o.name == o.location.canonical_name ()); + } + + // certificate + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.certificate; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.certificate_value, + i.certificate_size, + i.certificate_null); + } + + // local + // + { + ::butl::optional< bool >& v = + o.local; + + sqlite::value_traits< + ::butl::optional< bool >, + sqlite::id_integer >::set_value ( + v, + i.local_value, + i.local_null); + } + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + init (id_image_type& i, const id_type& id) + { + bool grew (false); + { + bool is_null (false); + std::size_t cap (i.id_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.id_value, + i.id_size, + is_null, + id); + i.id_null = is_null; + grew = grew || (cap != i.id_value.capacity ()); + } + + if (grew) + i.version++; + } + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"repository\" " + "(\"name\", " + "\"url\", " + "\"type\", " + "\"certificate\", " + "\"local\") " + "VALUES " + "(?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"repository\".\"name\", " + "\"main\".\"repository\".\"url\", " + "\"main\".\"repository\".\"type\", " + "\"main\".\"repository\".\"certificate\", " + "\"main\".\"repository\".\"local\" " + "FROM \"main\".\"repository\" " + "WHERE \"main\".\"repository\".\"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"repository\" " + "SET " + "\"url\"=?, " + "\"type\"=?, " + "\"certificate\"=?, " + "\"local\"=? " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"repository\" " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"repository\".\"name\", " + "\"main\".\"repository\".\"url\", " + "\"main\".\"repository\".\"type\", " + "\"main\".\"repository\".\"certificate\", " + "\"main\".\"repository\".\"local\" " + "FROM \"main\".\"repository\""; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"repository\""; + + const char access::object_traits_impl< ::bpkg::repository, id_sqlite >::table_name[] = + "\"main\".\"repository\""; + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + persist (database& db, const object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + callback (db, + obj, + callback_event::pre_persist); + + image_type& im (sts.image ()); + binding& imb (sts.insert_image_binding ()); + + if (init (im, obj, statement_insert)) + im.version++; + + if (im.version != sts.insert_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_insert); + sts.insert_image_version (im.version); + imb.version++; + } + + insert_statement& st (sts.persist_statement ()); + if (!st.execute ()) + throw object_already_persistent (); + + id_image_type& i (sts.id_image ()); + init (i, id (obj)); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // fragments + // + { + ::bpkg::repository::fragments_type const& v = + obj.fragments; + + fragments_traits::persist ( + v, + esc.fragments); + } + + callback (db, + obj, + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + update (database& db, const object_type& obj) + { + ODB_POTENTIALLY_UNUSED (db); + + using namespace sqlite; + using sqlite::update_statement; + + callback (db, obj, callback_event::pre_update); + + sqlite::transaction& tr (sqlite::transaction::current ()); + sqlite::connection& conn (tr.connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& idi (sts.id_image ()); + init (idi, id (obj)); + + image_type& im (sts.image ()); + if (init (im, obj, statement_update)) + im.version++; + + bool u (false); + binding& imb (sts.update_image_binding ()); + if (im.version != sts.update_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_update); + sts.update_image_version (im.version); + imb.version++; + u = true; + } + + binding& idb (sts.id_image_binding ()); + if (idi.version != sts.update_id_image_version () || + idb.version == 0) + { + if (idi.version != sts.id_image_version () || + idb.version == 0) + { + bind (idb.bind, idi); + sts.id_image_version (idi.version); + idb.version++; + } + + sts.update_id_image_version (idi.version); + + if (!u) + imb.version++; + } + + update_statement& st (sts.update_statement ()); + if (st.execute () == 0) + throw object_not_persistent (); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // fragments + // + { + ::bpkg::repository::fragments_type const& v = + obj.fragments; + + fragments_traits::update ( + v, + esc.fragments); + } + + callback (db, obj, callback_event::post_update); + pointer_cache_traits::update (db, obj); + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + erase (database& db, const id_type& id) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + id_image_type& i (sts.id_image ()); + init (i, id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // fragments + // + { + fragments_traits::erase ( + esc.fragments); + } + + if (sts.erase_statement ().execute () != 1) + throw object_not_persistent (); + + pointer_cache_traits::erase (db, id); + } + + access::object_traits_impl< ::bpkg::repository, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + find (database& db, const id_type& id) + { + using namespace sqlite; + + { + pointer_type p (pointer_cache_traits::find (db, id)); + + if (!pointer_traits::null_ptr (p)) + return p; + } + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + + if (l.locked ()) + { + if (!find_ (sts, &id)) + return pointer_type (); + } + + pointer_type p ( + access::object_factory<object_type, pointer_type>::create ()); + pointer_traits::guard pg (p); + + pointer_cache_traits::insert_guard ig ( + pointer_cache_traits::insert (db, id, p)); + + object_type& obj (pointer_traits::get_ref (p)); + + if (l.locked ()) + { + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + pointer_cache_traits::load (ig.position ()); + } + else + sts.delay_load (id, obj, ig.position ()); + + ig.release (); + pg.release (); + return p; + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + find (database& db, const id_type& id, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + reference_cache_traits::position_type pos ( + reference_cache_traits::insert (db, id, obj)); + reference_cache_traits::insert_guard ig (pos); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, false); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + reference_cache_traits::load (pos); + ig.release (); + return true; + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + reload (database& db, object_type& obj) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + const id_type& id (object_traits_impl::id (obj)); + if (!find_ (sts, &id)) + return false; + + select_statement& st (sts.find_statement ()); + ODB_POTENTIALLY_UNUSED (st); + + callback (db, obj, callback_event::pre_load); + init (obj, sts.image (), &db); + load_ (sts, obj, true); + sts.load_delayed (0); + l.unlock (); + callback (db, obj, callback_event::post_load); + return true; + } + + bool access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + find_ (statements_type& sts, + const id_type* id) + { + using namespace sqlite; + + id_image_type& i (sts.id_image ()); + init (i, *id); + + binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + select_statement& st (sts.find_statement ()); + + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + if (grow (im, sts.select_image_truncated ())) + im.version++; + + if (im.version != sts.select_image_version ()) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool reload) + { + ODB_POTENTIALLY_UNUSED (reload); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // fragments + // + { + ::bpkg::repository::fragments_type& v = + obj.fragments; + + fragments_traits::load ( + v, + esc.fragments); + } + } + + result< access::object_traits_impl< ::bpkg::repository, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + query (database& db, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + q.init_parameters (); + shared_ptr<select_statement> st ( + new (shared) select_statement ( + conn, + text, + false, + true, + q.parameters_binding (), + imb)); + + st->execute (); + + shared_ptr< odb::object_result_impl<object_type> > r ( + new (shared) sqlite::object_result_impl<object_type> ( + q, st, sts, 0)); + + return result<object_type> (r); + } + + unsigned long long access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + erase_query (database& db, const query_base_type& q) + { + using namespace sqlite; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + + std::string text (erase_query_statement); + if (!q.empty ()) + { + text += ' '; + text += q.clause (); + } + + q.init_parameters (); + delete_statement st ( + conn, + text, + q.parameters_binding ()); + + return st.execute (); + } + + odb::details::shared_ptr<prepared_query_impl> + access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + prepare_query (connection& c, const char* n, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + static_cast<sqlite::connection&> (c)); + + statements_type& sts ( + conn.statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + std::string text (query_statement); + if (!q.empty ()) + { + text += " "; + text += q.clause (); + } + + shared_ptr<sqlite::prepared_query_impl> r ( + new (shared) sqlite::prepared_query_impl (conn)); + r->name = n; + r->execute = &execute_query; + r->query = q; + r->stmt.reset ( + new (shared) select_statement ( + conn, + text, + false, + true, + r->query.parameters_binding (), + imb)); + + return r; + } + + odb::details::shared_ptr<result_impl> + access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + execute_query (prepared_query_impl& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::prepared_query_impl& pq ( + static_cast<sqlite::prepared_query_impl&> (q)); + shared_ptr<select_statement> st ( + odb::details::inc_ref ( + static_cast<select_statement*> (pq.stmt.get ()))); + + sqlite::transaction& tr (sqlite::transaction::current ()); + + // The connection used by the current transaction and the + // one used to prepare this statement must be the same. + // + assert (q.verify_connection (tr)); + + statements_type& sts ( + st->connection ().statement_cache ().find_object<object_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.select_image_binding ()); + + if (im.version != sts.select_image_version () || + imb.version == 0) + { + bind (imb.bind, im, statement_select); + sts.select_image_version (im.version); + imb.version++; + } + + pq.query.init_parameters (); + st->execute (); + + return shared_ptr<result_impl> ( + new (shared) sqlite::object_result_impl<object_type> ( + pq.query, st, sts, 0)); + } + + // repository_count + // + + bool access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // result + // + t[0UL] = false; + + return grew; + } + + void access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i) + { + using namespace sqlite; + + sqlite::statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + std::size_t n (0); + + // result + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.result_value; + b[n].is_null = &i.result_null; + n++; + } + + void access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // result + // + { + ::std::size_t& v = + o.result; + + sqlite::value_traits< + ::std::size_t, + sqlite::id_integer >::set_value ( + v, + i.result_value, + i.result_null); + } + } + + access::view_traits_impl< ::bpkg::repository_count, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "count(*) "); + + r += "FROM \"main\".\"repository\""; + + query_base_type c ( + // From package.hxx:507:38 + query_columns::name != "" && (q.empty () ? query_base_type::true_expr : q)); + + c.optimize (); + + if (!c.empty ()) + { + r += " "; + r += c.clause_prefix (); + r += c; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::repository_count, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + query (database& db, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (db)); + statements_type& sts ( + conn.statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + const query_base_type& qs (query_statement (q)); + qs.init_parameters (); + shared_ptr<select_statement> st ( + new (shared) select_statement ( + conn, + qs.clause (), + false, + true, + qs.parameters_binding (), + imb)); + + st->execute (); + + shared_ptr< odb::view_result_impl<view_type> > r ( + new (shared) sqlite::view_result_impl<view_type> ( + qs, st, sts, 0)); + + return result<view_type> (r); + } + + odb::details::shared_ptr<prepared_query_impl> + access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + prepare_query (connection& c, const char* n, const query_base_type& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::connection& conn ( + static_cast<sqlite::connection&> (c)); + statements_type& sts ( + conn.statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + shared_ptr<sqlite::prepared_query_impl> r ( + new (shared) sqlite::prepared_query_impl (conn)); + r->name = n; + r->execute = &execute_query; + r->query = query_statement (q); + r->stmt.reset ( + new (shared) select_statement ( + conn, + r->query.clause (), + false, + true, + r->query.parameters_binding (), + imb)); + + return r; + } + + odb::details::shared_ptr<result_impl> + access::view_traits_impl< ::bpkg::repository_count, id_sqlite >:: + execute_query (prepared_query_impl& q) + { + using namespace sqlite; + using odb::details::shared; + using odb::details::shared_ptr; + + sqlite::prepared_query_impl& pq ( + static_cast<sqlite::prepared_query_impl&> (q)); + shared_ptr<select_statement> st ( + odb::details::inc_ref ( + static_cast<select_statement*> (pq.stmt.get ()))); + + sqlite::transaction& tr (sqlite::transaction::current ()); + + // The connection used by the current transaction and the + // one used to prepare this statement must be the same. + // + assert (q.verify_connection (tr)); + + statements_type& sts ( + st->connection ().statement_cache ().find_view<view_type> ()); + + image_type& im (sts.image ()); + binding& imb (sts.image_binding ()); + + if (im.version != sts.image_version () || imb.version == 0) + { + bind (imb.bind, im); + sts.image_version (im.version); + imb.version++; + } + + pq.query.init_parameters (); + st->execute (); + + return shared_ptr<result_impl> ( + new (shared) sqlite::view_result_impl<view_type> ( + pq.query, st, sts, 0)); + } + + // package_location + // + + bool access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // repository_fragment + // + if (t[0UL]) + { + i.repository_fragment_value.capacity (i.repository_fragment_size); + grew = true; + } + + // location + // + if (t[1UL]) + { + i.location_value.capacity (i.location_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // repository_fragment + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.repository_fragment_value.data (); + b[n].size = &i.repository_fragment_size; + b[n].capacity = i.repository_fragment_value.capacity (); + b[n].is_null = &i.repository_fragment_null; + n++; + + // location + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.location_value.data (); + b[n].size = &i.location_size; + b[n].capacity = i.location_value.capacity (); + b[n].is_null = &i.location_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // repository_fragment + // + { + ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > const& v = + o.repository_fragment; + + typedef object_traits< ::bpkg::repository_fragment > obj_traits; + typedef odb::pointer_traits< ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > > ptr_traits; + + bool is_null (ptr_traits::null_ptr (v)); + if (!is_null) + { + const obj_traits::id_type& ptr_id ( + ptr_traits::object_id< ptr_traits::element_type > (v)); + + std::size_t cap (i.repository_fragment_value.capacity ()); + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_image ( + i.repository_fragment_value, + i.repository_fragment_size, + is_null, + ptr_id); + i.repository_fragment_null = is_null; + grew = grew || (cap != i.repository_fragment_value.capacity ()); + } + else + i.repository_fragment_null = true; + } + + // location + // + { + ::butl::path const& v = + o.location; + + // From package.hxx:45:14 + ::std::string const& vt = + (v).representation (); + + bool is_null (false); + std::size_t cap (i.location_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.location_value, + i.location_size, + is_null, + vt); + i.location_null = is_null; + grew = grew || (cap != i.location_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // repository_fragment + // + { + ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment >& v = + o.repository_fragment; + + typedef object_traits< ::bpkg::repository_fragment > obj_traits; + typedef odb::pointer_traits< ::bpkg::lazy_shared_ptr< ::bpkg::repository_fragment > > ptr_traits; + + if (i.repository_fragment_null) + v = ptr_traits::pointer_type (); + else + { + obj_traits::id_type ptr_id; + sqlite::value_traits< + obj_traits::id_type, + sqlite::id_text >::set_value ( + ptr_id, + i.repository_fragment_value, + i.repository_fragment_size, + i.repository_fragment_null); + + v = ptr_traits::pointer_type ( + *static_cast<sqlite::database*> (db), ptr_id); + } + } + + // location + // + { + ::butl::path& v = + o.location; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.location_value, + i.location_size, + i.location_null); + + // From package.hxx:45:14 + v = bpkg::path (vt); + } + } + + // dependency_alternatives_ex + // + + bool access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // dependency_alternatives base + // + if (composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::grow ( + i, t + 0UL)) + grew = true; + + // type + // + if (t[2UL]) + { + i.type_value.capacity (i.type_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // dependency_alternatives base + // + composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::bind (b + n, i, sk); + n += 2UL; + + // type + // + b[n].type = sqlite::image_traits< + ::bpkg::optional_string, + sqlite::id_text>::bind_value; + b[n].buffer = i.type_value.data (); + b[n].size = &i.type_size; + b[n].capacity = i.type_value.capacity (); + b[n].is_null = &i.type_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // dependency_alternatives base + // + if (composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::init (i, o, sk)) + grew = true; + + // type + // + { + ::butl::optional< ::bpkg::test_dependency_type > const& v = + o.type; + + // From package.hxx:617:14 + ::bpkg::optional_string const& vt = + (v) ? to_string ( * (v)) : bpkg::optional_string (); + + bool is_null (true); + std::size_t cap (i.type_value.capacity ()); + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_image ( + i.type_value, + i.type_size, + is_null, + vt); + i.type_null = is_null; + grew = grew || (cap != i.type_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // dependency_alternatives base + // + composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::init (o, i, db); + + // type + // + { + ::butl::optional< ::bpkg::test_dependency_type >& v = + o.type; + + ::bpkg::optional_string vt; + + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_value ( + vt, + i.type_value, + i.type_size, + i.type_null); + + // From package.hxx:617:14 + v = (vt) ? bpkg::to_test_dependency_type ( * (vt)) : bpkg::optional_test_dependency_type (); + } + } + + // available_package_id + // + + bool access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // name + // + if (t[0UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // version + // + if (composite_value_traits< ::bpkg::canonical_version, id_sqlite >::grow ( + i.version_value, t + 1UL)) + grew = true; + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // name + // + b[n].type = sqlite::image_traits< + ::bpkg::package_name, + sqlite::id_text>::bind_value; + b[n].buffer = i.name_value.data (); + b[n].size = &i.name_size; + b[n].capacity = i.name_value.capacity (); + b[n].is_null = &i.name_null; + n++; + + // version + // + composite_value_traits< ::bpkg::canonical_version, id_sqlite >::bind ( + b + n, i.version_value, sk); + n += 5UL; + } + + bool access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // name + // + { + ::bpkg::package_name const& v = + o.name; + + bool is_null (false); + std::size_t cap (i.name_value.capacity ()); + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_image ( + i.name_value, + i.name_size, + is_null, + v); + i.name_null = is_null; + grew = grew || (cap != i.name_value.capacity ()); + } + + // version + // + { + ::bpkg::canonical_version const& v = + o.version; + + if (composite_value_traits< ::bpkg::canonical_version, id_sqlite >::init ( + i.version_value, + v, + sk)) + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // name + // + { + ::bpkg::package_name& v = + o.name; + + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_value ( + v, + i.name_value, + i.name_size, + i.name_null); + } + + // version + // + { + ::bpkg::canonical_version& v = + o.version; + + composite_value_traits< ::bpkg::canonical_version, id_sqlite >::init ( + v, + i.version_value, + db); + } + } + + // _dependency_alternative_key + // + + bool access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // outer + // + t[0UL] = false; + + // inner + // + t[1UL] = false; + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // outer + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.outer_value; + b[n].is_null = &i.outer_null; + n++; + + // inner + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.inner_value; + b[n].is_null = &i.inner_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // outer + // + { + ::bpkg::available_package::_dependency_alternative_key::outer_type const& v = + o.outer; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_key::outer_type, + sqlite::id_integer >::set_image ( + i.outer_value, + is_null, + v); + i.outer_null = is_null; + } + + // inner + // + { + ::bpkg::available_package::_dependency_alternative_key::inner_type const& v = + o.inner; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_key::inner_type, + sqlite::id_integer >::set_image ( + i.inner_value, + is_null, + v); + i.inner_null = is_null; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // outer + // + { + ::bpkg::available_package::_dependency_alternative_key::outer_type& v = + o.outer; + + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_key::outer_type, + sqlite::id_integer >::set_value ( + v, + i.outer_value, + i.outer_null); + } + + // inner + // + { + ::bpkg::available_package::_dependency_alternative_key::inner_type& v = + o.inner; + + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_key::inner_type, + sqlite::id_integer >::set_value ( + v, + i.inner_value, + i.inner_null); + } + } + + // _dependency_key + // + + bool access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // outer + // + t[0UL] = false; + + // middle + // + t[1UL] = false; + + // inner + // + t[2UL] = false; + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + bind (sqlite::bind* b, + image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (b); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + std::size_t n (0); + ODB_POTENTIALLY_UNUSED (n); + + // outer + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.outer_value; + b[n].is_null = &i.outer_null; + n++; + + // middle + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.middle_value; + b[n].is_null = &i.middle_null; + n++; + + // inner + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.inner_value; + b[n].is_null = &i.inner_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + init (image_type& i, + const value_type& o, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + bool grew (false); + + // outer + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::outer_type const& v = + o.outer; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::outer_type, + sqlite::id_integer >::set_image ( + i.outer_value, + is_null, + v); + i.outer_null = is_null; + } + + // middle + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::middle_type const& v = + o.middle; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::middle_type, + sqlite::id_integer >::set_image ( + i.middle_value, + is_null, + v); + i.middle_null = is_null; + } + + // inner + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::inner_type const& v = + o.inner; + + bool is_null (false); + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::inner_type, + sqlite::id_integer >::set_image ( + i.inner_value, + is_null, + v); + i.inner_null = is_null; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // outer + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::outer_type& v = + o.outer; + + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::outer_type, + sqlite::id_integer >::set_value ( + v, + i.outer_value, + i.outer_null); + } + + // middle + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::middle_type& v = + o.middle; + + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::middle_type, + sqlite::id_integer >::set_value ( + v, + i.middle_value, + i.middle_null); + } + + // inner + // + { + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::inner_type& v = + o.inner; + + sqlite::value_traits< + ::bpkg::available_package::_dependency_alternative_dependencies_type::key_type::inner_type, + sqlite::id_integer >::set_value ( + v, + i.inner_value, + i.inner_null); + } + } + + // available_package + // + + struct access::object_traits_impl< ::bpkg::available_package, id_sqlite >::extra_statement_cache_type + { + sqlite::container_statements_impl< locations_traits > locations; + sqlite::container_statements_impl< dependencies_traits > dependencies; + sqlite::container_statements_impl< dependency_alternatives_traits > dependency_alternatives; + sqlite::container_statements_impl< dependency_alternative_dependencies_traits > dependency_alternative_dependencies; + sqlite::container_statements_impl< tests_traits > tests; + + extra_statement_cache_type ( + sqlite::connection& c, + image_type&, + id_image_type&, + sqlite::binding& id, + sqlite::binding&) + : locations (c, id), + dependencies (c, id), + dependency_alternatives (c, id), + dependency_alternative_dependencies (c, id), + tests (c, id) + { + } + }; + + // locations + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_locations\".\"repository_fragment\", " + "\"main\".\"available_package_locations\".\"location\" " + "FROM \"main\".\"available_package_locations\" " + "WHERE \"main\".\"available_package_locations\".\"name\"=? AND \"main\".\"available_package_locations\".\"version_epoch\"=? AND \"main\".\"available_package_locations\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_locations\".\"version_canonical_release\"=? AND \"main\".\"available_package_locations\".\"version_revision\"=? AND \"main\".\"available_package_locations\".\"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_locations\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"repository_fragment\", " + "\"location\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_locations\" " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // value + // + composite_value_traits< value_type, id_sqlite >::bind ( + b + n, d.value_value, sk); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // value + // + if (composite_value_traits< value_type, id_sqlite >::grow ( + i.value_value, t + 0UL)) + grew = true; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + init (data_image_type& i, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // value + // + { + if (composite_value_traits< value_type, id_sqlite >::init ( + i.value_value, + v, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + init (value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + insert (index_type, const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + select (index_type&, value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = false; + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + fs.ordered_ = false; + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = false; + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::locations_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = false; + container_traits_type::erase (fs); + } + + // dependencies + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_dependencies\".\"index\", " + "\"main\".\"available_package_dependencies\".\"buildtime\", " + "\"main\".\"available_package_dependencies\".\"comment\", " + "\"main\".\"available_package_dependencies\".\"type\" " + "FROM \"main\".\"available_package_dependencies\" " + "WHERE \"main\".\"available_package_dependencies\".\"name\"=? AND \"main\".\"available_package_dependencies\".\"version_epoch\"=? AND \"main\".\"available_package_dependencies\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_dependencies\".\"version_canonical_release\"=? AND \"main\".\"available_package_dependencies\".\"version_revision\"=? AND \"main\".\"available_package_dependencies\".\"version_iteration\"=? ORDER BY \"main\".\"available_package_dependencies\".\"index\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_dependencies\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"index\", " + "\"buildtime\", " + "\"comment\", " + "\"type\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_dependencies\" " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // index + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &d.index_value; + b[n].is_null = &d.index_null; + n++; + + // value + // + composite_value_traits< value_type, id_sqlite >::bind ( + b + n, d.value_value, sk); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // index + // + t[0UL] = false; + + // value + // + if (composite_value_traits< value_type, id_sqlite >::grow ( + i.value_value, t + 1UL)) + grew = true; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + init (data_image_type& i, + index_type* j, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // index + // + if (j != 0) + { + bool is_null (false); + sqlite::value_traits< + index_type, + sqlite::id_integer >::set_image ( + i.index_value, + is_null, + *j); + i.index_null = is_null; + } + + // value + // + { + if (composite_value_traits< value_type, id_sqlite >::init ( + i.value_value, + v, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + init (index_type& j, + value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // index + // + { + sqlite::value_traits< + index_type, + sqlite::id_integer >::set_value ( + j, + i.index_value, + i.index_null); + } + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + insert (index_type i, const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, &i, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + select (index_type& i, value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (i, v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependencies_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // dependency_alternatives + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_dependency_alternatives\".\"dependency_index\", " + "\"main\".\"available_package_dependency_alternatives\".\"index\", " + "\"main\".\"available_package_dependency_alternatives\".\"enable\", " + "\"main\".\"available_package_dependency_alternatives\".\"reflect\", " + "\"main\".\"available_package_dependency_alternatives\".\"prefer\", " + "\"main\".\"available_package_dependency_alternatives\".\"accept\", " + "\"main\".\"available_package_dependency_alternatives\".\"require\" " + "FROM \"main\".\"available_package_dependency_alternatives\" " + "WHERE \"main\".\"available_package_dependency_alternatives\".\"name\"=? AND \"main\".\"available_package_dependency_alternatives\".\"version_epoch\"=? AND \"main\".\"available_package_dependency_alternatives\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_dependency_alternatives\".\"version_canonical_release\"=? AND \"main\".\"available_package_dependency_alternatives\".\"version_revision\"=? AND \"main\".\"available_package_dependency_alternatives\".\"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_dependency_alternatives\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"index\", " + "\"enable\", " + "\"reflect\", " + "\"prefer\", " + "\"accept\", " + "\"require\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_dependency_alternatives\" " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // key + // + composite_value_traits< key_type, id_sqlite >::bind ( + b + n, d.key_value, sk); + n += 2UL; + + // value + // + composite_value_traits< value_type, id_sqlite >::bind ( + b + n, d.value_value, sk); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // key + // + if (composite_value_traits< key_type, id_sqlite >::grow ( + i.key_value, t + 0UL)) + grew = true; + + // value + // + if (composite_value_traits< value_type, id_sqlite >::grow ( + i.value_value, t + 2UL)) + grew = true; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + init (data_image_type& i, + const key_type* k, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // key + // + if (k != 0) + { + composite_value_traits< key_type, id_sqlite >::init ( + i.key_value, + *k, + sk); + } + + // value + // + { + if (composite_value_traits< value_type, id_sqlite >::init ( + i.value_value, + v, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + init (key_type& k, + value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // key + // + { + composite_value_traits< key_type, id_sqlite >::init ( + k, + i.key_value, + db); + } + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + insert (const key_type& k, const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, &k, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + select (key_type& k, value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (k, v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + update (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::update (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternatives_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::erase (fs); + } + + // dependency_alternative_dependencies + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dependency_index\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"alternative_index\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"index\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_name\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_epoch\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_canonical_upstream\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_canonical_release\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_revision\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_iteration\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_upstream\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_version_release\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_epoch\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_canonical_upstream\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_canonical_release\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_revision\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_iteration\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_upstream\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_version_release\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_min_open\", " + "\"main\".\"available_package_dependency_alternative_dependencies\".\"dep_max_open\" " + "FROM \"main\".\"available_package_dependency_alternative_dependencies\" " + "WHERE \"main\".\"available_package_dependency_alternative_dependencies\".\"name\"=? AND \"main\".\"available_package_dependency_alternative_dependencies\".\"version_epoch\"=? AND \"main\".\"available_package_dependency_alternative_dependencies\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_dependency_alternative_dependencies\".\"version_canonical_release\"=? AND \"main\".\"available_package_dependency_alternative_dependencies\".\"version_revision\"=? AND \"main\".\"available_package_dependency_alternative_dependencies\".\"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_dependency_alternative_dependencies\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"alternative_index\", " + "\"index\", " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"dep_min_version_iteration\", " + "\"dep_min_version_upstream\", " + "\"dep_min_version_release\", " + "\"dep_max_version_epoch\", " + "\"dep_max_version_canonical_upstream\", " + "\"dep_max_version_canonical_release\", " + "\"dep_max_version_revision\", " + "\"dep_max_version_iteration\", " + "\"dep_max_version_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_dependency_alternative_dependencies\" " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + bind (sqlite::bind* b, + const sqlite::bind* id, + std::size_t id_size, + data_image_type& d) + { + using namespace sqlite; + + statement_kind sk (statement_select); + ODB_POTENTIALLY_UNUSED (sk); + + size_t n (0); + + // object_id + // + if (id != 0) + std::memcpy (&b[n], id, id_size * sizeof (id[0])); + n += id_size; + + // key + // + composite_value_traits< key_type, id_sqlite >::bind ( + b + n, d.key_value, sk); + n += 3UL; + + // value + // + composite_value_traits< value_type, id_sqlite >::bind ( + b + n, d.value_value, sk); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // key + // + if (composite_value_traits< key_type, id_sqlite >::grow ( + i.key_value, t + 0UL)) + grew = true; + + // value + // + if (composite_value_traits< value_type, id_sqlite >::grow ( + i.value_value, t + 3UL)) + grew = true; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + init (data_image_type& i, + const key_type* k, + const value_type& v) + { + using namespace sqlite; + + statement_kind sk (statement_insert); + ODB_POTENTIALLY_UNUSED (sk); + + bool grew (false); + + // key + // + if (k != 0) + { + composite_value_traits< key_type, id_sqlite >::init ( + i.key_value, + *k, + sk); + } + + // value + // + { + if (composite_value_traits< value_type, id_sqlite >::init ( + i.value_value, + v, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + init (key_type& k, + value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // key + // + { + composite_value_traits< key_type, id_sqlite >::init ( + k, + i.key_value, + db); + } + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + insert (const key_type& k, const value_type& v, void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (di, &k, v); + + if (sts.data_binding_test_version ()) + { + const binding& id (sts.id_binding ()); + bind (sts.data_bind (), id.bind, id.count, di); + sts.data_binding_update_version (); + } + + if (!sts.insert_statement ().execute ()) + throw object_already_persistent (); + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + select (key_type& k, value_type& v, void* d) + { + using namespace sqlite; + using sqlite::select_statement; + + statements_type& sts (*static_cast< statements_type* > (d)); + data_image_type& di (sts.data_image ()); + + init (k, v, di, &sts.connection ().database ()); + + select_statement& st (sts.select_statement ()); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, sts.id_binding ().count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + delete_ (void* d) + { + using namespace sqlite; + + statements_type& sts (*static_cast< statements_type* > (d)); + sts.delete_statement ().execute (); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + persist (const container_type& c, + statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::persist (c, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alternative_dependencies_traits:: + load (container_type& c, + statements_type& sts) + { + using namespace sqlite; + using sqlite::select_statement; + + const binding& id (sts.id_binding ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), id.bind, id.count, sts.data_image ()); + sts.data_binding_update_version (); + } + + select_statement& st (sts.select_statement ()); + st.execute (); + auto_result ar (st); + select_statement::result r (st.fetch ()); + + if (r == select_statement::truncated) + { + data_image_type& di (sts.data_image ()); + grow (di, sts.select_image_truncated ()); + + if (sts.data_binding_test_version ()) + { + bind (sts.data_bind (), 0, id.count, di); + sts.data_binding_update_version (); + st.refetch (); + } + } + + bool more (r != select_statement::no_data); + + functions_type& fs (sts.functions ()); + container_traits_type::load (c, more, fs); + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::dependency_alterna |