diff options
108 files changed, 66508 insertions, 173 deletions
diff --git a/bpkg/argument-grouping.cxx b/bpkg/argument-grouping.cxx new file mode 100644 index 0000000..998b7ea --- /dev/null +++ b/bpkg/argument-grouping.cxx @@ -0,0 +1,84 @@ +// -*- 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> + +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..5604d2a --- /dev/null +++ b/bpkg/bpkg-options.cxx @@ -0,0 +1,1664 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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_bindist_ (), + 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_bindist_) + { + ::bpkg::cli::parser< bool>::merge ( + this->pkg_bindist_, a.pkg_bindist_); + } + + 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" << ::std::endl + << " 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-bindist\033[0m|\033[1mbindist\033[0m \033[1mbpkg-pkg-bindist(1)\033[0m -- generate binary distribution" << ::std::endl + << " 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, &commands::help_ >; + _cli_commands_map_["cfg-create"] = + &::bpkg::cli::thunk< commands, &commands::cfg_create_ >; + _cli_commands_map_["create"] = + &::bpkg::cli::thunk< commands, &commands::cfg_create_ >; + _cli_commands_map_["cfg-info"] = + &::bpkg::cli::thunk< commands, &commands::cfg_info_ >; + _cli_commands_map_["cfg-link"] = + &::bpkg::cli::thunk< commands, &commands::cfg_link_ >; + _cli_commands_map_["link"] = + &::bpkg::cli::thunk< commands, &commands::cfg_link_ >; + _cli_commands_map_["cfg-unlink"] = + &::bpkg::cli::thunk< commands, &commands::cfg_unlink_ >; + _cli_commands_map_["unlink"] = + &::bpkg::cli::thunk< commands, &commands::cfg_unlink_ >; + _cli_commands_map_["rep-info"] = + &::bpkg::cli::thunk< commands, &commands::rep_info_ >; + _cli_commands_map_["rep-add"] = + &::bpkg::cli::thunk< commands, &commands::rep_add_ >; + _cli_commands_map_["add"] = + &::bpkg::cli::thunk< commands, &commands::rep_add_ >; + _cli_commands_map_["rep-remove"] = + &::bpkg::cli::thunk< commands, &commands::rep_remove_ >; + _cli_commands_map_["remove"] = + &::bpkg::cli::thunk< commands, &commands::rep_remove_ >; + _cli_commands_map_["rep-list"] = + &::bpkg::cli::thunk< commands, &commands::rep_list_ >; + _cli_commands_map_["list"] = + &::bpkg::cli::thunk< commands, &commands::rep_list_ >; + _cli_commands_map_["rep-fetch"] = + &::bpkg::cli::thunk< commands, &commands::rep_fetch_ >; + _cli_commands_map_["fetch"] = + &::bpkg::cli::thunk< commands, &commands::rep_fetch_ >; + _cli_commands_map_["rep-create"] = + &::bpkg::cli::thunk< commands, &commands::rep_create_ >; + _cli_commands_map_["pkg-status"] = + &::bpkg::cli::thunk< commands, &commands::pkg_status_ >; + _cli_commands_map_["status"] = + &::bpkg::cli::thunk< commands, &commands::pkg_status_ >; + _cli_commands_map_["pkg-build"] = + &::bpkg::cli::thunk< commands, &commands::pkg_build_ >; + _cli_commands_map_["build"] = + &::bpkg::cli::thunk< commands, &commands::pkg_build_ >; + _cli_commands_map_["pkg-drop"] = + &::bpkg::cli::thunk< commands, &commands::pkg_drop_ >; + _cli_commands_map_["drop"] = + &::bpkg::cli::thunk< commands, &commands::pkg_drop_ >; + _cli_commands_map_["pkg-install"] = + &::bpkg::cli::thunk< commands, &commands::pkg_install_ >; + _cli_commands_map_["install"] = + &::bpkg::cli::thunk< commands, &commands::pkg_install_ >; + _cli_commands_map_["pkg-uninstall"] = + &::bpkg::cli::thunk< commands, &commands::pkg_uninstall_ >; + _cli_commands_map_["uninstall"] = + &::bpkg::cli::thunk< commands, &commands::pkg_uninstall_ >; + _cli_commands_map_["pkg-update"] = + &::bpkg::cli::thunk< commands, &commands::pkg_update_ >; + _cli_commands_map_["update"] = + &::bpkg::cli::thunk< commands, &commands::pkg_update_ >; + _cli_commands_map_["pkg-test"] = + &::bpkg::cli::thunk< commands, &commands::pkg_test_ >; + _cli_commands_map_["test"] = + &::bpkg::cli::thunk< commands, &commands::pkg_test_ >; + _cli_commands_map_["pkg-clean"] = + &::bpkg::cli::thunk< commands, &commands::pkg_clean_ >; + _cli_commands_map_["clean"] = + &::bpkg::cli::thunk< commands, &commands::pkg_clean_ >; + _cli_commands_map_["pkg-bindist"] = + &::bpkg::cli::thunk< commands, &commands::pkg_bindist_ >; + _cli_commands_map_["bindist"] = + &::bpkg::cli::thunk< commands, &commands::pkg_bindist_ >; + _cli_commands_map_["pkg-verify"] = + &::bpkg::cli::thunk< commands, &commands::pkg_verify_ >; + _cli_commands_map_["pkg-fetch"] = + &::bpkg::cli::thunk< commands, &commands::pkg_fetch_ >; + _cli_commands_map_["pkg-unpack"] = + &::bpkg::cli::thunk< commands, &commands::pkg_unpack_ >; + _cli_commands_map_["pkg-checkout"] = + &::bpkg::cli::thunk< commands, &commands::pkg_checkout_ >; + _cli_commands_map_["pkg-configure"] = + &::bpkg::cli::thunk< commands, &commands::pkg_configure_ >; + _cli_commands_map_["pkg-disfigure"] = + &::bpkg::cli::thunk< commands, &commands::pkg_disfigure_ >; + _cli_commands_map_["pkg-purge"] = + &::bpkg::cli::thunk< commands, &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, &topics::common_options_ >; + _cli_topics_map_["default-options-files"] = + &::bpkg::cli::thunk< topics, &topics::default_options_files_ >; + _cli_topics_map_["repository-types"] = + &::bpkg::cli::thunk< topics, &topics::repository_types_ >; + _cli_topics_map_["repository-signing"] = + &::bpkg::cli::thunk< topics, &topics::repository_signing_ >; + _cli_topics_map_["argument-grouping"] = + &::bpkg::cli::thunk< topics, &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, &options::help_ >; + _cli_options_map_["--version"] = + &::bpkg::cli::thunk< options, &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..9dda684 --- /dev/null +++ b/bpkg/bpkg-options.hxx @@ -0,0 +1,391 @@ +// -*- 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_bindist () 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_bindist_; + 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..fe5b6d4 --- /dev/null +++ b/bpkg/bpkg-options.ixx @@ -0,0 +1,231 @@ +// -*- 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_bindist () const + { + return this->pkg_bindist_; + } + + 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..27979a1 --- /dev/null +++ b/bpkg/cfg-create-options.cxx @@ -0,0 +1,883 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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" << ::std::endl + << " creating the new configuration. For safety, this" << ::std::endl + << " option requires that you specify the configuration" << ::std::endl + << " directory 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" << ::std::endl + << " instead 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, &cfg_create_options::existing_ >; + _cli_cfg_create_options_map_["-e"] = + &::bpkg::cli::thunk< cfg_create_options, &cfg_create_options::existing_ >; + _cli_cfg_create_options_map_["--wipe"] = + &::bpkg::cli::thunk< cfg_create_options, &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, &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, &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..51758f4 --- /dev/null +++ b/bpkg/cfg-info-options.cxx @@ -0,0 +1,745 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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, &cfg_info_options::link_ >; + _cli_cfg_info_options_map_["--backlink"] = + &::bpkg::cli::thunk< cfg_info_options, &cfg_info_options::backlink_ >; + _cli_cfg_info_options_map_["--dangling"] = + &::bpkg::cli::thunk< cfg_info_options, &cfg_info_options::dangling_ >; + _cli_cfg_info_options_map_["--recursive"] = + &::bpkg::cli::thunk< cfg_info_options, &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..6479d14 --- /dev/null +++ b/bpkg/cfg-link-options.cxx @@ -0,0 +1,715 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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" << ::std::endl + << " relative 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, &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..82b08d6 --- /dev/null +++ b/bpkg/cfg-unlink-options.cxx @@ -0,0 +1,732 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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, &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..e841232 --- /dev/null +++ b/bpkg/common-options.cxx @@ -0,0 +1,2230 @@ +// -*- 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 () noexcept + { + } + + void unknown_option:: + print (::std::ostream& os) const + { + os << "unknown option '" << option ().c_str () << "'"; + } + + const char* unknown_option:: + what () const noexcept + { + return "unknown option"; + } + + // unknown_argument + // + unknown_argument:: + ~unknown_argument () noexcept + { + } + + void unknown_argument:: + print (::std::ostream& os) const + { + os << "unknown argument '" << argument ().c_str () << "'"; + } + + const char* unknown_argument:: + what () const noexcept + { + return "unknown argument"; + } + + // missing_value + // + missing_value:: + ~missing_value () noexcept + { + } + + void missing_value:: + print (::std::ostream& os) const + { + os << "missing value for option '" << option ().c_str () << "'"; + } + + const char* missing_value:: + what () const noexcept + { + return "missing option value"; + } + + // invalid_value + // + invalid_value:: + ~invalid_value () noexcept + { + } + + 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 noexcept + { + return "invalid option value"; + } + + // eos_reached + // + void eos_reached:: + print (::std::ostream& os) const + { + os << what (); + } + + const char* eos_reached:: + what () const noexcept + { + return "end of argument stream reached"; + } + + // file_io_failure + // + file_io_failure:: + ~file_io_failure () noexcept + { + } + + 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 noexcept + { + return "unable to open file or read failure"; + } + + // unmatched_quote + // + unmatched_quote:: + ~unmatched_quote () noexcept + { + } + + void unmatched_quote:: + print (::std::ostream& os) const + { + os << "unmatched quote in argument '" << argument ().c_str () << "'"; + } + + const char* unmatched_quote:: + what () const noexcept + { + return "unmatched quote"; + } + + // unexpected_group + // + unexpected_group:: + ~unexpected_group () noexcept + { + } + + void unexpected_group:: + print (::std::ostream& os) const + { + os << "unexpected grouped argument '" << group_ << "' " + << "for argument '" << argument_ << "'"; + } + + const char* unexpected_group:: + what () const noexcept + { + return "unexpected grouped argument"; + } + + // group_separator + // + group_separator:: + ~group_separator () noexcept + { + } + + 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 noexcept + { + 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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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_ (), + structured_result_ (), + structured_result_specified_ (false), + progress_ (), + no_progress_ (), + diag_color_ (), + no_diag_color_ (), + build_ (), + build_specified_ (false), + build_option_ (), + build_option_specified_ (false), + fetch_ (), + fetch_specified_ (false), + fetch_option_ (), + fetch_option_specified_ (false), + curl_ (), + curl_specified_ (false), + curl_option_ (), + curl_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_ (), + git_capabilities_ (), + git_capabilities_specified_ (false), + 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_ (), + keep_tmp_ () + { + } + + 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.structured_result_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->structured_result_, a.structured_result_); + this->structured_result_specified_ = true; + } + + 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.diag_color_) + { + ::bpkg::cli::parser< bool>::merge ( + this->diag_color_, a.diag_color_); + } + + if (a.no_diag_color_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_diag_color_, a.no_diag_color_); + } + + 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.curl_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->curl_, a.curl_); + this->curl_specified_ = true; + } + + if (a.curl_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->curl_option_, a.curl_option_); + this->curl_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.git_capabilities_specified_) + { + ::bpkg::cli::parser< git_capabilities_map>::merge ( + this->git_capabilities_, a.git_capabilities_); + this->git_capabilities_specified_ = true; + } + + 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_); + } + + if (a.keep_tmp_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_tmp_, a.keep_tmp_); + } + } + + ::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--structured-result\033[0m \033[4mfmt\033[0m Write the result of performing a command in a" << ::std::endl + << " structured form." << ::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--diag-color\033[0m Use color in diagnostics." << ::std::endl; + + os << "\033[1m--no-diag-color\033[0m Don't use color in diagnostics." << ::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" << ::std::endl + << " 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" << ::std::endl + << " \033[1mno\033[0m." << ::std::endl; + + os << "\033[1m--git-capabilities\033[0m \033[4mup\033[0m=\033[4mpc\033[0m Protocol capabilities (\033[4mpc\033[0m) for a \033[1mgit\033[0m repository URL" << ::std::endl + << " prefix (\033[4mup\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" << ::std::endl + << " files from." << ::std::endl; + + os << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + os << "\033[1m--keep-tmp\033[0m Don't remove the \033[1mbpkg\033[0m's temporary directory at the" << ::std::endl + << " end of the command execution and print its path at" << ::std::endl + << " the verbosity level 2 or higher." << ::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" << ::std::endl + << " level 6 produces lots of information, with level 1" << ::std::endl + << " being the default. The following additional types of" << ::std::endl + << " diagnostics 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" << ::std::endl + << " 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" << ::std::endl + << " on 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." << ::std::endl + << " This option is also propagated when performing build" << ::std::endl + << " system 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--structured-result\033[0m \033[4mfmt\033[0m Write the result of performing a command in a" << ::std::endl + << " structured form. In this mode, instead of printing to" << ::std::endl + << " \033[1mstderr\033[0m informational messages about the outcome of" << ::std::endl + << " performing a command or some of its parts, \033[1mbpkg\033[0m" << ::std::endl + << " writes to \033[1mstdout\033[0m a machine-readable result" << ::std::endl + << " description in the specified format. Not all commands" << ::std::endl + << " support producing structured result and valid \033[4mfmt\033[0m" << ::std::endl + << " values are command-specific. Consult the command" << ::std::endl + << " documentation for details." << ::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" << ::std::endl + << " by default for low verbosity levels. Use" << ::std::endl + << " \033[1m--no-progress\033[0m to 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--diag-color\033[0m Use color in diagnostics. If printing to a terminal" << ::std::endl + << " the color is used by default provided the terminal is" << ::std::endl + << " not dumb. Use \033[1m--no-diag-color\033[0m to suppress." << ::std::endl; + + os << std::endl + << "\033[1m--no-diag-color\033[0m Don't use color in diagnostics." << ::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" << ::std::endl + << " can also specify additional options that should be" << ::std::endl + << " passed to the build program with \033[1m--build-option\033[0m." << ::std::endl + << ::std::endl + << " If the build program is not explicitly specified," << ::std::endl + << " then \033[1mbpkg\033[0m will by default use \033[1mb\033[0m plus an executable" << ::std::endl + << " suffix if one was specified when building \033[1mbpkg\033[0m. So," << ::std::endl + << " for example, if \033[1mbpkg\033[0m name was set to \033[1mbpkg-1.0\033[0m, then" << ::std::endl + << " it 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" << ::std::endl + << " program. Repeat this option to specify multiple build" << ::std::endl + << " 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." << ::std::endl + << " Note that the last component of \033[4mpath\033[0m must contain one" << ::std::endl + << " of 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[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" << ::std::endl + << " program. Repeat this option to specify multiple fetch" << ::std::endl + << " 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" << ::std::endl + << " specifies in seconds the maximum time that can be" << ::std::endl + << " spent without 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" << ::std::endl + << " fetch program from tunneling (which is the standard" << ::std::endl + << " approach 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" << ::std::endl + << " (for example, host name). For security, this" << ::std::endl + << " mechanism should only be used with signed" << ::std::endl + << " repositories or when the proxy is located inside a" << ::std::endl + << " 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" << ::std::endl + << " be 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" << ::std::endl + << " for \033[1mbpkg\033[0m to recognize which program is being used." << ::std::endl + << " You can also specify additional options that should" << ::std::endl + << " be passed 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" << ::std::endl + << " will 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" << ::std::endl + << " sha256 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" << ::std::endl + << " by 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." << ::std::endl + << " See \033[1m--tar\033[0m for more information on the tar program." << ::std::endl + << " Repeat 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" << ::std::endl + << " be passed to the openssl program with" << ::std::endl + << " \033[1m--openssl-option\033[0m. If the openssl program is not" << ::std::endl + << " explicitly specified, then \033[1mbpkg\033[0m will use \033[1mopenssl\033[0m by" << ::std::endl + << " default." << ::std::endl + << ::std::endl + << " The \033[1m--openssl*\033[0m values can be optionally qualified" << ::std::endl + << " with the openssl command in the \033[4mcommand\033[0m\033[1m:\033[0m\033[4mvalue\033[0m\033[0m form." << ::std::endl + << " This 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" << ::std::endl + << " program. See \033[1m--openssl\033[0m for more information on the" << ::std::endl + << " openssl program. The values can be optionally" << ::std::endl + << " qualified with the openssl command, as discussed in" << ::std::endl + << " \033[1m--openssl\033[0m. Repeat this option to specify multiple" << ::std::endl + << " 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" << ::std::endl + << " only remote repositories are authenticated. You can" << ::std::endl + << " request authentication of local repositories by" << ::std::endl + << " passing \033[1mall\033[0m or disable authentication completely by" << ::std::endl + << " 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" << ::std::endl + << " fingerprint and to obtain a SHA256 one you will need" << ::std::endl + << " to pass the \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" << ::std::endl + << " \033[1mno\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--git-capabilities\033[0m \033[4mup\033[0m=\033[4mpc\033[0m Protocol capabilities (\033[4mpc\033[0m) for a \033[1mgit\033[0m repository URL" << ::std::endl + << " prefix (\033[4mup\033[0m). Valid values for the capabilities are" << ::std::endl + << " \033[1mdumb\033[0m (no shallow clone support), \033[1msmart\033[0m (support for" << ::std::endl + << " shallow clone, but not for fetching unadvertised" << ::std::endl + << " commits), \033[1munadv\033[0m (support for shallow clone and for" << ::std::endl + << " fetching unadvertised commits). For example:" << ::std::endl + << ::std::endl + << " bpkg build https://example.org/foo.git#master \\" << ::std::endl + << " --git-capabilities https://example.org=smart" << ::std::endl + << ::std::endl + << " See \033[1mbpkg-repository-types(1)\033[0m for details on the \033[1mgit\033[0m" << ::std::endl + << " protocol capabilities." << ::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" << ::std::endl + << " an empty string is specified as the pager program," << ::std::endl + << " then no pager will be used. If the pager program is" << ::std::endl + << " not explicitly specified, then \033[1mbpkg\033[0m will try to use" << ::std::endl + << " \033[1mless\033[0m. If it is not available, then no pager will be" << ::std::endl + << " 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" << ::std::endl + << " program. Repeat this option to specify multiple pager" << ::std::endl + << " 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" << ::std::endl + << " space or equal sign (\033[1m=\033[0m) and an option value. Empty" << ::std::endl + << " lines and lines starting with \033[1m#\033[0m are ignored. Option" << ::std::endl + << " values can be enclosed in double (\033[1m\"\033[0m) or single (\033[1m'\033[0m)" << ::std::endl + << " quotes to preserve leading and trailing whitespaces" << ::std::endl + << " as well as to specify empty values. If the value" << ::std::endl + << " itself contains trailing or leading quotes, enclose" << ::std::endl + << " it with an extra pair of quotes, for example \033[1m'\"x\"'\033[0m." << ::std::endl + << " Non-leading and non-trailing quotes are interpreted" << ::std::endl + << " as being part of 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" << ::std::endl + << " the same order on the command line at the point where" << ::std::endl + << " the \033[1m--options-file\033[0m option is specified except that" << ::std::endl + << " the shell escaping and quoting is not required." << ::std::endl + << " Repeat this option to specify more than one options" << ::std::endl + << " file." << ::std::endl; + + os << std::endl + << "\033[1m--default-options\033[0m \033[4mdir\033[0m The directory to load additional default options" << ::std::endl + << " files from." << ::std::endl; + + os << std::endl + << "\033[1m--no-default-options\033[0m Don't load default options files." << ::std::endl; + + os << std::endl + << "\033[1m--keep-tmp\033[0m Don't remove the \033[1mbpkg\033[0m's temporary directory at the" << ::std::endl + << " end of the command execution and print its path at" << ::std::endl + << " the verbosity level 2 or higher. This option is" << ::std::endl + << " primarily useful for troubleshooting." << ::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, &common_options::v_ >; + _cli_common_options_map_["-V"] = + &::bpkg::cli::thunk< common_options, &common_options::V_ >; + _cli_common_options_map_["--quiet"] = + &::bpkg::cli::thunk< common_options, &common_options::quiet_ >; + _cli_common_options_map_["-q"] = + &::bpkg::cli::thunk< common_options, &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, &common_options::no_result_ >; + _cli_common_options_map_["--structured-result"] = + &::bpkg::cli::thunk< common_options, string, &common_options::structured_result_, + &common_options::structured_result_specified_ >; + _cli_common_options_map_["--progress"] = + &::bpkg::cli::thunk< common_options, &common_options::progress_ >; + _cli_common_options_map_["--no-progress"] = + &::bpkg::cli::thunk< common_options, &common_options::no_progress_ >; + _cli_common_options_map_["--diag-color"] = + &::bpkg::cli::thunk< common_options, &common_options::diag_color_ >; + _cli_common_options_map_["--no-diag-color"] = + &::bpkg::cli::thunk< common_options, &common_options::no_diag_color_ >; + _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_["--curl"] = + &::bpkg::cli::thunk< common_options, path, &common_options::curl_, + &common_options::curl_specified_ >; + _cli_common_options_map_["--curl-option"] = + &::bpkg::cli::thunk< common_options, strings, &common_options::curl_option_, + &common_options::curl_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, &common_options::trust_yes_ >; + _cli_common_options_map_["--trust-no"] = + &::bpkg::cli::thunk< common_options, &common_options::trust_no_ >; + _cli_common_options_map_["--git-capabilities"] = + &::bpkg::cli::thunk< common_options, git_capabilities_map, &common_options::git_capabilities_, + &common_options::git_capabilities_specified_ >; + _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, &common_options::no_default_options_ >; + _cli_common_options_map_["--keep-tmp"] = + &::bpkg::cli::thunk< common_options, &common_options::keep_tmp_ >; + } + }; + + 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..0df9871 --- /dev/null +++ b/bpkg/common-options.hxx @@ -0,0 +1,1235 @@ +// -*- 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 () noexcept; + + unknown_option (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string option_; + }; + + class unknown_argument: public exception + { + public: + virtual + ~unknown_argument () noexcept; + + unknown_argument (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string argument_; + }; + + class missing_value: public exception + { + public: + virtual + ~missing_value () noexcept; + + missing_value (const std::string& option); + + const std::string& + option () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string option_; + }; + + class invalid_value: public exception + { + public: + virtual + ~invalid_value () noexcept; + + 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 noexcept; + + 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 noexcept; + }; + + class file_io_failure: public exception + { + public: + virtual + ~file_io_failure () noexcept; + + file_io_failure (const std::string& file); + + const std::string& + file () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string file_; + }; + + class unmatched_quote: public exception + { + public: + virtual + ~unmatched_quote () noexcept; + + unmatched_quote (const std::string& argument); + + const std::string& + argument () const; + + virtual void + print (::std::ostream&) const; + + virtual const char* + what () const noexcept; + + private: + std::string argument_; + }; + + class unexpected_group: public exception + { + public: + virtual + ~unexpected_group () noexcept; + + 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 noexcept; + + private: + std::string argument_; + std::string group_; + }; + + class group_separator: public exception + { + public: + virtual + ~group_separator () noexcept; + + // 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 noexcept; + + 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 string& + structured_result () const; + + string& + structured_result (); + + void + structured_result (const string&); + + bool + structured_result_specified () const; + + void + structured_result_specified (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 bool& + diag_color () const; + + bool& + diag_color (); + + void + diag_color (const bool&); + + const bool& + no_diag_color () const; + + bool& + no_diag_color (); + + void + no_diag_color (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 path& + curl () const; + + path& + curl (); + + void + curl (const path&); + + bool + curl_specified () const; + + void + curl_specified (bool); + + const strings& + curl_option () const; + + strings& + curl_option (); + + void + curl_option (const strings&); + + bool + curl_option_specified () const; + + void + curl_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 git_capabilities_map& + git_capabilities () const; + + git_capabilities_map& + git_capabilities (); + + void + git_capabilities (const git_capabilities_map&); + + bool + git_capabilities_specified () const; + + void + git_capabilities_specified (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&); + + const bool& + keep_tmp () const; + + bool& + keep_tmp (); + + void + keep_tmp (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_; + string structured_result_; + bool structured_result_specified_; + bool progress_; + bool no_progress_; + bool diag_color_; + bool no_diag_color_; + path build_; + bool build_specified_; + strings build_option_; + bool build_option_specified_; + path fetch_; + bool fetch_specified_; + strings fetch_option_; + bool fetch_option_specified_; + path curl_; + bool curl_specified_; + strings curl_option_; + bool curl_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_; + git_capabilities_map git_capabilities_; + bool git_capabilities_specified_; + 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_; + bool keep_tmp_; + }; +} + +// 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..ed27ac3 --- /dev/null +++ b/bpkg/common-options.ixx @@ -0,0 +1,1436 @@ +// -*- 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 string& common_options:: + structured_result () const + { + return this->structured_result_; + } + + inline string& common_options:: + structured_result () + { + return this->structured_result_; + } + + inline void common_options:: + structured_result (const string& x) + { + this->structured_result_ = x; + } + + inline bool common_options:: + structured_result_specified () const + { + return this->structured_result_specified_; + } + + inline void common_options:: + structured_result_specified (bool x) + { + this->structured_result_specified_ = 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 bool& common_options:: + diag_color () const + { + return this->diag_color_; + } + + inline bool& common_options:: + diag_color () + { + return this->diag_color_; + } + + inline void common_options:: + diag_color (const bool& x) + { + this->diag_color_ = x; + } + + inline const bool& common_options:: + no_diag_color () const + { + return this->no_diag_color_; + } + + inline bool& common_options:: + no_diag_color () + { + return this->no_diag_color_; + } + + inline void common_options:: + no_diag_color (const bool& x) + { + this->no_diag_color_ = 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 path& common_options:: + curl () const + { + return this->curl_; + } + + inline path& common_options:: + curl () + { + return this->curl_; + } + + inline void common_options:: + curl (const path& x) + { + this->curl_ = x; + } + + inline bool common_options:: + curl_specified () const + { + return this->curl_specified_; + } + + inline void common_options:: + curl_specified (bool x) + { + this->curl_specified_ = x; + } + + inline const strings& common_options:: + curl_option () const + { + return this->curl_option_; + } + + inline strings& common_options:: + curl_option () + { + return this->curl_option_; + } + + inline void common_options:: + curl_option (const strings& x) + { + this->curl_option_ = x; + } + + inline bool common_options:: + curl_option_specified () const + { + return this->curl_option_specified_; + } + + inline void common_options:: + curl_option_specified (bool x) + { + this->curl_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 git_capabilities_map& common_options:: + git_capabilities () const + { + return this->git_capabilities_; + } + + inline git_capabilities_map& common_options:: + git_capabilities () + { + return this->git_capabilities_; + } + + inline void common_options:: + git_capabilities (const git_capabilities_map& x) + { + this->git_capabilities_ = x; + } + + inline bool common_options:: + git_capabilities_specified () const + { + return this->git_capabilities_specified_; + } + + inline void common_options:: + git_capabilities_specified (bool x) + { + this->git_capabilities_specified_ = 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; + } + + inline const bool& common_options:: + keep_tmp () const + { + return this->keep_tmp_; + } + + inline bool& common_options:: + keep_tmp () + { + return this->keep_tmp_; + } + + inline void common_options:: + keep_tmp (const bool& x) + { + this->keep_tmp_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/configuration-options.cxx b/bpkg/configuration-options.cxx new file mode 100644 index 0000000..9790132 --- /dev/null +++ b/bpkg/configuration-options.cxx @@ -0,0 +1,653 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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..72c5745 --- /dev/null +++ b/bpkg/default-options-files.cxx @@ -0,0 +1,91 @@ +// -*- 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> + +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/fetch-git.cxx b/bpkg/fetch-git.cxx index 5d2e5fe..c283626 100644 --- a/bpkg/fetch-git.cxx +++ b/bpkg/fetch-git.cxx @@ -119,7 +119,8 @@ namespace bpkg template <typename O, typename E, typename... A> static process - start_git (const common_options& co, + start_git (uint16_t verbosity, + const common_options& co, O&& out, E&& err, A&&... args) @@ -162,7 +163,8 @@ namespace bpkg // We assume that non-sanitized git environment can't harm this call. // - process pr (start_git (co, + process pr (start_git (2 /* verbosity */, + co, pipe, 2 /* stderr */, co.git_option (), "rev-parse", @@ -231,9 +233,10 @@ namespace bpkg ep = "--exec-path=" + pp.effect.directory ().string (); #endif - return process_start_callback ([] (const char* const args[], size_t n) + return process_start_callback ([verbosity] (const char* const args[], + size_t n) { - if (verb >= 2) + if (verb >= verbosity) print_process (args, n); }, 0 /* stdin */, out, err, @@ -247,6 +250,16 @@ namespace bpkg } } + template <typename O, typename E, typename... A> + inline static process + start_git (const common_options& co, + O&& out, + E&& err, + A&&... args) + { + return start_git (2 /* verbosity */, co, out, err, forward<A> (args)...); + } + // Run git process, optionally suppressing progress. // template <typename... A> @@ -2569,7 +2582,8 @@ namespace bpkg path tp; fdpipe pipe (open_pipe ()); - process pr (start_git (co, + process pr (start_git (3 /* verbosity */, + co, pipe, 2 /* stderr */, co.git_option (), "-C", dir, diff --git a/bpkg/help-options.cxx b/bpkg/help-options.cxx new file mode 100644 index 0000000..4a7244e --- /dev/null +++ b/bpkg/help-options.cxx @@ -0,0 +1,657 @@ +// -*- 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> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +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..aa7e156 --- /dev/null +++ b/bpkg/package-odb.cxx @@ -0,0 +1,19100 @@ +// -*- 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/section-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); + } + } + + // language + // + + bool access::composite_value_traits< ::bpkg::language, 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; + } + + // impl + // + t[1UL] = false; + + return grew; + } + + void access::composite_value_traits< ::bpkg::language, 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< + ::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++; + + // impl + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.impl_value; + b[n].is_null = &i.impl_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::language, 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 + // + { + ::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 ()); + } + + // impl + // + { + bool const& v = + o.impl; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.impl_value, + is_null, + v); + i.impl_null = is_null; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::language, 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 + // + { + ::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); + } + + // impl + // + { + bool& v = + o.impl; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.impl_value, + i.impl_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:325: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:325: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:325: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:325: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; + + // enable + // + if (t[19UL]) + { + i.enable_value.capacity (i.enable_size); + grew = true; + } + + // reflect + // + if (t[20UL]) + { + 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++; + + // 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++; + } + + 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:629: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; + } + + // 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 ()); + } + + 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:629: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); + } + + // 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); + } + } + + // buildfile + // + + bool access::composite_value_traits< ::bpkg::buildfile, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // path + // + if (t[0UL]) + { + i.path_value.capacity (i.path_size); + grew = true; + } + + // content + // + if (t[1UL]) + { + i.content_value.capacity (i.content_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::buildfile, 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); + + // 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++; + + // content + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.content_value.data (); + b[n].size = &i.content_size; + b[n].capacity = i.content_value.capacity (); + b[n].is_null = &i.content_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::buildfile, 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); + + // path + // + { + ::butl::path const& v = + o.path; + + // From package.hxx:50:14 + ::std::string const& vt = + (v).representation (); + + 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 ()); + } + + // content + // + { + ::std::string const& v = + o.content; + + bool is_null (false); + std::size_t cap (i.content_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.content_value, + i.content_size, + is_null, + v); + i.content_null = is_null; + grew = grew || (cap != i.content_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::buildfile, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // path + // + { + ::butl::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:50:14 + v = bpkg::path (vt); + } + + // content + // + { + ::std::string& v = + o.content; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.content_value, + i.content_size, + i.content_null); + } + } + + // distribution_name_value + // + + bool access::composite_value_traits< ::bpkg::distribution_name_value, 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; + } + + // value + // + if (t[1UL]) + { + i.value_value.capacity (i.value_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::distribution_name_value, 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< + ::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++; + + // value + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.value_value.data (); + b[n].size = &i.value_size; + b[n].capacity = i.value_value.capacity (); + b[n].is_null = &i.value_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::distribution_name_value, 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 + // + { + ::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 ()); + } + + // value + // + { + ::std::string const& v = + o.value; + + bool is_null (false); + std::size_t cap (i.value_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.value_value, + i.value_size, + is_null, + v); + i.value_null = is_null; + grew = grew || (cap != i.value_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::distribution_name_value, 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 + // + { + ::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); + } + + // value + // + { + ::std::string& v = + o.value; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.value_value, + i.value_size, + i.value_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:66: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:57: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:66: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:57: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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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:276: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:281: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:277: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:277:7 + o = bpkg::version (0, std::move (v), std::string (), bpkg::nullopt, 0); + } + + // release_ + // + { + // From package.hxx:282: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:282: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:358: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:362: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:358: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:362: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:368: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:437: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:368:14 + v = bpkg::repository_location (std::move ((vt).url), (vt).type); + // From package.hxx:437: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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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:452: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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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:368: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:501: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:368:14 + v = bpkg::repository_location (std::move ((vt).url), (vt).type); + // From package.hxx:501: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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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:512: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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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:50: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:50: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:633: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:633: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< languages_traits > languages; + 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; + sqlite::container_statements_impl< buildfiles_traits > buildfiles; + sqlite::container_statements_impl< distribution_values_traits > distribution_values; + + sqlite::section_statements< ::bpkg::available_package, languages_section_traits > languages_section; + + extra_statement_cache_type ( + sqlite::connection& c, + image_type& im, + id_image_type& idim, + sqlite::binding& id, + sqlite::binding& idv) + : languages (c, id), + locations (c, id), + dependencies (c, id), + dependency_alternatives (c, id), + dependency_alternative_dependencies (c, id), + tests (c, id), + buildfiles (c, id), + distribution_values (c, id), + languages_section (c, im, idim, id, idv) + { + } + }; + + // languages + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::languages_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_languages\".\"index\", " + "\"main\".\"available_package_languages\".\"language_name\", " + "\"main\".\"available_package_languages\".\"language_impl\" " + "FROM \"main\".\"available_package_languages\" " + "WHERE \"main\".\"available_package_languages\".\"name\"=? AND \"main\".\"available_package_languages\".\"version_epoch\"=? AND \"main\".\"available_package_languages\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_languages\".\"version_canonical_release\"=? AND \"main\".\"available_package_languages\".\"version_revision\"=? AND \"main\".\"available_package_languages\".\"version_iteration\"=? ORDER BY \"main\".\"available_package_languages\".\"index\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::languages_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_languages\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"index\", " + "\"language_name\", " + "\"language_impl\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::languages_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_languages\" " + "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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_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 >::languages_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // 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_alternative_dependencies_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_alternative_dependencies_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::erase (fs); + } + + // tests + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::tests_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_tests\".\"index\", " + "\"main\".\"available_package_tests\".\"test_name\", " + "\"main\".\"available_package_tests\".\"test_min_version_epoch\", " + "\"main\".\"available_package_tests\".\"test_min_version_canonical_upstream\", " + "\"main\".\"available_package_tests\".\"test_min_version_canonical_release\", " + "\"main\".\"available_package_tests\".\"test_min_version_revision\", " + "\"main\".\"available_package_tests\".\"test_min_version_iteration\", " + "\"main\".\"available_package_tests\".\"test_min_version_upstream\", " + "\"main\".\"available_package_tests\".\"test_min_version_release\", " + "\"main\".\"available_package_tests\".\"test_max_version_epoch\", " + "\"main\".\"available_package_tests\".\"test_max_version_canonical_upstream\", " + "\"main\".\"available_package_tests\".\"test_max_version_canonical_release\", " + "\"main\".\"available_package_tests\".\"test_max_version_revision\", " + "\"main\".\"available_package_tests\".\"test_max_version_iteration\", " + "\"main\".\"available_package_tests\".\"test_max_version_upstream\", " + "\"main\".\"available_package_tests\".\"test_max_version_release\", " + "\"main\".\"available_package_tests\".\"test_min_open\", " + "\"main\".\"available_package_tests\".\"test_max_open\", " + "\"main\".\"available_package_tests\".\"test_type\", " + "\"main\".\"available_package_tests\".\"test_buildtime\", " + "\"main\".\"available_package_tests\".\"test_enable\", " + "\"main\".\"available_package_tests\".\"test_reflect\" " + "FROM \"main\".\"available_package_tests\" " + "WHERE \"main\".\"available_package_tests\".\"name\"=? AND \"main\".\"available_package_tests\".\"version_epoch\"=? AND \"main\".\"available_package_tests\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_tests\".\"version_canonical_release\"=? AND \"main\".\"available_package_tests\".\"version_revision\"=? AND \"main\".\"available_package_tests\".\"version_iteration\"=? ORDER BY \"main\".\"available_package_tests\".\"index\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::tests_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_tests\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"index\", " + "\"test_name\", " + "\"test_min_version_epoch\", " + "\"test_min_version_canonical_upstream\", " + "\"test_min_version_canonical_release\", " + "\"test_min_version_revision\", " + "\"test_min_version_iteration\", " + "\"test_min_version_upstream\", " + "\"test_min_version_release\", " + "\"test_max_version_epoch\", " + "\"test_max_version_canonical_upstream\", " + "\"test_max_version_canonical_release\", " + "\"test_max_version_revision\", " + "\"test_max_version_iteration\", " + "\"test_max_version_upstream\", " + "\"test_max_version_release\", " + "\"test_min_open\", " + "\"test_max_open\", " + "\"test_type\", " + "\"test_buildtime\", " + "\"test_enable\", " + "\"test_reflect\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::tests_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_tests\" " + "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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_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 >::tests_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // buildfiles + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::buildfiles_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_buildfiles\".\"index\", " + "\"main\".\"available_package_buildfiles\".\"path\", " + "\"main\".\"available_package_buildfiles\".\"content\" " + "FROM \"main\".\"available_package_buildfiles\" " + "WHERE \"main\".\"available_package_buildfiles\".\"name\"=? AND \"main\".\"available_package_buildfiles\".\"version_epoch\"=? AND \"main\".\"available_package_buildfiles\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_buildfiles\".\"version_canonical_release\"=? AND \"main\".\"available_package_buildfiles\".\"version_revision\"=? AND \"main\".\"available_package_buildfiles\".\"version_iteration\"=? ORDER BY \"main\".\"available_package_buildfiles\".\"index\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::buildfiles_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_buildfiles\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"index\", " + "\"path\", " + "\"content\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::buildfiles_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_buildfiles\" " + "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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_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 >::buildfiles_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // distribution_values + // + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::distribution_values_traits:: + select_statement[] = + "SELECT " + "\"main\".\"available_package_distribution_values\".\"index\", " + "\"main\".\"available_package_distribution_values\".\"dist_name\", " + "\"main\".\"available_package_distribution_values\".\"dist_value\" " + "FROM \"main\".\"available_package_distribution_values\" " + "WHERE \"main\".\"available_package_distribution_values\".\"name\"=? AND \"main\".\"available_package_distribution_values\".\"version_epoch\"=? AND \"main\".\"available_package_distribution_values\".\"version_canonical_upstream\"=? AND \"main\".\"available_package_distribution_values\".\"version_canonical_release\"=? AND \"main\".\"available_package_distribution_values\".\"version_revision\"=? AND \"main\".\"available_package_distribution_values\".\"version_iteration\"=? ORDER BY \"main\".\"available_package_distribution_values\".\"index\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::distribution_values_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"available_package_distribution_values\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"index\", " + "\"dist_name\", " + "\"dist_value\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::distribution_values_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"available_package_distribution_values\" " + "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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_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 >::distribution_values_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // languages_section + // + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::languages_section_traits:: + load (extra_statement_cache_type& esc, object_type& obj) + { + // languages + // + { + ::butl::small_vector< ::bpkg::language, 1 >& v = + obj.languages; + + languages_traits::load ( + v, + esc.languages); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >::languages_section_traits:: + update (extra_statement_cache_type& esc, const object_type& obj) + { + // languages + // + { + ::butl::small_vector< ::bpkg::language, 1 > const& v = + obj.languages; + + languages_traits::update ( + v, + esc.languages); + } + } + + access::object_traits_impl< ::bpkg::available_package, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + id (const image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::init ( + id, + i.id_value, + db); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // id + // + if (composite_value_traits< ::bpkg::available_package_id, id_sqlite >::grow ( + i.id_value, t + 0UL)) + grew = true; + + // version + // + if (composite_value_traits< ::bpkg::available_package::upstream_version_type, id_sqlite >::grow ( + i.version_value, t + 6UL)) + grew = true; + + // upstream_version + // + if (t[8UL]) + { + i.upstream_version_value.capacity (i.upstream_version_size); + grew = true; + } + + // type + // + if (t[9UL]) + { + i.type_value.capacity (i.type_size); + grew = true; + } + + // project + // + if (t[10UL]) + { + i.project_value.capacity (i.project_size); + grew = true; + } + + // alt_naming + // + t[11UL] = false; + + // bootstrap_build + // + if (t[12UL]) + { + i.bootstrap_build_value.capacity (i.bootstrap_build_size); + grew = true; + } + + // root_build + // + if (t[13UL]) + { + i.root_build_value.capacity (i.root_build_size); + grew = true; + } + + // sha256sum + // + if (t[14UL]) + { + i.sha256sum_value.capacity (i.sha256sum_size); + grew = true; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::available_package, 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) + { + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::bind ( + b + n, i.id_value, sk); + n += 6UL; + } + + // version + // + composite_value_traits< ::bpkg::available_package::upstream_version_type, id_sqlite >::bind ( + b + n, i.version_value, sk); + n += 2UL; + + // upstream_version + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.upstream_version_value.data (); + b[n].size = &i.upstream_version_size; + b[n].capacity = i.upstream_version_value.capacity (); + b[n].is_null = &i.upstream_version_null; + n++; + + // type + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + 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++; + + // project + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::butl::project_name >, + sqlite::id_text>::bind_value; + b[n].buffer = i.project_value.data (); + b[n].size = &i.project_size; + b[n].capacity = i.project_value.capacity (); + b[n].is_null = &i.project_null; + n++; + + // alt_naming + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.alt_naming_value; + b[n].is_null = &i.alt_naming_null; + n++; + + // bootstrap_build + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.bootstrap_build_value.data (); + b[n].size = &i.bootstrap_build_size; + b[n].capacity = i.bootstrap_build_value.capacity (); + b[n].is_null = &i.bootstrap_build_null; + n++; + + // root_build + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.root_build_value.data (); + b[n].size = &i.root_build_size; + b[n].capacity = i.root_build_value.capacity (); + b[n].is_null = &i.root_build_null; + n++; + + // sha256sum + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.sha256sum_value.data (); + b[n].size = &i.sha256sum_size; + b[n].capacity = i.sha256sum_value.capacity (); + b[n].is_null = &i.sha256sum_null; + n++; + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + bind (sqlite::bind* b, id_image_type& i) + { + std::size_t n (0); + sqlite::statement_kind sk (sqlite::statement_select); + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::bind ( + b + n, i.id_value, sk); + } + + bool access::object_traits_impl< ::bpkg::available_package, 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::available_package_id const& v = + o.id; + + if (composite_value_traits< ::bpkg::available_package_id, id_sqlite >::init ( + i.id_value, + v, + sk)) + grew = true; + } + + // version + // + { + ::bpkg::available_package::upstream_version_type const& v = + o.version; + + if (composite_value_traits< ::bpkg::available_package::upstream_version_type, id_sqlite >::init ( + i.version_value, + v, + sk)) + grew = true; + } + + // upstream_version + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.upstream_version; + + bool is_null (true); + std::size_t cap (i.upstream_version_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.upstream_version_value, + i.upstream_version_size, + is_null, + v); + i.upstream_version_null = is_null; + grew = grew || (cap != i.upstream_version_value.capacity ()); + } + + // type + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.type; + + bool is_null (true); + std::size_t cap (i.type_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + 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 ()); + } + + // project + // + { + ::butl::optional< ::butl::project_name > const& v = + o.project; + + bool is_null (true); + std::size_t cap (i.project_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::butl::project_name >, + sqlite::id_text >::set_image ( + i.project_value, + i.project_size, + is_null, + v); + i.project_null = is_null; + grew = grew || (cap != i.project_value.capacity ()); + } + + // alt_naming + // + { + ::butl::optional< bool > const& v = + o.alt_naming; + + bool is_null (true); + sqlite::value_traits< + ::butl::optional< bool >, + sqlite::id_integer >::set_image ( + i.alt_naming_value, + is_null, + v); + i.alt_naming_null = is_null; + } + + // bootstrap_build + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.bootstrap_build; + + bool is_null (true); + std::size_t cap (i.bootstrap_build_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.bootstrap_build_value, + i.bootstrap_build_size, + is_null, + v); + i.bootstrap_build_null = is_null; + grew = grew || (cap != i.bootstrap_build_value.capacity ()); + } + + // root_build + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.root_build; + + bool is_null (true); + std::size_t cap (i.root_build_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.root_build_value, + i.root_build_size, + is_null, + v); + i.root_build_null = is_null; + grew = grew || (cap != i.root_build_value.capacity ()); + } + + // sha256sum + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.sha256sum; + + bool is_null (true); + std::size_t cap (i.sha256sum_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.sha256sum_value, + i.sha256sum_size, + is_null, + v); + i.sha256sum_null = is_null; + grew = grew || (cap != i.sha256sum_value.capacity ()); + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::available_package, 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::available_package_id& v = + o.id; + + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::init ( + v, + i.id_value, + db); + } + + // version + // + { + // From package.hxx:830:32 + ::bpkg::available_package::upstream_version_type v; + + composite_value_traits< ::bpkg::available_package::upstream_version_type, id_sqlite >::init ( + v, + i.version_value, + db); + + // From package.hxx:830:32 + o.version.init (o.id.version, (v)); + } + + // upstream_version + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.upstream_version; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.upstream_version_value, + i.upstream_version_size, + i.upstream_version_null); + } + + // type + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.type; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.type_value, + i.type_size, + i.type_null); + } + + // project + // + { + ::butl::optional< ::butl::project_name >& v = + o.project; + + sqlite::value_traits< + ::butl::optional< ::butl::project_name >, + sqlite::id_text >::set_value ( + v, + i.project_value, + i.project_size, + i.project_null); + } + + // alt_naming + // + { + ::butl::optional< bool >& v = + o.alt_naming; + + sqlite::value_traits< + ::butl::optional< bool >, + sqlite::id_integer >::set_value ( + v, + i.alt_naming_value, + i.alt_naming_null); + } + + // bootstrap_build + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.bootstrap_build; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.bootstrap_build_value, + i.bootstrap_build_size, + i.bootstrap_build_null); + } + + // root_build + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.root_build; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.root_build_value, + i.root_build_size, + i.root_build_null); + } + + // sha256sum + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.sha256sum; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.sha256sum_value, + i.sha256sum_size, + i.sha256sum_null); + } + } + + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + init (id_image_type& i, const id_type& id) + { + bool grew (false); + sqlite::statement_kind sk (sqlite::statement_select); + { + if (composite_value_traits< ::bpkg::available_package_id, id_sqlite >::init ( + i.id_value, + id, + sk)) + grew = true; + } + + if (grew) + i.version++; + } + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"available_package\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"version_upstream\", " + "\"version_release\", " + "\"upstream_version\", " + "\"type\", " + "\"project\", " + "\"alt_naming\", " + "\"bootstrap_build\", " + "\"root_build\", " + "\"sha256sum\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"available_package\".\"name\", " + "\"main\".\"available_package\".\"version_epoch\", " + "\"main\".\"available_package\".\"version_canonical_upstream\", " + "\"main\".\"available_package\".\"version_canonical_release\", " + "\"main\".\"available_package\".\"version_revision\", " + "\"main\".\"available_package\".\"version_iteration\", " + "\"main\".\"available_package\".\"version_upstream\", " + "\"main\".\"available_package\".\"version_release\", " + "\"main\".\"available_package\".\"upstream_version\", " + "\"main\".\"available_package\".\"type\", " + "\"main\".\"available_package\".\"project\", " + "\"main\".\"available_package\".\"alt_naming\", " + "\"main\".\"available_package\".\"bootstrap_build\", " + "\"main\".\"available_package\".\"root_build\", " + "\"main\".\"available_package\".\"sha256sum\" " + "FROM \"main\".\"available_package\" " + "WHERE \"main\".\"available_package\".\"name\"=? AND \"main\".\"available_package\".\"version_epoch\"=? AND \"main\".\"available_package\".\"version_canonical_upstream\"=? AND \"main\".\"available_package\".\"version_canonical_release\"=? AND \"main\".\"available_package\".\"version_revision\"=? AND \"main\".\"available_package\".\"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"available_package\" " + "SET " + "\"version_upstream\"=?, " + "\"version_release\"=?, " + "\"upstream_version\"=?, " + "\"type\"=?, " + "\"project\"=?, " + "\"alt_naming\"=?, " + "\"bootstrap_build\"=?, " + "\"root_build\"=?, " + "\"sha256sum\"=? " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"available_package\" " + "WHERE \"name\"=? AND \"version_epoch\"=? AND \"version_canonical_upstream\"=? AND \"version_canonical_release\"=? AND \"version_revision\"=? AND \"version_iteration\"=?"; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"available_package\".\"name\", " + "\"main\".\"available_package\".\"version_epoch\", " + "\"main\".\"available_package\".\"version_canonical_upstream\", " + "\"main\".\"available_package\".\"version_canonical_release\", " + "\"main\".\"available_package\".\"version_revision\", " + "\"main\".\"available_package\".\"version_iteration\", " + "\"main\".\"available_package\".\"version_upstream\", " + "\"main\".\"available_package\".\"version_release\", " + "\"main\".\"available_package\".\"upstream_version\", " + "\"main\".\"available_package\".\"type\", " + "\"main\".\"available_package\".\"project\", " + "\"main\".\"available_package\".\"alt_naming\", " + "\"main\".\"available_package\".\"bootstrap_build\", " + "\"main\".\"available_package\".\"root_build\", " + "\"main\".\"available_package\".\"sha256sum\" " + "FROM \"main\".\"available_package\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"available_package\""; + + const char access::object_traits_impl< ::bpkg::available_package, id_sqlite >::table_name[] = + "\"main\".\"available_package\""; + + void access::object_traits_impl< ::bpkg::available_package, 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 ()); + + // languages + // + { + ::butl::small_vector< ::bpkg::language, 1 > const& v = + obj.languages; + + languages_traits::persist ( + v, + esc.languages); + } + + // locations + // + { + ::butl::small_vector< ::bpkg::package_location, 1 > const& v = + obj.locations; + + locations_traits::persist ( + v, + esc.locations); + } + + // dependencies + // + { + ::bpkg::available_package::dependencies_type const& v = + obj.dependencies; + + dependencies_traits::persist ( + v, + esc.dependencies); + } + + // dependency_alternatives + // + { + // From package.hxx:868:7 + ::std::map< ::odb::nested_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency_alternative > const& v = + odb::nested_get (obj.dependencies); + + dependency_alternatives_traits::persist ( + v, + esc.dependency_alternatives); + } + + // dependency_alternative_dependencies + // + { + // From package.hxx:886:7 + ::std::map< ::odb::nested2_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency > const& v = + odb::nested2_get (obj.dependencies); + + dependency_alternative_dependencies_traits::persist ( + v, + esc.dependency_alternative_dependencies); + } + + // tests + // + { + ::butl::small_vector< ::bpkg::test_dependency, 1 > const& v = + obj.tests; + + tests_traits::persist ( + v, + esc.tests); + } + + // buildfiles + // + { + ::std::vector< ::bpkg::buildfile > const& v = + obj.buildfiles; + + buildfiles_traits::persist ( + v, + esc.buildfiles); + } + + // distribution_values + // + { + ::std::vector< ::bpkg::distribution_name_value > const& v = + obj.distribution_values; + + distribution_values_traits::persist ( + v, + esc.distribution_values); + } + + obj.languages_section.reset (true, false); + + callback (db, + obj, + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::available_package, 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 ()); + + // locations + // + { + ::butl::small_vector< ::bpkg::package_location, 1 > const& v = + obj.locations; + + locations_traits::update ( + v, + esc.locations); + } + + // dependencies + // + { + ::bpkg::available_package::dependencies_type const& v = + obj.dependencies; + + dependencies_traits::update ( + v, + esc.dependencies); + } + + // dependency_alternatives + // + { + // From package.hxx:868:7 + ::std::map< ::odb::nested_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency_alternative > const& v = + odb::nested_get (obj.dependencies); + + dependency_alternatives_traits::update ( + v, + esc.dependency_alternatives); + } + + // dependency_alternative_dependencies + // + { + // From package.hxx:886:7 + ::std::map< ::odb::nested2_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency > const& v = + odb::nested2_get (obj.dependencies); + + dependency_alternative_dependencies_traits::update ( + v, + esc.dependency_alternative_dependencies); + } + + // tests + // + { + ::butl::small_vector< ::bpkg::test_dependency, 1 > const& v = + obj.tests; + + tests_traits::update ( + v, + esc.tests); + } + + // buildfiles + // + { + ::std::vector< ::bpkg::buildfile > const& v = + obj.buildfiles; + + buildfiles_traits::update ( + v, + esc.buildfiles); + } + + // distribution_values + // + { + ::std::vector< ::bpkg::distribution_name_value > const& v = + obj.distribution_values; + + distribution_values_traits::update ( + v, + esc.distribution_values); + } + + if (obj.languages_section.loaded ()) + { + languages_section_traits::update (esc, obj); + } + + callback (db, obj, callback_event::post_update); + pointer_cache_traits::update (db, obj); + } + + void access::object_traits_impl< ::bpkg::available_package, 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 ()); + + // languages + // + { + languages_traits::erase ( + esc.languages); + } + + // locations + // + { + locations_traits::erase ( + esc.locations); + } + + // dependencies + // + { + dependencies_traits::erase ( + esc.dependencies); + } + + // dependency_alternatives + // + { + dependency_alternatives_traits::erase ( + esc.dependency_alternatives); + } + + // dependency_alternative_dependencies + // + { + dependency_alternative_dependencies_traits::erase ( + esc.dependency_alternative_dependencies); + } + + // tests + // + { + tests_traits::erase ( + esc.tests); + } + + // buildfiles + // + { + buildfiles_traits::erase ( + esc.buildfiles); + } + + // distribution_values + // + { + distribution_values_traits::erase ( + esc.distribution_values); + } + + if (sts.erase_statement ().execute () != 1) + throw object_not_persistent (); + + pointer_cache_traits::erase (db, id); + } + + access::object_traits_impl< ::bpkg::available_package, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::available_package, 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::available_package, 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::available_package, 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::available_package, id_sqlite >:: + load (connection& conn, object_type& obj, section& s) + { + using namespace sqlite; + + sqlite::connection& c (static_cast<sqlite::connection&> (conn)); + statements_type& sts (c.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + bool r (false); + + 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 ()); + + if (!r && &s == &obj.languages_section) + { + languages_section_traits::load (esc, obj); + r = true; + } + + sts.load_delayed (0); + l.unlock (); + return r; + } + + bool access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + update (connection& conn, const object_type& obj, const section& s) + { + using namespace sqlite; + + sqlite::connection& c (static_cast<sqlite::connection&> (conn)); + statements_type& sts (c.statement_cache ().find_object<object_type> ()); + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + 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++; + } + + if (&s == &obj.languages_section)languages_section_traits::update (esc, obj); + else + return false; + + return true; + } + + bool access::object_traits_impl< ::bpkg::available_package, 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::available_package, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool reload) + { + ODB_POTENTIALLY_UNUSED (reload); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // locations + // + { + ::butl::small_vector< ::bpkg::package_location, 1 >& v = + obj.locations; + + locations_traits::load ( + v, + esc.locations); + } + + // dependencies + // + { + ::bpkg::available_package::dependencies_type& v = + obj.dependencies; + + dependencies_traits::load ( + v, + esc.dependencies); + } + + // dependency_alternatives + // + { + ::std::map< ::odb::nested_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency_alternative > v; + + dependency_alternatives_traits::load ( + v, + esc.dependency_alternatives); + + // From package.hxx:869:7 + odb::nested_set (obj.dependencies, std::move (v)); + } + + // dependency_alternative_dependencies + // + { + ::std::map< ::odb::nested2_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency > v; + + dependency_alternative_dependencies_traits::load ( + v, + esc.dependency_alternative_dependencies); + + // From package.hxx:887:7 + odb::nested2_set (obj.dependencies, std::move (v)); + } + + // tests + // + { + ::butl::small_vector< ::bpkg::test_dependency, 1 >& v = + obj.tests; + + tests_traits::load ( + v, + esc.tests); + } + + // buildfiles + // + { + ::std::vector< ::bpkg::buildfile >& v = + obj.buildfiles; + + buildfiles_traits::load ( + v, + esc.buildfiles); + } + + // distribution_values + // + { + ::std::vector< ::bpkg::distribution_name_value >& v = + obj.distribution_values; + + distribution_values_traits::load ( + v, + esc.distribution_values); + } + + if (reload) + { + if (obj.languages_section.loaded ()) + { + languages_section_traits::load (esc, obj); + obj.languages_section.reset (true, false); + } + } + else + obj.languages_section.reset (); + } + + result< access::object_traits_impl< ::bpkg::available_package, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::available_package, 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::available_package, 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::available_package, 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::available_package, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // available_package_count + // + + bool access::view_traits_impl< ::bpkg::available_package_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::available_package_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::available_package_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::available_package_count, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::available_package_count, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "count(*) "); + + r += "FROM \"main\".\"available_package\""; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::available_package_count, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::available_package_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::available_package_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::available_package_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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // available_test + // + + const char alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_test, id_sqlite >::package_tag>:: + table_name[] = "\"package\""; + + bool access::view_traits_impl< ::bpkg::available_test, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // package + // + if (object_traits_impl< ::bpkg::available_package, id_sqlite >::grow ( + i.package_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::available_test, 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); + + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::bind ( + b + n, i.package_value, sk); + n += 15UL; + } + + void access::view_traits_impl< ::bpkg::available_test, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // package pre + // + typedef ::bpkg::available_package package_object_type; + typedef object_traits_impl<package_object_type, id_sqlite> package_object_traits; + typedef package_object_traits::pointer_type package_pointer_type; + typedef package_object_traits::pointer_traits package_pointer_traits; + typedef package_object_traits::pointer_cache_traits package_cache_traits; + + package_object_traits::id_type package_id; + package_pointer_type package_p; + package_pointer_traits::guard package_pg; + package_cache_traits::insert_guard package_ig; + package_object_type* package_o (0); + + { + if (!composite_value_traits< package_object_traits::id_type, id_sqlite >::get_null ( + i.package_value.id_value)) + { + package_id = package_object_traits::id (i.package_value); + package_p = package_cache_traits::find (*db, package_id); + + if (package_pointer_traits::null_ptr (package_p)) + { + package_p = object_factory<package_object_type, package_pointer_type>::create (); + package_pg.reset (package_p); + package_ig.reset (package_cache_traits::insert (*db, package_id, package_p)); + package_o = package_pointer_traits::get_ptr (package_p); + } + } + } + + // package + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::pre_load); + package_object_traits::init (*package_o, i.package_value, db); + package_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<package_object_type> ()); + package_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + package_object_traits::id_image_type& i (sts.id_image ()); + package_object_traits::init (i, package_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + package_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + package_object_traits::load_ (sts, *package_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // package post + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::post_load); + package_cache_traits::load (package_ig.position ()); + package_ig.release (); + package_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.package = ::std::shared_ptr< ::bpkg::available_package > ( + std::move (package_p)); + } + } + + access::view_traits_impl< ::bpkg::available_test, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::available_test, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"package\".\"name\", " + "\"package\".\"version_epoch\", " + "\"package\".\"version_canonical_upstream\", " + "\"package\".\"version_canonical_release\", " + "\"package\".\"version_revision\", " + "\"package\".\"version_iteration\", " + "\"package\".\"version_upstream\", " + "\"package\".\"version_release\", " + "\"package\".\"upstream_version\", " + "\"package\".\"type\", " + "\"package\".\"project\", " + "\"package\".\"alt_naming\", " + "\"package\".\"bootstrap_build\", " + "\"package\".\"root_build\", " + "\"package\".\"sha256sum\" "); + + r += "FROM \"main\".\"available_package\" AS \"package\""; + + r += " INNER JOIN \"main\".\"available_package_dependencies\" AS \"pd\" ON"; + // From package.hxx:952:5 + r += "pd.type IN ('tests', 'examples', 'benchmarks') AND pd.name = " + query_columns::id.name + "AND" + "pd.version_epoch = " + query_columns::id.version.epoch + "AND" + "pd.version_canonical_upstream = " + query_columns::id.version.canonical_upstream + "AND" + "pd.version_canonical_release = " + query_columns::id.version.canonical_release + "AND" + "pd.version_revision = " + query_columns::id.version.revision + "AND" + "pd.version_iteration = " + query_columns::id.version.iteration; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::available_test, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::available_test, 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::available_test, 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::available_test, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // available_main + // + + const char alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_main, id_sqlite >::package_tag>:: + table_name[] = "\"package\""; + + bool access::view_traits_impl< ::bpkg::available_main, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // package + // + if (object_traits_impl< ::bpkg::available_package, id_sqlite >::grow ( + i.package_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::available_main, 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); + + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::bind ( + b + n, i.package_value, sk); + n += 15UL; + } + + void access::view_traits_impl< ::bpkg::available_main, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // package pre + // + typedef ::bpkg::available_package package_object_type; + typedef object_traits_impl<package_object_type, id_sqlite> package_object_traits; + typedef package_object_traits::pointer_type package_pointer_type; + typedef package_object_traits::pointer_traits package_pointer_traits; + typedef package_object_traits::pointer_cache_traits package_cache_traits; + + package_object_traits::id_type package_id; + package_pointer_type package_p; + package_pointer_traits::guard package_pg; + package_cache_traits::insert_guard package_ig; + package_object_type* package_o (0); + + { + if (!composite_value_traits< package_object_traits::id_type, id_sqlite >::get_null ( + i.package_value.id_value)) + { + package_id = package_object_traits::id (i.package_value); + package_p = package_cache_traits::find (*db, package_id); + + if (package_pointer_traits::null_ptr (package_p)) + { + package_p = object_factory<package_object_type, package_pointer_type>::create (); + package_pg.reset (package_p); + package_ig.reset (package_cache_traits::insert (*db, package_id, package_p)); + package_o = package_pointer_traits::get_ptr (package_p); + } + } + } + + // package + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::pre_load); + package_object_traits::init (*package_o, i.package_value, db); + package_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<package_object_type> ()); + package_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + package_object_traits::id_image_type& i (sts.id_image ()); + package_object_traits::init (i, package_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + package_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + package_object_traits::load_ (sts, *package_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // package post + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::post_load); + package_cache_traits::load (package_ig.position ()); + package_ig.release (); + package_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.package = ::std::shared_ptr< ::bpkg::available_package > ( + std::move (package_p)); + } + } + + access::view_traits_impl< ::bpkg::available_main, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::available_main, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT DISTINCT " + "\"package\".\"name\", " + "\"package\".\"version_epoch\", " + "\"package\".\"version_canonical_upstream\", " + "\"package\".\"version_canonical_release\", " + "\"package\".\"version_revision\", " + "\"package\".\"version_iteration\", " + "\"package\".\"version_upstream\", " + "\"package\".\"version_release\", " + "\"package\".\"upstream_version\", " + "\"package\".\"type\", " + "\"package\".\"project\", " + "\"package\".\"alt_naming\", " + "\"package\".\"bootstrap_build\", " + "\"package\".\"root_build\", " + "\"package\".\"sha256sum\" "); + + r += "FROM \"main\".\"available_package\" AS \"package\""; + + r += " INNER JOIN \"main\".\"available_package_tests\" AS \"pt\" ON"; + // From package.hxx:971:5 + r += "pt.name = " + query_columns::id.name + "AND" + "pt.version_epoch = " + query_columns::id.version.epoch + "AND" + "pt.version_canonical_upstream = " + query_columns::id.version.canonical_upstream + "AND" + "pt.version_canonical_release = " + query_columns::id.version.canonical_release + "AND" + "pt.version_revision = " + query_columns::id.version.revision + "AND" + "pt.version_iteration = " + query_columns::id.version.iteration; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::available_main, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::available_main, 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::available_main, 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::available_main, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // prerequisite_info + // + + bool access::composite_value_traits< ::bpkg::prerequisite_info, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // constraint + // + if (composite_value_traits< ::bpkg::version_constraint, id_sqlite >::grow ( + i.constraint_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::composite_value_traits< ::bpkg::prerequisite_info, 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); + + // constraint + // + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::bind ( + b + n, i.constraint_value, sk); + n += 16UL; + } + + bool access::composite_value_traits< ::bpkg::prerequisite_info, 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); + + // 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::prerequisite_info, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // 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); + } + } + } + + // _selected_package_ref + // + + bool access::composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // configuration + // + if (t[0UL]) + { + i.configuration_value.capacity (i.configuration_size); + grew = true; + } + + // prerequisite + // + if (t[1UL]) + { + i.prerequisite_value.capacity (i.prerequisite_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_selected_package_ref, 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); + + // configuration + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.configuration_value.data (); + b[n].size = &i.configuration_size; + b[n].capacity = i.configuration_value.capacity (); + b[n].is_null = &i.configuration_null; + n++; + + // prerequisite + // + b[n].type = sqlite::image_traits< + ::bpkg::package_name, + sqlite::id_text>::bind_value; + b[n].buffer = i.prerequisite_value.data (); + b[n].size = &i.prerequisite_size; + b[n].capacity = i.prerequisite_value.capacity (); + b[n].is_null = &i.prerequisite_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::_selected_package_ref, 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); + + // configuration + // + { + ::butl::uuid const& v = + o.configuration; + + // From package.hxx:66:14 + ::std::string const& vt = + (v).string (); + + bool is_null (false); + std::size_t cap (i.configuration_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.configuration_value, + i.configuration_size, + is_null, + vt); + i.configuration_null = is_null; + grew = grew || (cap != i.configuration_value.capacity ()); + } + + // prerequisite + // + { + ::bpkg::package_name const& v = + o.prerequisite; + + bool is_null (false); + std::size_t cap (i.prerequisite_value.capacity ()); + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_image ( + i.prerequisite_value, + i.prerequisite_size, + is_null, + v); + i.prerequisite_null = is_null; + grew = grew || (cap != i.prerequisite_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >:: + init (value_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + // configuration + // + { + ::butl::uuid& v = + o.configuration; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.configuration_value, + i.configuration_size, + i.configuration_null); + + // From package.hxx:66:14 + v = bpkg::uuid (vt); + } + + // prerequisite + // + { + ::bpkg::package_name& v = + o.prerequisite; + + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_value ( + v, + i.prerequisite_value, + i.prerequisite_size, + i.prerequisite_null); + } + } + + // config_variable + // + + bool access::composite_value_traits< ::bpkg::config_variable, 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; + } + + // source + // + if (t[1UL]) + { + i.source_value.capacity (i.source_size); + grew = true; + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::config_variable, 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< + ::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++; + + // source + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.source_value.data (); + b[n].size = &i.source_size; + b[n].capacity = i.source_value.capacity (); + b[n].is_null = &i.source_null; + n++; + } + + bool access::composite_value_traits< ::bpkg::config_variable, 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 + // + { + ::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 ()); + } + + // source + // + { + ::bpkg::config_source const& v = + o.source; + + // From package.hxx:1151:14 + ::std::string const& vt = + to_string (v); + + bool is_null (false); + std::size_t cap (i.source_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.source_value, + i.source_size, + is_null, + vt); + i.source_null = is_null; + grew = grew || (cap != i.source_value.capacity ()); + } + + return grew; + } + + void access::composite_value_traits< ::bpkg::config_variable, 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 + // + { + ::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); + } + + // source + // + { + ::bpkg::config_source& v = + o.source; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.source_value, + i.source_size, + i.source_null); + + // From package.hxx:1151:14 + v = bpkg::to_config_source (vt); + } + } + + // selected_package + // + + struct access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::extra_statement_cache_type + { + sqlite::container_statements_impl< prerequisites_traits > prerequisites; + sqlite::container_statements_impl< dependency_alternatives_traits > dependency_alternatives; + sqlite::container_statements_impl< config_variables_traits > config_variables; + + sqlite::section_statements< ::bpkg::selected_package, dependency_alternatives_section_traits > dependency_alternatives_section; + + extra_statement_cache_type ( + sqlite::connection& c, + image_type& im, + id_image_type& idim, + sqlite::binding& id, + sqlite::binding& idv) + : prerequisites (c, id), + dependency_alternatives (c, id), + config_variables (c, id), + dependency_alternatives_section (c, im, idim, id, idv) + { + } + }; + + // prerequisites + // + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::prerequisites_traits:: + select_statement[] = + "SELECT " + "\"main\".\"selected_package_prerequisites\".\"configuration\", " + "\"main\".\"selected_package_prerequisites\".\"prerequisite\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_epoch\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_canonical_upstream\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_canonical_release\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_revision\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_iteration\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_upstream\", " + "\"main\".\"selected_package_prerequisites\".\"min_version_release\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_epoch\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_canonical_upstream\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_canonical_release\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_revision\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_iteration\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_upstream\", " + "\"main\".\"selected_package_prerequisites\".\"max_version_release\", " + "\"main\".\"selected_package_prerequisites\".\"min_open\", " + "\"main\".\"selected_package_prerequisites\".\"max_open\" " + "FROM \"main\".\"selected_package_prerequisites\" " + "WHERE \"main\".\"selected_package_prerequisites\".\"package\"=?"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::prerequisites_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"selected_package_prerequisites\" " + "(\"package\", " + "\"configuration\", " + "\"prerequisite\", " + "\"min_version_epoch\", " + "\"min_version_canonical_upstream\", " + "\"min_version_canonical_release\", " + "\"min_version_revision\", " + "\"min_version_iteration\", " + "\"min_version_upstream\", " + "\"min_version_release\", " + "\"max_version_epoch\", " + "\"max_version_canonical_upstream\", " + "\"max_version_canonical_release\", " + "\"max_version_revision\", " + "\"max_version_iteration\", " + "\"max_version_upstream\", " + "\"max_version_release\", " + "\"min_open\", " + "\"max_open\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::prerequisites_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"selected_package_prerequisites\" " + "WHERE \"package\"=?"; + + void access::object_traits_impl< ::bpkg::selected_package, 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; + + // key + // + composite_value_traits< ::bpkg::_selected_package_ref, 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::selected_package, id_sqlite >::prerequisites_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // key + // + if (composite_value_traits< ::bpkg::_selected_package_ref, 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::selected_package, id_sqlite >::prerequisites_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) + { + // From package.hxx:1133:14 + ::bpkg::_selected_package_ref const& vt = + bpkg::_selected_package_ref (*k); + + if (composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >::init ( + i.key_value, + vt, + sk)) + grew = true; + } + + // 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::selected_package, id_sqlite >::prerequisites_traits:: + init (key_type& k, + value_type& v, + const data_image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (db); + + // key + // + { + ::bpkg::_selected_package_ref vt; + + composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >::init ( + vt, + i.key_value, + db); + + // From package.hxx:1133:14 + k = std::move (vt).to_ptr ( * db); + } + + // value + // + { + composite_value_traits< value_type, id_sqlite >::init ( + v, + i.value_value, + db); + } + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::prerequisites_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::selected_package, id_sqlite >::prerequisites_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::selected_package, 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::selected_package, 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::selected_package, 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::selected_package, 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::selected_package, id_sqlite >::prerequisites_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + container_traits_type::erase (fs); + } + + // dependency_alternatives + // + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_traits:: + select_statement[] = + "SELECT " + "\"main\".\"selected_package_dependency_alternatives\".\"index\", " + "\"main\".\"selected_package_dependency_alternatives\".\"position\" " + "FROM \"main\".\"selected_package_dependency_alternatives\" " + "WHERE \"main\".\"selected_package_dependency_alternatives\".\"package\"=? ORDER BY \"main\".\"selected_package_dependency_alternatives\".\"index\""; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"selected_package_dependency_alternatives\" " + "(\"package\", " + "\"index\", " + "\"position\") " + "VALUES " + "(?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"selected_package_dependency_alternatives\" " + "WHERE \"package\"=?"; + + void access::object_traits_impl< ::bpkg::selected_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; + + // index + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &d.index_value; + b[n].is_null = &d.index_null; + n++; + + // value + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &d.value_value; + b[n].is_null = &d.value_null; + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_traits:: + grow (data_image_type& i, + bool* t) + { + bool grew (false); + + // index + // + t[0UL] = false; + + // value + // + t[1UL] = false; + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_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 + // + { + bool is_null (false); + sqlite::value_traits< + value_type, + sqlite::id_integer >::set_image ( + i.value_value, + is_null, + v); + i.value_null = is_null; + } + + if (grew) + i.version++; + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_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 + // + { + sqlite::value_traits< + value_type, + sqlite::id_integer >::set_value ( + v, + i.value_value, + i.value_null); + } + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_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::selected_package, id_sqlite >::dependency_alternatives_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 ()); + return r != select_statement::no_data; + } + + void access::object_traits_impl< ::bpkg::selected_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::selected_package, id_sqlite >::dependency_alternatives_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::selected_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 ()); + 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::selected_package, id_sqlite >::dependency_alternatives_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::selected_package, id_sqlite >::dependency_alternatives_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // config_variables + // + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::config_variables_traits:: + select_statement[] = + "SELECT " + "\"main\".\"selected_package_config_variables\".\"index\", " + "\"main\".\"selected_package_config_variables\".\"name\", " + "\"main\".\"selected_package_config_variables\".\"source\" " + "FROM \"main\".\"selected_package_config_variables\" " + "WHERE \"main\".\"selected_package_config_variables\".\"package\"=? ORDER BY \"main\".\"selected_package_config_variables\".\"index\""; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::config_variables_traits:: + insert_statement[] = + "INSERT INTO \"main\".\"selected_package_config_variables\" " + "(\"package\", " + "\"index\", " + "\"name\", " + "\"source\") " + "VALUES " + "(?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::config_variables_traits:: + delete_statement[] = + "DELETE FROM \"main\".\"selected_package_config_variables\" " + "WHERE \"package\"=?"; + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_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::selected_package, id_sqlite >::config_variables_traits:: + erase (statements_type& sts) + { + using namespace sqlite; + + functions_type& fs (sts.functions ()); + fs.ordered_ = true; + container_traits_type::erase (fs); + } + + // dependency_alternatives_section + // + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_section_traits:: + load (extra_statement_cache_type& esc, object_type& obj) + { + // dependency_alternatives + // + { + ::bpkg::selected_package::indexes_type& v = + obj.dependency_alternatives; + + dependency_alternatives_traits::load ( + v, + esc.dependency_alternatives); + } + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::dependency_alternatives_section_traits:: + update (extra_statement_cache_type& esc, const object_type& obj) + { + // dependency_alternatives + // + { + ::bpkg::selected_package::indexes_type const& v = + obj.dependency_alternatives; + + dependency_alternatives_traits::update ( + v, + esc.dependency_alternatives); + } + } + + access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::selected_package, id_sqlite >:: + id (const image_type& i) + { + sqlite::database* db (0); + ODB_POTENTIALLY_UNUSED (db); + + id_type id; + { + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::set_value ( + id, + i.name_value, + i.name_size, + i.name_null); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::selected_package, 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::_version, id_sqlite >::grow ( + i.version_value, t + 1UL)) + grew = true; + + // state + // + if (t[8UL]) + { + i.state_value.capacity (i.state_size); + grew = true; + } + + // substate + // + if (t[9UL]) + { + i.substate_value.capacity (i.substate_size); + grew = true; + } + + // hold_package + // + t[10UL] = false; + + // hold_version + // + t[11UL] = false; + + // repository_fragment + // + if (composite_value_traits< ::bpkg::_repository_location, id_sqlite >::grow ( + i.repository_fragment_value, t + 12UL)) + grew = true; + + // archive + // + if (t[14UL]) + { + i.archive_value.capacity (i.archive_size); + grew = true; + } + + // purge_archive + // + t[15UL] = false; + + // src_root + // + if (t[16UL]) + { + i.src_root_value.capacity (i.src_root_size); + grew = true; + } + + // purge_src + // + t[17UL] = false; + + // manifest_checksum + // + if (t[18UL]) + { + i.manifest_checksum_value.capacity (i.manifest_checksum_size); + grew = true; + } + + // buildfiles_checksum + // + if (t[19UL]) + { + i.buildfiles_checksum_value.capacity (i.buildfiles_checksum_size); + grew = true; + } + + // out_root + // + if (t[20UL]) + { + i.out_root_value.capacity (i.out_root_size); + grew = true; + } + + // config_checksum + // + if (t[21UL]) + { + i.config_checksum_value.capacity (i.config_checksum_size); + grew = true; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::selected_package, 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< + ::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::_version, id_sqlite >::bind ( + b + n, i.version_value, sk); + n += 7UL; + + // state + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.state_value.data (); + b[n].size = &i.state_size; + b[n].capacity = i.state_value.capacity (); + b[n].is_null = &i.state_null; + n++; + + // substate + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.substate_value.data (); + b[n].size = &i.substate_size; + b[n].capacity = i.substate_value.capacity (); + b[n].is_null = &i.substate_null; + n++; + + // hold_package + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.hold_package_value; + b[n].is_null = &i.hold_package_null; + n++; + + // hold_version + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.hold_version_value; + b[n].is_null = &i.hold_version_null; + n++; + + // repository_fragment + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::bind ( + b + n, i.repository_fragment_value, sk); + n += 2UL; + + // archive + // + b[n].type = sqlite::image_traits< + ::bpkg::optional_string, + sqlite::id_text>::bind_value; + b[n].buffer = i.archive_value.data (); + b[n].size = &i.archive_size; + b[n].capacity = i.archive_value.capacity (); + b[n].is_null = &i.archive_null; + n++; + + // purge_archive + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.purge_archive_value; + b[n].is_null = &i.purge_archive_null; + n++; + + // src_root + // + b[n].type = sqlite::image_traits< + ::bpkg::optional_string, + sqlite::id_text>::bind_value; + b[n].buffer = i.src_root_value.data (); + b[n].size = &i.src_root_size; + b[n].capacity = i.src_root_value.capacity (); + b[n].is_null = &i.src_root_null; + n++; + + // purge_src + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.purge_src_value; + b[n].is_null = &i.purge_src_null; + n++; + + // manifest_checksum + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.manifest_checksum_value.data (); + b[n].size = &i.manifest_checksum_size; + b[n].capacity = i.manifest_checksum_value.capacity (); + b[n].is_null = &i.manifest_checksum_null; + n++; + + // buildfiles_checksum + // + b[n].type = sqlite::image_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text>::bind_value; + b[n].buffer = i.buildfiles_checksum_value.data (); + b[n].size = &i.buildfiles_checksum_size; + b[n].capacity = i.buildfiles_checksum_value.capacity (); + b[n].is_null = &i.buildfiles_checksum_null; + n++; + + // out_root + // + b[n].type = sqlite::image_traits< + ::bpkg::optional_string, + sqlite::id_text>::bind_value; + b[n].buffer = i.out_root_value.data (); + b[n].size = &i.out_root_size; + b[n].capacity = i.out_root_value.capacity (); + b[n].is_null = &i.out_root_null; + n++; + + // config_checksum + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.config_checksum_value.data (); + b[n].size = &i.config_checksum_size; + b[n].capacity = i.config_checksum_value.capacity (); + b[n].is_null = &i.config_checksum_null; + n++; + } + + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >:: + bind (sqlite::bind* b, id_image_type& i) + { + std::size_t n (0); + b[n].type = sqlite::image_traits< + ::bpkg::package_name, + 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::selected_package, 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) + { + ::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::selected_package::version_type const& v = + o.version; + + // From package.hxx:308:14 + ::bpkg::_version const& vt = + bpkg::_version + { + (v).epoch, (v).canonical_upstream, (v).canonical_release, (v).revision, (v).iteration, (v).upstream, (v).release + }; + + + if (composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + i.version_value, + vt, + sk)) + grew = true; + } + + // state + // + { + ::bpkg::package_state const& v = + o.state; + + // From package.hxx:1018:14 + ::std::string const& vt = + to_string (v); + + bool is_null (false); + std::size_t cap (i.state_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.state_value, + i.state_size, + is_null, + vt); + i.state_null = is_null; + grew = grew || (cap != i.state_value.capacity ()); + } + + // substate + // + { + ::bpkg::package_substate const& v = + o.substate; + + // From package.hxx:1039:14 + ::std::string const& vt = + to_string (v); + + bool is_null (false); + std::size_t cap (i.substate_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.substate_value, + i.substate_size, + is_null, + vt); + i.substate_null = is_null; + grew = grew || (cap != i.substate_value.capacity ()); + } + + // hold_package + // + { + bool const& v = + o.hold_package; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.hold_package_value, + is_null, + v); + i.hold_package_null = is_null; + } + + // hold_version + // + { + bool const& v = + o.hold_version; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.hold_version_value, + is_null, + v); + i.hold_version_null = is_null; + } + + // repository_fragment + // + { + ::bpkg::repository_location const& v = + o.repository_fragment; + + // From package.hxx:368: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.repository_fragment_value, + vt, + sk)) + grew = true; + } + + // archive + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::any_path_kind< char > > > const& v = + o.archive; + + // From package.hxx:53:14 + ::bpkg::optional_string const& vt = + (v) ? (v)->string () : bpkg::optional_string (); + + bool is_null (true); + std::size_t cap (i.archive_value.capacity ()); + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_image ( + i.archive_value, + i.archive_size, + is_null, + vt); + i.archive_null = is_null; + grew = grew || (cap != i.archive_value.capacity ()); + } + + // purge_archive + // + { + bool const& v = + o.purge_archive; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.purge_archive_value, + is_null, + v); + i.purge_archive_null = is_null; + } + + // src_root + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::dir_path_kind< char > > > const& v = + o.src_root; + + // From package.hxx:60:14 + ::bpkg::optional_string const& vt = + (v) ? (v)->string () : bpkg::optional_string (); + + bool is_null (true); + std::size_t cap (i.src_root_value.capacity ()); + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_image ( + i.src_root_value, + i.src_root_size, + is_null, + vt); + i.src_root_null = is_null; + grew = grew || (cap != i.src_root_value.capacity ()); + } + + // purge_src + // + { + bool const& v = + o.purge_src; + + bool is_null (false); + sqlite::value_traits< + bool, + sqlite::id_integer >::set_image ( + i.purge_src_value, + is_null, + v); + i.purge_src_null = is_null; + } + + // manifest_checksum + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.manifest_checksum; + + bool is_null (true); + std::size_t cap (i.manifest_checksum_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.manifest_checksum_value, + i.manifest_checksum_size, + is_null, + v); + i.manifest_checksum_null = is_null; + grew = grew || (cap != i.manifest_checksum_value.capacity ()); + } + + // buildfiles_checksum + // + { + ::butl::optional< ::std::basic_string< char > > const& v = + o.buildfiles_checksum; + + bool is_null (true); + std::size_t cap (i.buildfiles_checksum_value.capacity ()); + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_image ( + i.buildfiles_checksum_value, + i.buildfiles_checksum_size, + is_null, + v); + i.buildfiles_checksum_null = is_null; + grew = grew || (cap != i.buildfiles_checksum_value.capacity ()); + } + + // out_root + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::dir_path_kind< char > > > const& v = + o.out_root; + + // From package.hxx:60:14 + ::bpkg::optional_string const& vt = + (v) ? (v)->string () : bpkg::optional_string (); + + bool is_null (true); + std::size_t cap (i.out_root_value.capacity ()); + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_image ( + i.out_root_value, + i.out_root_size, + is_null, + vt); + i.out_root_null = is_null; + grew = grew || (cap != i.out_root_value.capacity ()); + } + + // config_checksum + // + { + ::std::string const& v = + o.config_checksum; + + bool is_null (false); + std::size_t cap (i.config_checksum_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.config_checksum_value, + i.config_checksum_size, + is_null, + v); + i.config_checksum_null = is_null; + grew = grew || (cap != i.config_checksum_value.capacity ()); + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::selected_package, 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 + // + { + ::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::selected_package::version_type& v = + o.version; + + ::bpkg::_version vt; + + composite_value_traits< ::bpkg::_version, id_sqlite >::init ( + vt, + i.version_value, + db); + + // From package.hxx:308:14 + v = bpkg::version ((vt).epoch, std::move ((vt).upstream), std::move ((vt).release), (vt).revision, (vt).iteration); + } + + // state + // + { + ::bpkg::package_state& v = + o.state; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.state_value, + i.state_size, + i.state_null); + + // From package.hxx:1018:14 + v = bpkg::to_package_state (vt); + } + + // substate + // + { + ::bpkg::package_substate& v = + o.substate; + + ::std::string vt; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + vt, + i.substate_value, + i.substate_size, + i.substate_null); + + // From package.hxx:1039:14 + v = bpkg::to_package_substate (vt); + } + + // hold_package + // + { + bool& v = + o.hold_package; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.hold_package_value, + i.hold_package_null); + } + + // hold_version + // + { + bool& v = + o.hold_version; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.hold_version_value, + i.hold_version_null); + } + + // repository_fragment + // + { + ::bpkg::repository_location& v = + o.repository_fragment; + + ::bpkg::_repository_location vt; + + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::init ( + vt, + i.repository_fragment_value, + db); + + // From package.hxx:368:14 + v = bpkg::repository_location (std::move ((vt).url), (vt).type); + } + + // archive + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::any_path_kind< char > > >& v = + o.archive; + + ::bpkg::optional_string vt; + + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_value ( + vt, + i.archive_value, + i.archive_size, + i.archive_null); + + // From package.hxx:53:14 + v = (vt) ? bpkg::path ( * (vt)) : bpkg::optional_path (); + } + + // purge_archive + // + { + bool& v = + o.purge_archive; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.purge_archive_value, + i.purge_archive_null); + } + + // src_root + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::dir_path_kind< char > > >& v = + o.src_root; + + ::bpkg::optional_string vt; + + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_value ( + vt, + i.src_root_value, + i.src_root_size, + i.src_root_null); + + // From package.hxx:60:14 + v = (vt) ? bpkg::dir_path ( * (vt)) : bpkg::optional_dir_path (); + } + + // purge_src + // + { + bool& v = + o.purge_src; + + sqlite::value_traits< + bool, + sqlite::id_integer >::set_value ( + v, + i.purge_src_value, + i.purge_src_null); + } + + // manifest_checksum + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.manifest_checksum; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.manifest_checksum_value, + i.manifest_checksum_size, + i.manifest_checksum_null); + } + + // buildfiles_checksum + // + { + ::butl::optional< ::std::basic_string< char > >& v = + o.buildfiles_checksum; + + sqlite::value_traits< + ::butl::optional< ::std::basic_string< char > >, + sqlite::id_text >::set_value ( + v, + i.buildfiles_checksum_value, + i.buildfiles_checksum_size, + i.buildfiles_checksum_null); + } + + // out_root + // + { + ::butl::optional< ::butl::basic_path< char, ::butl::dir_path_kind< char > > >& v = + o.out_root; + + ::bpkg::optional_string vt; + + sqlite::value_traits< + ::bpkg::optional_string, + sqlite::id_text >::set_value ( + vt, + i.out_root_value, + i.out_root_size, + i.out_root_null); + + // From package.hxx:60:14 + v = (vt) ? bpkg::dir_path ( * (vt)) : bpkg::optional_dir_path (); + } + + // config_checksum + // + { + ::std::string& v = + o.config_checksum; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.config_checksum_value, + i.config_checksum_size, + i.config_checksum_null); + } + } + + void access::object_traits_impl< ::bpkg::selected_package, 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< + ::bpkg::package_name, + 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::selected_package, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"selected_package\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"version_upstream\", " + "\"version_release\", " + "\"state\", " + "\"substate\", " + "\"hold_package\", " + "\"hold_version\", " + "\"repository_fragment_url\", " + "\"repository_fragment_type\", " + "\"archive\", " + "\"purge_archive\", " + "\"src_root\", " + "\"purge_src\", " + "\"manifest_checksum\", " + "\"buildfiles_checksum\", " + "\"out_root\", " + "\"config_checksum\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"selected_package\".\"name\", " + "\"main\".\"selected_package\".\"version_epoch\", " + "\"main\".\"selected_package\".\"version_canonical_upstream\", " + "\"main\".\"selected_package\".\"version_canonical_release\", " + "\"main\".\"selected_package\".\"version_revision\", " + "\"main\".\"selected_package\".\"version_iteration\", " + "\"main\".\"selected_package\".\"version_upstream\", " + "\"main\".\"selected_package\".\"version_release\", " + "\"main\".\"selected_package\".\"state\", " + "\"main\".\"selected_package\".\"substate\", " + "\"main\".\"selected_package\".\"hold_package\", " + "\"main\".\"selected_package\".\"hold_version\", " + "\"main\".\"selected_package\".\"repository_fragment_url\", " + "\"main\".\"selected_package\".\"repository_fragment_type\", " + "\"main\".\"selected_package\".\"archive\", " + "\"main\".\"selected_package\".\"purge_archive\", " + "\"main\".\"selected_package\".\"src_root\", " + "\"main\".\"selected_package\".\"purge_src\", " + "\"main\".\"selected_package\".\"manifest_checksum\", " + "\"main\".\"selected_package\".\"buildfiles_checksum\", " + "\"main\".\"selected_package\".\"out_root\", " + "\"main\".\"selected_package\".\"config_checksum\" " + "FROM \"main\".\"selected_package\" " + "WHERE \"main\".\"selected_package\".\"name\"=?"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"selected_package\" " + "SET " + "\"version_epoch\"=?, " + "\"version_canonical_upstream\"=?, " + "\"version_canonical_release\"=?, " + "\"version_revision\"=?, " + "\"version_iteration\"=?, " + "\"version_upstream\"=?, " + "\"version_release\"=?, " + "\"state\"=?, " + "\"substate\"=?, " + "\"hold_package\"=?, " + "\"hold_version\"=?, " + "\"repository_fragment_url\"=?, " + "\"repository_fragment_type\"=?, " + "\"archive\"=?, " + "\"purge_archive\"=?, " + "\"src_root\"=?, " + "\"purge_src\"=?, " + "\"manifest_checksum\"=?, " + "\"buildfiles_checksum\"=?, " + "\"out_root\"=?, " + "\"config_checksum\"=? " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"selected_package\" " + "WHERE \"name\"=?"; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"selected_package\".\"name\", " + "\"main\".\"selected_package\".\"version_epoch\", " + "\"main\".\"selected_package\".\"version_canonical_upstream\", " + "\"main\".\"selected_package\".\"version_canonical_release\", " + "\"main\".\"selected_package\".\"version_revision\", " + "\"main\".\"selected_package\".\"version_iteration\", " + "\"main\".\"selected_package\".\"version_upstream\", " + "\"main\".\"selected_package\".\"version_release\", " + "\"main\".\"selected_package\".\"state\", " + "\"main\".\"selected_package\".\"substate\", " + "\"main\".\"selected_package\".\"hold_package\", " + "\"main\".\"selected_package\".\"hold_version\", " + "\"main\".\"selected_package\".\"repository_fragment_url\", " + "\"main\".\"selected_package\".\"repository_fragment_type\", " + "\"main\".\"selected_package\".\"archive\", " + "\"main\".\"selected_package\".\"purge_archive\", " + "\"main\".\"selected_package\".\"src_root\", " + "\"main\".\"selected_package\".\"purge_src\", " + "\"main\".\"selected_package\".\"manifest_checksum\", " + "\"main\".\"selected_package\".\"buildfiles_checksum\", " + "\"main\".\"selected_package\".\"out_root\", " + "\"main\".\"selected_package\".\"config_checksum\" " + "FROM \"main\".\"selected_package\""; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"selected_package\""; + + const char access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::table_name[] = + "\"main\".\"selected_package\""; + + void access::object_traits_impl< ::bpkg::selected_package, 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 ()); + + // prerequisites + // + { + ::bpkg::package_prerequisites const& v = + obj.prerequisites; + + prerequisites_traits::persist ( + v, + esc.prerequisites); + } + + // dependency_alternatives + // + { + ::bpkg::selected_package::indexes_type const& v = + obj.dependency_alternatives; + + dependency_alternatives_traits::persist ( + v, + esc.dependency_alternatives); + } + + // config_variables + // + { + ::std::vector< ::bpkg::config_variable > const& v = + obj.config_variables; + + config_variables_traits::persist ( + v, + esc.config_variables); + } + + obj.dependency_alternatives_section.reset (true, false); + + callback (db, + obj, + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::selected_package, 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 ()); + + // prerequisites + // + { + ::bpkg::package_prerequisites const& v = + obj.prerequisites; + + prerequisites_traits::update ( + v, + esc.prerequisites); + } + + // config_variables + // + { + ::std::vector< ::bpkg::config_variable > const& v = + obj.config_variables; + + config_variables_traits::update ( + v, + esc.config_variables); + } + + if (obj.dependency_alternatives_section.loaded ()) + { + dependency_alternatives_section_traits::update (esc, obj); + } + + callback (db, obj, callback_event::post_update); + pointer_cache_traits::update (db, obj); + } + + void access::object_traits_impl< ::bpkg::selected_package, 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 ()); + + // prerequisites + // + { + prerequisites_traits::erase ( + esc.prerequisites); + } + + // dependency_alternatives + // + { + dependency_alternatives_traits::erase ( + esc.dependency_alternatives); + } + + // config_variables + // + { + config_variables_traits::erase ( + esc.config_variables); + } + + if (sts.erase_statement ().execute () != 1) + throw object_not_persistent (); + + pointer_cache_traits::erase (db, id); + } + + access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::selected_package, 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::selected_package, 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::selected_package, 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::selected_package, id_sqlite >:: + load (connection& conn, object_type& obj, section& s) + { + using namespace sqlite; + + sqlite::connection& c (static_cast<sqlite::connection&> (conn)); + statements_type& sts (c.statement_cache ().find_object<object_type> ()); + + statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + bool r (false); + + 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 ()); + + if (!r && &s == &obj.dependency_alternatives_section) + { + dependency_alternatives_section_traits::load (esc, obj); + r = true; + } + + sts.load_delayed (0); + l.unlock (); + return r; + } + + bool access::object_traits_impl< ::bpkg::selected_package, id_sqlite >:: + update (connection& conn, const object_type& obj, const section& s) + { + using namespace sqlite; + + sqlite::connection& c (static_cast<sqlite::connection&> (conn)); + statements_type& sts (c.statement_cache ().find_object<object_type> ()); + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + 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++; + } + + if (&s == &obj.dependency_alternatives_section)dependency_alternatives_section_traits::update (esc, obj); + else + return false; + + return true; + } + + bool access::object_traits_impl< ::bpkg::selected_package, 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::selected_package, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool reload) + { + ODB_POTENTIALLY_UNUSED (reload); + + extra_statement_cache_type& esc (sts.extra_statement_cache ()); + + // prerequisites + // + { + ::bpkg::package_prerequisites& v = + obj.prerequisites; + + prerequisites_traits::load ( + v, + esc.prerequisites); + } + + // config_variables + // + { + ::std::vector< ::bpkg::config_variable >& v = + obj.config_variables; + + config_variables_traits::load ( + v, + esc.config_variables); + } + + if (reload) + { + if (obj.dependency_alternatives_section.loaded ()) + { + dependency_alternatives_section_traits::load (esc, obj); + obj.dependency_alternatives_section.reset (true, false); + } + } + else + obj.dependency_alternatives_section.reset (); + } + + result< access::object_traits_impl< ::bpkg::selected_package, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::selected_package, 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::selected_package, 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::selected_package, 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::selected_package, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // certificate + // + + struct access::object_traits_impl< ::bpkg::certificate, 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::certificate, id_sqlite >::id_type + access::object_traits_impl< ::bpkg::certificate, 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.id_value, + i.id_size, + i.id_null); + } + + return id; + } + + bool access::object_traits_impl< ::bpkg::certificate, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // id + // + if (t[0UL]) + { + i.id_value.capacity (i.id_size); + grew = true; + } + + // fingerprint + // + if (t[1UL]) + { + i.fingerprint_value.capacity (i.fingerprint_size); + grew = true; + } + + // name + // + if (t[2UL]) + { + i.name_value.capacity (i.name_size); + grew = true; + } + + // organization + // + if (t[3UL]) + { + i.organization_value.capacity (i.organization_size); + grew = true; + } + + // email + // + if (t[4UL]) + { + i.email_value.capacity (i.email_size); + grew = true; + } + + // start_date + // + t[5UL] = false; + + // end_date + // + t[6UL] = false; + + return grew; + } + + void access::object_traits_impl< ::bpkg::certificate, 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::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; + n++; + } + + // fingerprint + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.fingerprint_value.data (); + b[n].size = &i.fingerprint_size; + b[n].capacity = i.fingerprint_value.capacity (); + b[n].is_null = &i.fingerprint_null; + n++; + + // name + // + 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++; + + // organization + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.organization_value.data (); + b[n].size = &i.organization_size; + b[n].capacity = i.organization_value.capacity (); + b[n].is_null = &i.organization_null; + n++; + + // email + // + b[n].type = sqlite::image_traits< + ::std::string, + sqlite::id_text>::bind_value; + b[n].buffer = i.email_value.data (); + b[n].size = &i.email_size; + b[n].capacity = i.email_value.capacity (); + b[n].is_null = &i.email_null; + n++; + + // start_date + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.start_date_value; + b[n].is_null = &i.start_date_null; + n++; + + // end_date + // + b[n].type = sqlite::bind::integer; + b[n].buffer = &i.end_date_value; + b[n].is_null = &i.end_date_null; + n++; + } + + void access::object_traits_impl< ::bpkg::certificate, 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::certificate, 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) + { + ::std::string const& v = + o.id; + + 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, + v); + i.id_null = is_null; + grew = grew || (cap != i.id_value.capacity ()); + } + + // fingerprint + // + { + ::std::string const& v = + o.fingerprint; + + bool is_null (false); + std::size_t cap (i.fingerprint_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.fingerprint_value, + i.fingerprint_size, + is_null, + v); + i.fingerprint_null = is_null; + grew = grew || (cap != i.fingerprint_value.capacity ()); + } + + // name + // + { + ::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 ()); + } + + // organization + // + { + ::std::string const& v = + o.organization; + + bool is_null (false); + std::size_t cap (i.organization_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.organization_value, + i.organization_size, + is_null, + v); + i.organization_null = is_null; + grew = grew || (cap != i.organization_value.capacity ()); + } + + // email + // + { + ::std::string const& v = + o.email; + + bool is_null (false); + std::size_t cap (i.email_value.capacity ()); + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_image ( + i.email_value, + i.email_size, + is_null, + v); + i.email_null = is_null; + grew = grew || (cap != i.email_value.capacity ()); + } + + // start_date + // + { + ::butl::timestamp const& v = + o.start_date; + + // From package.hxx:84:14 + ::uint64_t const& vt = + std::chrono::duration_cast < std::chrono::nanoseconds > ((v).time_since_epoch ()).count (); + + bool is_null (false); + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::set_image ( + i.start_date_value, + is_null, + vt); + i.start_date_null = is_null; + } + + // end_date + // + { + ::butl::timestamp const& v = + o.end_date; + + // From package.hxx:84:14 + ::uint64_t const& vt = + std::chrono::duration_cast < std::chrono::nanoseconds > ((v).time_since_epoch ()).count (); + + bool is_null (false); + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::set_image ( + i.end_date_value, + is_null, + vt); + i.end_date_null = is_null; + } + + return grew; + } + + void access::object_traits_impl< ::bpkg::certificate, 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 + // + { + ::std::string& v = + o.id; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.id_value, + i.id_size, + i.id_null); + } + + // fingerprint + // + { + ::std::string& v = + o.fingerprint; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.fingerprint_value, + i.fingerprint_size, + i.fingerprint_null); + } + + // 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); + } + + // organization + // + { + ::std::string& v = + o.organization; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.organization_value, + i.organization_size, + i.organization_null); + } + + // email + // + { + ::std::string& v = + o.email; + + sqlite::value_traits< + ::std::string, + sqlite::id_text >::set_value ( + v, + i.email_value, + i.email_size, + i.email_null); + } + + // start_date + // + { + ::butl::timestamp& v = + o.start_date; + + ::uint64_t vt; + + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::set_value ( + vt, + i.start_date_value, + i.start_date_null); + + // From package.hxx:84:14 + v = butl::timestamp (std::chrono::duration_cast < butl::timestamp::duration > (std::chrono::nanoseconds (vt))); + } + + // end_date + // + { + ::butl::timestamp& v = + o.end_date; + + ::uint64_t vt; + + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::set_value ( + vt, + i.end_date_value, + i.end_date_null); + + // From package.hxx:84:14 + v = butl::timestamp (std::chrono::duration_cast < butl::timestamp::duration > (std::chrono::nanoseconds (vt))); + } + } + + void access::object_traits_impl< ::bpkg::certificate, 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::certificate, id_sqlite >::persist_statement[] = + "INSERT INTO \"main\".\"certificate\" " + "(\"id\", " + "\"fingerprint\", " + "\"name\", " + "\"organization\", " + "\"email\", " + "\"start_date\", " + "\"end_date\") " + "VALUES " + "(?, ?, ?, ?, ?, ?, ?)"; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::find_statement[] = + "SELECT " + "\"main\".\"certificate\".\"id\", " + "\"main\".\"certificate\".\"fingerprint\", " + "\"main\".\"certificate\".\"name\", " + "\"main\".\"certificate\".\"organization\", " + "\"main\".\"certificate\".\"email\", " + "\"main\".\"certificate\".\"start_date\", " + "\"main\".\"certificate\".\"end_date\" " + "FROM \"main\".\"certificate\" " + "WHERE \"main\".\"certificate\".\"id\"=?"; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::update_statement[] = + "UPDATE \"main\".\"certificate\" " + "SET " + "\"fingerprint\"=?, " + "\"name\"=?, " + "\"organization\"=?, " + "\"email\"=?, " + "\"start_date\"=?, " + "\"end_date\"=? " + "WHERE \"id\"=?"; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::erase_statement[] = + "DELETE FROM \"main\".\"certificate\" " + "WHERE \"id\"=?"; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::query_statement[] = + "SELECT " + "\"main\".\"certificate\".\"id\", " + "\"main\".\"certificate\".\"fingerprint\", " + "\"main\".\"certificate\".\"name\", " + "\"main\".\"certificate\".\"organization\", " + "\"main\".\"certificate\".\"email\", " + "\"main\".\"certificate\".\"start_date\", " + "\"main\".\"certificate\".\"end_date\" " + "FROM \"main\".\"certificate\""; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::erase_query_statement[] = + "DELETE FROM \"main\".\"certificate\""; + + const char access::object_traits_impl< ::bpkg::certificate, id_sqlite >::table_name[] = + "\"main\".\"certificate\""; + + void access::object_traits_impl< ::bpkg::certificate, 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 (); + + callback (db, + obj, + callback_event::post_persist); + } + + void access::object_traits_impl< ::bpkg::certificate, 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::certificate, 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::certificate, id_sqlite >::pointer_type + access::object_traits_impl< ::bpkg::certificate, 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::certificate, 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::certificate, 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::certificate, 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::certificate, id_sqlite >::object_type > + access::object_traits_impl< ::bpkg::certificate, 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::certificate, 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::certificate, 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::certificate, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // package_dependent + // + + bool access::view_traits_impl< ::bpkg::package_dependent, 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::view_traits_impl< ::bpkg::package_dependent, 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); + + // 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; + } + + void access::view_traits_impl< ::bpkg::package_dependent, id_sqlite >:: + init (view_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); + } + } + } + + access::view_traits_impl< ::bpkg::package_dependent, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::package_dependent, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"pp\".\"package\", " + "\"pp\".\"min_version_epoch\", " + "\"pp\".\"min_version_canonical_upstream\", " + "\"pp\".\"min_version_canonical_release\", " + "\"pp\".\"min_version_revision\", " + "\"pp\".\"min_version_iteration\", " + "\"pp\".\"min_version_upstream\", " + "\"pp\".\"min_version_release\", " + "\"pp\".\"max_version_epoch\", " + "\"pp\".\"max_version_canonical_upstream\", " + "\"pp\".\"max_version_canonical_release\", " + "\"pp\".\"max_version_revision\", " + "\"pp\".\"max_version_iteration\", " + "\"pp\".\"max_version_upstream\", " + "\"pp\".\"max_version_release\", " + "\"pp\".\"min_open\", " + "\"pp\".\"max_open\" "); + + r += "FROM \"main\".\"selected_package_prerequisites\" AS \"pp\""; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::package_dependent, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::package_dependent, 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::package_dependent, 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::package_dependent, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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_repository_count + // + + bool access::view_traits_impl< ::bpkg::fragment_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::fragment_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::fragment_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::fragment_repository_count, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::fragment_repository_count, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "count(*) "); + + r += "FROM \"main\".\"repository_fragments\""; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::fragment_repository_count, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::fragment_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::fragment_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::fragment_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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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_repository + // + + bool access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // object + // + if (object_traits_impl< ::bpkg::repository, id_sqlite >::grow ( + i.object_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::fragment_repository, 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); + + // object + // + object_traits_impl< ::bpkg::repository, id_sqlite >::bind ( + b + n, i.object_value, sk); + n += 5UL; + } + + void access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // object pre + // + typedef ::bpkg::repository object_object_type; + typedef object_traits_impl<object_object_type, id_sqlite> object_object_traits; + typedef object_object_traits::pointer_type object_pointer_type; + typedef object_object_traits::pointer_traits object_pointer_traits; + typedef object_object_traits::pointer_cache_traits object_cache_traits; + + object_object_traits::id_type object_id; + object_pointer_type object_p; + object_pointer_traits::guard object_pg; + object_cache_traits::insert_guard object_ig; + object_object_type* object_o (0); + + { + if (!(i.object_value.name_null)) + { + object_id = object_object_traits::id (i.object_value); + object_p = object_cache_traits::find (*db, object_id); + + if (object_pointer_traits::null_ptr (object_p)) + { + object_p = object_factory<object_object_type, object_pointer_type>::create (); + object_pg.reset (object_p); + object_ig.reset (object_cache_traits::insert (*db, object_id, object_p)); + object_o = object_pointer_traits::get_ptr (object_p); + } + } + } + + // object + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::pre_load); + object_object_traits::init (*object_o, i.object_value, db); + object_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<object_object_type> ()); + object_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + object_object_traits::id_image_type& i (sts.id_image ()); + object_object_traits::init (i, object_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + object_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + object_object_traits::load_ (sts, *object_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // object post + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::post_load); + object_cache_traits::load (object_ig.position ()); + object_ig.release (); + object_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.object = ::std::shared_ptr< ::bpkg::repository > ( + std::move (object_p)); + } + } + + access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"main\".\"repository\".\"name\", " + "\"main\".\"repository\".\"url\", " + "\"main\".\"repository\".\"type\", " + "\"main\".\"repository\".\"certificate\", " + "\"main\".\"repository\".\"local\" "); + + r += "FROM \"main\".\"repository\""; + + r += " INNER JOIN \"main\".\"repository_fragments\" AS \"rfs\" ON"; + // From package.hxx:1731:5 + r += "rfs.repository = " + query_columns::repository::name; + + r += " INNER JOIN \"main\".\"repository_fragment\" ON"; + // From package.hxx:1733:5 + r += "rfs.fragment = " + query_columns::repository_fragment::name; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::fragment_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_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::fragment_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_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::fragment_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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // repository_complement_dependent + // + + const char alias_traits< ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::complement_tag>:: + table_name[] = "\"complement\""; + + bool access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // object + // + if (object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::grow ( + i.object_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::repository_complement_dependent, 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); + + // object + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::bind ( + b + n, i.object_value, sk); + n += 3UL; + } + + void access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // object pre + // + typedef ::bpkg::repository_fragment object_object_type; + typedef object_traits_impl<object_object_type, id_sqlite> object_object_traits; + typedef object_object_traits::pointer_type object_pointer_type; + typedef object_object_traits::pointer_traits object_pointer_traits; + typedef object_object_traits::pointer_cache_traits object_cache_traits; + + object_object_traits::id_type object_id; + object_pointer_type object_p; + object_pointer_traits::guard object_pg; + object_cache_traits::insert_guard object_ig; + object_object_type* object_o (0); + + { + if (!(i.object_value.name_null)) + { + object_id = object_object_traits::id (i.object_value); + object_p = object_cache_traits::find (*db, object_id); + + if (object_pointer_traits::null_ptr (object_p)) + { + object_p = object_factory<object_object_type, object_pointer_type>::create (); + object_pg.reset (object_p); + object_ig.reset (object_cache_traits::insert (*db, object_id, object_p)); + object_o = object_pointer_traits::get_ptr (object_p); + } + } + } + + // object + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::pre_load); + object_object_traits::init (*object_o, i.object_value, db); + object_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<object_object_type> ()); + object_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + object_object_traits::id_image_type& i (sts.id_image ()); + object_object_traits::init (i, object_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + object_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + object_object_traits::load_ (sts, *object_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // object post + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::post_load); + object_cache_traits::load (object_ig.position ()); + object_ig.release (); + object_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.object = ::std::shared_ptr< ::bpkg::repository_fragment > ( + std::move (object_p)); + } + } + + access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"main\".\"repository_fragment\".\"name\", " + "\"main\".\"repository_fragment\".\"url\", " + "\"main\".\"repository_fragment\".\"type\" "); + + r += "FROM \"main\".\"repository\" AS \"complement\""; + + r += " INNER JOIN \"main\".\"repository_fragment_complements\" AS \"rfc\" ON"; + // From package.hxx:1746:5 + r += "rfc.complement = " + query_columns::complement::name; + + r += " INNER JOIN \"main\".\"repository_fragment\" ON"; + // From package.hxx:1748:5 + r += "rfc.repository_fragment = " + query_columns::repository_fragment::name; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::repository_complement_dependent, 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_complement_dependent, 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_complement_dependent, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // repository_prerequisite_dependent + // + + const char alias_traits< ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::prerequisite_tag>:: + table_name[] = "\"prerequisite\""; + + bool access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // object + // + if (object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::grow ( + i.object_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, 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); + + // object + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::bind ( + b + n, i.object_value, sk); + n += 3UL; + } + + void access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // object pre + // + typedef ::bpkg::repository_fragment object_object_type; + typedef object_traits_impl<object_object_type, id_sqlite> object_object_traits; + typedef object_object_traits::pointer_type object_pointer_type; + typedef object_object_traits::pointer_traits object_pointer_traits; + typedef object_object_traits::pointer_cache_traits object_cache_traits; + + object_object_traits::id_type object_id; + object_pointer_type object_p; + object_pointer_traits::guard object_pg; + object_cache_traits::insert_guard object_ig; + object_object_type* object_o (0); + + { + if (!(i.object_value.name_null)) + { + object_id = object_object_traits::id (i.object_value); + object_p = object_cache_traits::find (*db, object_id); + + if (object_pointer_traits::null_ptr (object_p)) + { + object_p = object_factory<object_object_type, object_pointer_type>::create (); + object_pg.reset (object_p); + object_ig.reset (object_cache_traits::insert (*db, object_id, object_p)); + object_o = object_pointer_traits::get_ptr (object_p); + } + } + } + + // object + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::pre_load); + object_object_traits::init (*object_o, i.object_value, db); + object_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<object_object_type> ()); + object_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + object_object_traits::id_image_type& i (sts.id_image ()); + object_object_traits::init (i, object_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + object_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + object_object_traits::load_ (sts, *object_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // object post + // + { + if (object_o != 0) + { + object_object_traits::callback (*db, *object_o, callback_event::post_load); + object_cache_traits::load (object_ig.position ()); + object_ig.release (); + object_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.object = ::std::shared_ptr< ::bpkg::repository_fragment > ( + std::move (object_p)); + } + } + + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"main\".\"repository_fragment\".\"name\", " + "\"main\".\"repository_fragment\".\"url\", " + "\"main\".\"repository_fragment\".\"type\" "); + + r += "FROM \"main\".\"repository\" AS \"prerequisite\""; + + r += " INNER JOIN \"main\".\"repository_fragment_prerequisites\" AS \"rfp\" ON"; + // From package.hxx:1761:5 + r += "rfp.prerequisite = " + query_columns::prerequisite::name; + + r += " INNER JOIN \"main\".\"repository_fragment\" ON"; + // From package.hxx:1763:5 + r += "rfp.repository_fragment = " + query_columns::repository_fragment::name; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, 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_prerequisite_dependent, 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_prerequisite_dependent, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } + + // repository_fragment_package + // + + const char alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::package_tag>:: + table_name[] = "\"package\""; + + bool access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // package + // + if (object_traits_impl< ::bpkg::available_package, id_sqlite >::grow ( + i.package_value, t + 0UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::repository_fragment_package, 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); + + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::bind ( + b + n, i.package_value, sk); + n += 15UL; + } + + void access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // package pre + // + typedef ::bpkg::available_package package_object_type; + typedef object_traits_impl<package_object_type, id_sqlite> package_object_traits; + typedef package_object_traits::pointer_type package_pointer_type; + typedef package_object_traits::pointer_traits package_pointer_traits; + typedef package_object_traits::pointer_cache_traits package_cache_traits; + + package_object_traits::id_type package_id; + package_pointer_type package_p; + package_pointer_traits::guard package_pg; + package_cache_traits::insert_guard package_ig; + package_object_type* package_o (0); + + { + if (!composite_value_traits< package_object_traits::id_type, id_sqlite >::get_null ( + i.package_value.id_value)) + { + package_id = package_object_traits::id (i.package_value); + package_p = package_cache_traits::find (*db, package_id); + + if (package_pointer_traits::null_ptr (package_p)) + { + package_p = object_factory<package_object_type, package_pointer_type>::create (); + package_pg.reset (package_p); + package_ig.reset (package_cache_traits::insert (*db, package_id, package_p)); + package_o = package_pointer_traits::get_ptr (package_p); + } + } + } + + // package + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::pre_load); + package_object_traits::init (*package_o, i.package_value, db); + package_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<package_object_type> ()); + package_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + package_object_traits::id_image_type& i (sts.id_image ()); + package_object_traits::init (i, package_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + package_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + package_object_traits::load_ (sts, *package_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // package post + // + { + if (package_o != 0) + { + package_object_traits::callback (*db, *package_o, callback_event::post_load); + package_cache_traits::load (package_ig.position ()); + package_ig.release (); + package_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.package = ::std::shared_ptr< ::bpkg::available_package > ( + std::move (package_p)); + } + } + + access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"package\".\"name\", " + "\"package\".\"version_epoch\", " + "\"package\".\"version_canonical_upstream\", " + "\"package\".\"version_canonical_release\", " + "\"package\".\"version_revision\", " + "\"package\".\"version_iteration\", " + "\"package\".\"version_upstream\", " + "\"package\".\"version_release\", " + "\"package\".\"upstream_version\", " + "\"package\".\"type\", " + "\"package\".\"project\", " + "\"package\".\"alt_naming\", " + "\"package\".\"bootstrap_build\", " + "\"package\".\"root_build\", " + "\"package\".\"sha256sum\" "); + + r += "FROM \"main\".\"repository_fragment\""; + + r += " INNER JOIN \"main\".\"available_package_locations\" AS \"pl\" ON"; + // From package.hxx:1775:5 + r += "pl.repository_fragment = " + query_columns::repository_fragment::name; + + r += " INNER JOIN \"main\".\"available_package\" AS \"package\" ON"; + // From package.hxx:1777:5 + r += "pl.name = " + query_columns::package::id.name + "AND" + "pl.version_epoch = " + query_columns::package::id.version.epoch + "AND" + "pl.version_canonical_upstream = " + query_columns::package::id.version.canonical_upstream + "AND" + "pl.version_canonical_release = " + query_columns::package::id.version.canonical_release + "AND" + "pl.version_revision = " + query_columns::package::id.version.revision + "AND" + "pl.version_iteration = " + query_columns::package::id.version.iteration; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::repository_fragment_package, 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_package, 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_package, 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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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_repository_fragment + // + + const char alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::package_tag>:: + table_name[] = "\"package\""; + + bool access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >:: + grow (image_type& i, + bool* t) + { + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (t); + + bool grew (false); + + // package_id + // + if (composite_value_traits< ::bpkg::available_package_id, id_sqlite >::grow ( + i.package_id_value, t + 0UL)) + grew = true; + + // repository_fragment + // + if (object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::grow ( + i.repository_fragment_value, t + 6UL)) + grew = true; + + return grew; + } + + void access::view_traits_impl< ::bpkg::package_repository_fragment, 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); + + // package_id + // + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::bind ( + b + n, i.package_id_value, sk); + n += 6UL; + + // repository_fragment + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::bind ( + b + n, i.repository_fragment_value, sk); + n += 3UL; + } + + void access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >:: + init (view_type& o, + const image_type& i, + database* db) + { + ODB_POTENTIALLY_UNUSED (o); + ODB_POTENTIALLY_UNUSED (i); + ODB_POTENTIALLY_UNUSED (db); + + sqlite::connection& conn ( + sqlite::transaction::current ().connection (*db)); + + // repository_fragment pre + // + typedef ::bpkg::repository_fragment repository_fragment_object_type; + typedef object_traits_impl<repository_fragment_object_type, id_sqlite> repository_fragment_object_traits; + typedef repository_fragment_object_traits::pointer_type repository_fragment_pointer_type; + typedef repository_fragment_object_traits::pointer_traits repository_fragment_pointer_traits; + typedef repository_fragment_object_traits::pointer_cache_traits repository_fragment_cache_traits; + + repository_fragment_object_traits::id_type repository_fragment_id; + repository_fragment_pointer_type repository_fragment_p; + repository_fragment_pointer_traits::guard repository_fragment_pg; + repository_fragment_cache_traits::insert_guard repository_fragment_ig; + repository_fragment_object_type* repository_fragment_o (0); + + { + if (!(i.repository_fragment_value.name_null)) + { + repository_fragment_id = repository_fragment_object_traits::id (i.repository_fragment_value); + repository_fragment_p = repository_fragment_cache_traits::find (*db, repository_fragment_id); + + if (repository_fragment_pointer_traits::null_ptr (repository_fragment_p)) + { + repository_fragment_p = object_factory<repository_fragment_object_type, repository_fragment_pointer_type>::create (); + repository_fragment_pg.reset (repository_fragment_p); + repository_fragment_ig.reset (repository_fragment_cache_traits::insert (*db, repository_fragment_id, repository_fragment_p)); + repository_fragment_o = repository_fragment_pointer_traits::get_ptr (repository_fragment_p); + } + } + } + + // package_id + // + { + ::bpkg::available_package_id& v = + o.package_id; + + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::init ( + v, + i.package_id_value, + db); + } + + // repository_fragment + // + { + if (repository_fragment_o != 0) + { + repository_fragment_object_traits::callback (*db, *repository_fragment_o, callback_event::pre_load); + repository_fragment_object_traits::init (*repository_fragment_o, i.repository_fragment_value, db); + repository_fragment_object_traits::statements_type& sts ( + conn.statement_cache ().find_object<repository_fragment_object_type> ()); + repository_fragment_object_traits::statements_type::auto_lock l (sts); + assert (l.locked ()) /* Must be a top-level call. */; + + repository_fragment_object_traits::id_image_type& i (sts.id_image ()); + repository_fragment_object_traits::init (i, repository_fragment_id); + sqlite::binding& idb (sts.id_image_binding ()); + if (i.version != sts.id_image_version () || idb.version == 0) + { + repository_fragment_object_traits::bind (idb.bind, i); + sts.id_image_version (i.version); + idb.version++; + } + + repository_fragment_object_traits::load_ (sts, *repository_fragment_o, false); + sts.load_delayed (0); + l.unlock (); + } + } + + // repository_fragment post + // + { + if (repository_fragment_o != 0) + { + repository_fragment_object_traits::callback (*db, *repository_fragment_o, callback_event::post_load); + repository_fragment_cache_traits::load (repository_fragment_ig.position ()); + repository_fragment_ig.release (); + repository_fragment_pg.release (); + } + + // If a compiler error points to the line below, then + // it most likely means that a pointer used in view + // member cannot be initialized from an object pointer. + // + o.repository_fragment = ::std::shared_ptr< ::bpkg::repository_fragment > ( + std::move (repository_fragment_p)); + } + } + + access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::query_base_type + access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >:: + query_statement (const query_base_type& q) + { + query_base_type r ( + "SELECT " + "\"package\".\"name\", " + "\"package\".\"version_epoch\", " + "\"package\".\"version_canonical_upstream\", " + "\"package\".\"version_canonical_release\", " + "\"package\".\"version_revision\", " + "\"package\".\"version_iteration\", " + "\"main\".\"repository_fragment\".\"name\", " + "\"main\".\"repository_fragment\".\"url\", " + "\"main\".\"repository_fragment\".\"type\" "); + + r += "FROM \"main\".\"repository_fragment\""; + + r += " INNER JOIN \"main\".\"available_package_locations\" AS \"pl\" ON"; + // From package.hxx:1796:5 + r += "pl.repository_fragment = " + query_columns::repository_fragment::name; + + r += " INNER JOIN \"main\".\"available_package\" AS \"package\" ON"; + // From package.hxx:1798:5 + r += "pl.name = " + query_columns::package::id.name + "AND" + "pl.version_epoch = " + query_columns::package::id.version.epoch + "AND" + "pl.version_canonical_upstream = " + query_columns::package::id.version.canonical_upstream + "AND" + "pl.version_canonical_release = " + query_columns::package::id.version.canonical_release + "AND" + "pl.version_revision = " + query_columns::package::id.version.revision + "AND" + "pl.version_iteration = " + query_columns::package::id.version.iteration; + + if (!q.empty ()) + { + r += " "; + r += q.clause_prefix (); + r += q; + } + + return r; + } + + result< access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::view_type > + access::view_traits_impl< ::bpkg::package_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_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::package_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_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::package_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 ()); + ODB_POTENTIALLY_UNUSED (tr); + + // 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)); + } +} + +namespace odb +{ + static bool + create_schema (database& db, unsigned short pass, bool drop) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (pass); + ODB_POTENTIALLY_UNUSED (drop); + + if (drop) + { + switch (pass) + { + case 1: + { + return true; + } + case 2: + { + db.execute ("DROP TABLE IF EXISTS \"main\".\"certificate\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"selected_package_config_variables\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"selected_package_dependency_alternatives\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"selected_package_prerequisites\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"selected_package\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_distribution_values\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_buildfiles\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_tests\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_dependency_alternative_dependencies\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_dependency_alternatives\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_dependencies\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_locations\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package_languages\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"available_package\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"repository_fragments\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"repository\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"repository_fragment_prerequisites\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"repository_fragment_complements\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"repository_fragment\""); + db.execute ("DROP TABLE IF EXISTS \"main\".\"configuration\""); + db.execute ("CREATE TABLE IF NOT EXISTS \"main\".\"schema_version\" (\n" + " \"name\" TEXT NOT NULL PRIMARY KEY,\n" + " \"version\" INTEGER NOT NULL,\n" + " \"migration\" INTEGER NOT NULL)"); + db.execute ("DELETE FROM \"main\".\"schema_version\"\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + else + { + switch (pass) + { + case 1: + { + db.execute ("CREATE TABLE \"main\".\"configuration\" (\n" + " \"id\" INTEGER NULL PRIMARY KEY AUTOINCREMENT,\n" + " \"uuid\" TEXT NULL,\n" + " \"name\" TEXT NULL,\n" + " \"type\" TEXT NULL,\n" + " \"path\" TEXT NULL,\n" + " \"explicit\" INTEGER NULL)"); + db.execute ("CREATE UNIQUE INDEX \"main\".\"configuration_uuid_i\"\n" + " ON \"configuration\" (\"uuid\")"); + db.execute ("CREATE UNIQUE INDEX \"main\".\"configuration_name_i\"\n" + " ON \"configuration\" (\"name\")"); + db.execute ("CREATE UNIQUE INDEX \"main\".\"configuration_path_i\"\n" + " ON \"configuration\" (\"path\")"); + db.execute ("CREATE TABLE \"main\".\"repository_fragment\" (\n" + " \"name\" TEXT NULL PRIMARY KEY,\n" + " \"url\" TEXT NULL,\n" + " \"type\" TEXT NULL)"); + db.execute ("CREATE TABLE \"main\".\"repository_fragment_complements\" (\n" + " \"repository_fragment\" TEXT NULL,\n" + " \"complement\" TEXT NULL,\n" + " CONSTRAINT \"repository_fragment_fk\"\n" + " FOREIGN KEY (\"repository_fragment\")\n" + " REFERENCES \"repository_fragment\" (\"name\")\n" + " ON DELETE CASCADE,\n" + " CONSTRAINT \"complement_fk\"\n" + " FOREIGN KEY (\"complement\")\n" + " REFERENCES \"repository\" (\"name\")\n" + " DEFERRABLE INITIALLY DEFERRED)"); + db.execute ("CREATE INDEX \"main\".\"repository_fragment_complements_repository_fragment_i\"\n" + " ON \"repository_fragment_complements\" (\"repository_fragment\")"); + db.execute ("CREATE TABLE \"main\".\"repository_fragment_prerequisites\" (\n" + " \"repository_fragment\" TEXT NULL,\n" + " \"prerequisite\" TEXT NULL,\n" + " CONSTRAINT \"repository_fragment_fk\"\n" + " FOREIGN KEY (\"repository_fragment\")\n" + " REFERENCES \"repository_fragment\" (\"name\")\n" + " ON DELETE CASCADE,\n" + " CONSTRAINT \"prerequisite_fk\"\n" + " FOREIGN KEY (\"prerequisite\")\n" + " REFERENCES \"repository\" (\"name\")\n" + " DEFERRABLE INITIALLY DEFERRED)"); + db.execute ("CREATE INDEX \"main\".\"repository_fragment_prerequisites_repository_fragment_i\"\n" + " ON \"repository_fragment_prerequisites\" (\"repository_fragment\")"); + db.execute ("CREATE TABLE \"main\".\"repository\" (\n" + " \"name\" TEXT NULL PRIMARY KEY,\n" + " \"url\" TEXT NULL,\n" + " \"type\" TEXT NULL,\n" + " \"certificate\" TEXT NULL,\n" + " \"local\" INTEGER NULL)"); + db.execute ("CREATE TABLE \"main\".\"repository_fragments\" (\n" + " \"repository\" TEXT NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"friendly_name\" TEXT NULL,\n" + " \"fragment\" TEXT NULL,\n" + " CONSTRAINT \"repository_fk\"\n" + " FOREIGN KEY (\"repository\")\n" + " REFERENCES \"repository\" (\"name\")\n" + " ON DELETE CASCADE,\n" + " CONSTRAINT \"fragment_fk\"\n" + " FOREIGN KEY (\"fragment\")\n" + " REFERENCES \"repository_fragment\" (\"name\")\n" + " DEFERRABLE INITIALLY DEFERRED)"); + db.execute ("CREATE INDEX \"main\".\"repository_fragments_repository_i\"\n" + " ON \"repository_fragments\" (\"repository\")"); + db.execute ("CREATE INDEX \"main\".\"repository_fragments_index_i\"\n" + " ON \"repository_fragments\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"available_package\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"version_upstream\" TEXT NULL,\n" + " \"version_release\" TEXT NULL,\n" + " \"upstream_version\" TEXT NULL,\n" + " \"type\" TEXT NULL,\n" + " \"project\" TEXT NULL COLLATE NOCASE,\n" + " \"alt_naming\" INTEGER NULL DEFAULT 0,\n" + " \"bootstrap_build\" TEXT NULL DEFAULT '',\n" + " \"root_build\" TEXT NULL,\n" + " \"sha256sum\" TEXT NULL,\n" + " PRIMARY KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\"))"); + db.execute ("CREATE TABLE \"main\".\"available_package_languages\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"language_name\" TEXT NULL,\n" + " \"language_impl\" INTEGER NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_languages_object_id_i\"\n" + " ON \"available_package_languages\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE INDEX \"main\".\"available_package_languages_index_i\"\n" + " ON \"available_package_languages\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_locations\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"repository_fragment\" TEXT NULL,\n" + " \"location\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE,\n" + " CONSTRAINT \"repository_fragment_fk\"\n" + " FOREIGN KEY (\"repository_fragment\")\n" + " REFERENCES \"repository_fragment\" (\"name\")\n" + " DEFERRABLE INITIALLY DEFERRED)"); + db.execute ("CREATE INDEX \"main\".\"available_package_locations_object_id_i\"\n" + " ON \"available_package_locations\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_dependencies\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"buildtime\" INTEGER NULL,\n" + " \"comment\" TEXT NULL,\n" + " \"type\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_dependencies_object_id_i\"\n" + " ON \"available_package_dependencies\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE INDEX \"main\".\"available_package_dependencies_index_i\"\n" + " ON \"available_package_dependencies\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_dependency_alternatives\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"dependency_index\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"enable\" TEXT NULL,\n" + " \"reflect\" TEXT NULL,\n" + " \"prefer\" TEXT NULL,\n" + " \"accept\" TEXT NULL,\n" + " \"require\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_dependency_alternatives_object_id_i\"\n" + " ON \"available_package_dependency_alternatives\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_dependency_alternative_dependencies\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"dependency_index\" INTEGER NULL,\n" + " \"alternative_index\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"dep_name\" TEXT NULL COLLATE NOCASE,\n" + " \"dep_min_version_epoch\" INTEGER NULL,\n" + " \"dep_min_version_canonical_upstream\" TEXT NULL,\n" + " \"dep_min_version_canonical_release\" TEXT NULL,\n" + " \"dep_min_version_revision\" INTEGER NULL,\n" + " \"dep_min_version_iteration\" INTEGER NULL,\n" + " \"dep_min_version_upstream\" TEXT NULL,\n" + " \"dep_min_version_release\" TEXT NULL,\n" + " \"dep_max_version_epoch\" INTEGER NULL,\n" + " \"dep_max_version_canonical_upstream\" TEXT NULL,\n" + " \"dep_max_version_canonical_release\" TEXT NULL,\n" + " \"dep_max_version_revision\" INTEGER NULL,\n" + " \"dep_max_version_iteration\" INTEGER NULL,\n" + " \"dep_max_version_upstream\" TEXT NULL,\n" + " \"dep_max_version_release\" TEXT NULL,\n" + " \"dep_min_open\" INTEGER NULL,\n" + " \"dep_max_open\" INTEGER NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_dependency_alternative_dependencies_object_id_i\"\n" + " ON \"available_package_dependency_alternative_dependencies\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_tests\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"test_name\" TEXT NULL COLLATE NOCASE,\n" + " \"test_min_version_epoch\" INTEGER NULL,\n" + " \"test_min_version_canonical_upstream\" TEXT NULL,\n" + " \"test_min_version_canonical_release\" TEXT NULL,\n" + " \"test_min_version_revision\" INTEGER NULL,\n" + " \"test_min_version_iteration\" INTEGER NULL,\n" + " \"test_min_version_upstream\" TEXT NULL,\n" + " \"test_min_version_release\" TEXT NULL,\n" + " \"test_max_version_epoch\" INTEGER NULL,\n" + " \"test_max_version_canonical_upstream\" TEXT NULL,\n" + " \"test_max_version_canonical_release\" TEXT NULL,\n" + " \"test_max_version_revision\" INTEGER NULL,\n" + " \"test_max_version_iteration\" INTEGER NULL,\n" + " \"test_max_version_upstream\" TEXT NULL,\n" + " \"test_max_version_release\" TEXT NULL,\n" + " \"test_min_open\" INTEGER NULL,\n" + " \"test_max_open\" INTEGER NULL,\n" + " \"test_type\" TEXT NULL,\n" + " \"test_buildtime\" INTEGER NULL DEFAULT 0,\n" + " \"test_enable\" TEXT NULL,\n" + " \"test_reflect\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_tests_object_id_i\"\n" + " ON \"available_package_tests\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE INDEX \"main\".\"available_package_tests_index_i\"\n" + " ON \"available_package_tests\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_buildfiles\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"path\" TEXT NULL,\n" + " \"content\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_buildfiles_object_id_i\"\n" + " ON \"available_package_buildfiles\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE INDEX \"main\".\"available_package_buildfiles_index_i\"\n" + " ON \"available_package_buildfiles\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"available_package_distribution_values\" (\n" + " \"name\" TEXT NULL COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL COLLATE BINARY,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"index\" INTEGER NULL,\n" + " \"dist_name\" TEXT NULL,\n" + " \"dist_value\" TEXT NULL,\n" + " CONSTRAINT \"object_id_fk\"\n" + " FOREIGN KEY (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " REFERENCES \"available_package\" (\"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"available_package_distribution_values_object_id_i\"\n" + " ON \"available_package_distribution_values\" (\n" + " \"name\",\n" + " \"version_epoch\",\n" + " \"version_canonical_upstream\",\n" + " \"version_canonical_release\",\n" + " \"version_revision\",\n" + " \"version_iteration\")"); + db.execute ("CREATE INDEX \"main\".\"available_package_distribution_values_index_i\"\n" + " ON \"available_package_distribution_values\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"selected_package\" (\n" + " \"name\" TEXT NULL PRIMARY KEY COLLATE NOCASE,\n" + " \"version_epoch\" INTEGER NULL,\n" + " \"version_canonical_upstream\" TEXT NULL,\n" + " \"version_canonical_release\" TEXT NULL,\n" + " \"version_revision\" INTEGER NULL,\n" + " \"version_iteration\" INTEGER NULL,\n" + " \"version_upstream\" TEXT NULL,\n" + " \"version_release\" TEXT NULL,\n" + " \"state\" TEXT NULL,\n" + " \"substate\" TEXT NULL,\n" + " \"hold_package\" INTEGER NULL,\n" + " \"hold_version\" INTEGER NULL,\n" + " \"repository_fragment_url\" TEXT NULL,\n" + " \"repository_fragment_type\" TEXT NULL,\n" + " \"archive\" TEXT NULL,\n" + " \"purge_archive\" INTEGER NULL,\n" + " \"src_root\" TEXT NULL,\n" + " \"purge_src\" INTEGER NULL,\n" + " \"manifest_checksum\" TEXT NULL,\n" + " \"buildfiles_checksum\" TEXT NULL,\n" + " \"out_root\" TEXT NULL,\n" + " \"config_checksum\" TEXT NULL DEFAULT '')"); + db.execute ("CREATE TABLE \"main\".\"selected_package_prerequisites\" (\n" + " \"package\" TEXT NULL COLLATE NOCASE,\n" + " \"configuration\" TEXT NULL,\n" + " \"prerequisite\" TEXT NULL COLLATE NOCASE,\n" + " \"min_version_epoch\" INTEGER NULL,\n" + " \"min_version_canonical_upstream\" TEXT NULL,\n" + " \"min_version_canonical_release\" TEXT NULL,\n" + " \"min_version_revision\" INTEGER NULL,\n" + " \"min_version_iteration\" INTEGER NULL,\n" + " \"min_version_upstream\" TEXT NULL,\n" + " \"min_version_release\" TEXT NULL,\n" + " \"max_version_epoch\" INTEGER NULL,\n" + " \"max_version_canonical_upstream\" TEXT NULL,\n" + " \"max_version_canonical_release\" TEXT NULL,\n" + " \"max_version_revision\" INTEGER NULL,\n" + " \"max_version_iteration\" INTEGER NULL,\n" + " \"max_version_upstream\" TEXT NULL,\n" + " \"max_version_release\" TEXT NULL,\n" + " \"min_open\" INTEGER NULL,\n" + " \"max_open\" INTEGER NULL,\n" + " CONSTRAINT \"package_fk\"\n" + " FOREIGN KEY (\"package\")\n" + " REFERENCES \"selected_package\" (\"name\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"selected_package_prerequisites_package_i\"\n" + " ON \"selected_package_prerequisites\" (\"package\")"); + db.execute ("CREATE TABLE \"main\".\"selected_package_dependency_alternatives\" (\n" + " \"package\" TEXT NULL COLLATE NOCASE,\n" + " \"index\" INTEGER NULL,\n" + " \"position\" INTEGER NULL,\n" + " CONSTRAINT \"package_fk\"\n" + " FOREIGN KEY (\"package\")\n" + " REFERENCES \"selected_package\" (\"name\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"selected_package_dependency_alternatives_package_i\"\n" + " ON \"selected_package_dependency_alternatives\" (\"package\")"); + db.execute ("CREATE INDEX \"main\".\"selected_package_dependency_alternatives_index_i\"\n" + " ON \"selected_package_dependency_alternatives\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"selected_package_config_variables\" (\n" + " \"package\" TEXT NULL COLLATE NOCASE,\n" + " \"index\" INTEGER NULL,\n" + " \"name\" TEXT NULL,\n" + " \"source\" TEXT NULL,\n" + " CONSTRAINT \"package_fk\"\n" + " FOREIGN KEY (\"package\")\n" + " REFERENCES \"selected_package\" (\"name\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"selected_package_config_variables_package_i\"\n" + " ON \"selected_package_config_variables\" (\"package\")"); + db.execute ("CREATE INDEX \"main\".\"selected_package_config_variables_index_i\"\n" + " ON \"selected_package_config_variables\" (\"index\")"); + db.execute ("CREATE TABLE \"main\".\"certificate\" (\n" + " \"id\" TEXT NULL PRIMARY KEY,\n" + " \"fingerprint\" TEXT NULL,\n" + " \"name\" TEXT NULL,\n" + " \"organization\" TEXT NULL,\n" + " \"email\" TEXT NULL,\n" + " \"start_date\" INTEGER NULL,\n" + " \"end_date\" INTEGER NULL)"); + return true; + } + case 2: + { + db.execute ("CREATE TABLE IF NOT EXISTS \"main\".\"schema_version\" (\n" + " \"name\" TEXT NOT NULL PRIMARY KEY,\n" + " \"version\" INTEGER NOT NULL,\n" + " \"migration\" INTEGER NOT NULL)"); + db.execute ("INSERT OR IGNORE INTO \"main\".\"schema_version\" (\n" + " \"name\", \"version\", \"migration\")\n" + " VALUES ('', 26, 0)"); + return false; + } + } + } + + return false; + } + + static const schema_catalog_create_entry + create_schema_entry_ ( + id_sqlite, + "", + &create_schema); + + static const schema_catalog_migrate_entry + migrate_schema_entry_23_ ( + id_sqlite, + "", + 23ULL, + 0); + + static bool + migrate_schema_24 (database& db, unsigned short pass, bool pre) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (pass); + ODB_POTENTIALLY_UNUSED (pre); + + if (pre) + { + switch (pass) + { + case 1: + { + db.execute ("ALTER TABLE \"main\".\"selected_package\"\n" + " ADD COLUMN \"config_checksum\" TEXT NULL DEFAULT ''"); + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"version\" = 24, \"migration\" = 1\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + else + { + switch (pass) + { + case 1: + { + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"migration\" = 0\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + + return false; + } + + static const schema_catalog_migrate_entry + migrate_schema_entry_24_ ( + id_sqlite, + "", + 24ULL, + &migrate_schema_24); + + static bool + migrate_schema_25 (database& db, unsigned short pass, bool pre) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (pass); + ODB_POTENTIALLY_UNUSED (pre); + + if (pre) + { + switch (pass) + { + case 1: + { + db.execute ("CREATE TABLE \"main\".\"selected_package_dependency_alternatives\" (\n" + " \"package\" TEXT NULL COLLATE NOCASE,\n" + " \"index\" INTEGER NULL,\n" + " \"position\" INTEGER NULL,\n" + " CONSTRAINT \"package_fk\"\n" + " FOREIGN KEY (\"package\")\n" + " REFERENCES \"selected_package\" (\"name\")\n" + " ON DELETE CASCADE)"); + db.execute ("CREATE INDEX \"main\".\"selected_package_dependency_alternatives_package_i\"\n" + " ON \"selected_package_dependency_alternatives\" (\"package\")"); + db.execute ("CREATE INDEX \"main\".\"selected_package_dependency_alternatives_index_i\"\n" + " ON \"selected_package_dependency_alternatives\" (\"index\")"); + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"version\" = 25, \"migration\" = 1\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + else + { + switch (pass) + { + case 1: + { + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"selected_package_prerequisites\"\n" + " SET \"config_dependency_index\" = NULL,\n" + " \"config_alternative_index\" = NULL"); + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"migration\" = 0\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + + return false; + } + + static const schema_catalog_migrate_entry + migrate_schema_entry_25_ ( + id_sqlite, + "", + 25ULL, + &migrate_schema_25); + + static bool + migrate_schema_26 (database& db, unsigned short pass, bool pre) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (pass); + ODB_POTENTIALLY_UNUSED (pre); + + if (pre) + { + switch (pass) + { + case 1: + { + db.execute ("ALTER TABLE \"main\".\"available_package_tests\"\n" + " ADD COLUMN \"test_enable\" TEXT NULL"); + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"version\" = 26, \"migration\" = 1\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + else + { + switch (pass) + { + case 1: + { + return true; + } + case 2: + { + db.execute ("UPDATE \"main\".\"schema_version\"\n" + " SET \"migration\" = 0\n" + " WHERE \"name\" = ''"); + return false; + } + } + } + + return false; + } + + static const schema_catalog_migrate_entry + migrate_schema_entry_26_ ( + id_sqlite, + "", + 26ULL, + &migrate_schema_26); +} + +#include <odb/post.hxx> diff --git a/bpkg/package-odb.hxx b/bpkg/package-odb.hxx new file mode 100644 index 0000000..a60efde --- /dev/null +++ b/bpkg/package-odb.hxx @@ -0,0 +1,6023 @@ +// -*- C++ -*- +// +// This file was generated by ODB, object-relational mapping (ORM) +// compiler for C++. +// + +#ifndef BPKG_PACKAGE_ODB_HXX +#define BPKG_PACKAGE_ODB_HXX + +// Begin prologue. +// +#include <libbutl/small-vector-odb.hxx> +#include <bpkg/pointer-traits.hxx> +#include <bpkg/wrapper-traits.hxx> +#include <bpkg/value-traits.hxx> +// +// End prologue. + +#include <odb/version.hxx> + +#if ODB_VERSION != 20478UL +#error ODB runtime version mismatch +#endif + +#include <odb/pre.hxx> + +#include <bpkg/package.hxx> + +#include <memory> +#include <cstddef> +#include <utility> + +#include <odb/core.hxx> +#include <odb/traits.hxx> +#include <odb/callback.hxx> +#include <odb/wrapper-traits.hxx> +#include <odb/pointer-traits.hxx> +#include <odb/container-traits.hxx> +#include <odb/session.hxx> +#include <odb/cache-traits.hxx> +#include <odb/prepared-query.hxx> +#include <odb/result.hxx> +#include <odb/simple-object-result.hxx> +#include <odb/view-image.hxx> +#include <odb/view-result.hxx> + +#include <odb/details/unused.hxx> +#include <odb/details/shared-ptr.hxx> + +namespace odb +{ + // configuration + // + template <> + struct class_traits< ::bpkg::configuration > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::configuration > + { + public: + typedef ::bpkg::configuration object_type; + typedef ::std::shared_ptr< ::bpkg::configuration > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::bpkg::optional_uint64_t id_type; + + static const bool auto_id = true; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + no_op_pointer_cache_traits<pointer_type> + pointer_cache_traits; + + typedef + no_op_reference_cache_traits<object_type> + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // repository_fragment + // + template <> + struct class_traits< ::bpkg::repository_fragment > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::repository_fragment > + { + public: + typedef ::bpkg::repository_fragment object_type; + typedef ::std::shared_ptr< ::bpkg::repository_fragment > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::std::string id_type; + + static const bool auto_id = false; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + odb::pointer_cache_traits< + pointer_type, + odb::session > + pointer_cache_traits; + + typedef + odb::reference_cache_traits< + object_type, + odb::session > + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // repository_fragment_count + // + template <> + struct class_traits< ::bpkg::repository_fragment_count > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::repository_fragment_count > + { + public: + typedef ::bpkg::repository_fragment_count view_type; + typedef ::bpkg::repository_fragment_count* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // repository + // + template <> + struct class_traits< ::bpkg::repository > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::repository > + { + public: + typedef ::bpkg::repository object_type; + typedef ::std::shared_ptr< ::bpkg::repository > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::std::string id_type; + + static const bool auto_id = false; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + odb::pointer_cache_traits< + pointer_type, + odb::session > + pointer_cache_traits; + + typedef + odb::reference_cache_traits< + object_type, + odb::session > + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // repository_count + // + template <> + struct class_traits< ::bpkg::repository_count > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::repository_count > + { + public: + typedef ::bpkg::repository_count view_type; + typedef ::bpkg::repository_count* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // available_package + // + template <> + struct class_traits< ::bpkg::available_package > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::available_package > + { + public: + typedef ::bpkg::available_package object_type; + typedef ::std::shared_ptr< ::bpkg::available_package > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::bpkg::available_package_id id_type; + + static const bool auto_id = false; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + odb::pointer_cache_traits< + pointer_type, + odb::session > + pointer_cache_traits; + + typedef + odb::reference_cache_traits< + object_type, + odb::session > + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // available_package_count + // + template <> + struct class_traits< ::bpkg::available_package_count > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::available_package_count > + { + public: + typedef ::bpkg::available_package_count view_type; + typedef ::bpkg::available_package_count* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // available_test + // + template <> + struct class_traits< ::bpkg::available_test > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::available_test > + { + public: + typedef ::bpkg::available_test view_type; + typedef ::bpkg::available_test* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // available_main + // + template <> + struct class_traits< ::bpkg::available_main > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::available_main > + { + public: + typedef ::bpkg::available_main view_type; + typedef ::bpkg::available_main* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // selected_package + // + template <> + struct class_traits< ::bpkg::selected_package > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::selected_package > + { + public: + typedef ::bpkg::selected_package object_type; + typedef ::std::shared_ptr< ::bpkg::selected_package > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::bpkg::package_name id_type; + + static const bool auto_id = false; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + odb::pointer_cache_traits< + pointer_type, + odb::session > + pointer_cache_traits; + + typedef + odb::reference_cache_traits< + object_type, + odb::session > + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // certificate + // + template <> + struct class_traits< ::bpkg::certificate > + { + static const class_kind kind = class_object; + }; + + template <> + class access::object_traits< ::bpkg::certificate > + { + public: + typedef ::bpkg::certificate object_type; + typedef ::std::shared_ptr< ::bpkg::certificate > pointer_type; + typedef odb::pointer_traits<pointer_type> pointer_traits; + + static const bool polymorphic = false; + + typedef ::std::string id_type; + + static const bool auto_id = false; + + static const bool abstract = false; + + static id_type + id (const object_type&); + + typedef + odb::pointer_cache_traits< + pointer_type, + odb::session > + pointer_cache_traits; + + typedef + odb::reference_cache_traits< + object_type, + odb::session > + reference_cache_traits; + + static void + callback (database&, object_type&, callback_event); + + static void + callback (database&, const object_type&, callback_event); + }; + + // package_dependent + // + template <> + struct class_traits< ::bpkg::package_dependent > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::package_dependent > + { + public: + typedef ::bpkg::package_dependent view_type; + typedef ::bpkg::package_dependent* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // fragment_repository_count + // + template <> + struct class_traits< ::bpkg::fragment_repository_count > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::fragment_repository_count > + { + public: + typedef ::bpkg::fragment_repository_count view_type; + typedef ::bpkg::fragment_repository_count* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // fragment_repository + // + template <> + struct class_traits< ::bpkg::fragment_repository > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::fragment_repository > + { + public: + typedef ::bpkg::fragment_repository view_type; + typedef ::bpkg::fragment_repository* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // repository_complement_dependent + // + template <> + struct class_traits< ::bpkg::repository_complement_dependent > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::repository_complement_dependent > + { + public: + typedef ::bpkg::repository_complement_dependent view_type; + typedef ::bpkg::repository_complement_dependent* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // repository_prerequisite_dependent + // + template <> + struct class_traits< ::bpkg::repository_prerequisite_dependent > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::repository_prerequisite_dependent > + { + public: + typedef ::bpkg::repository_prerequisite_dependent view_type; + typedef ::bpkg::repository_prerequisite_dependent* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // repository_fragment_package + // + template <> + struct class_traits< ::bpkg::repository_fragment_package > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::repository_fragment_package > + { + public: + typedef ::bpkg::repository_fragment_package view_type; + typedef ::bpkg::repository_fragment_package* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; + + // package_repository_fragment + // + template <> + struct class_traits< ::bpkg::package_repository_fragment > + { + static const class_kind kind = class_view; + }; + + template <> + class access::view_traits< ::bpkg::package_repository_fragment > + { + public: + typedef ::bpkg::package_repository_fragment view_type; + typedef ::bpkg::package_repository_fragment* pointer_type; + + static void + callback (database&, view_type&, callback_event); + }; +} + +#include <odb/details/buffer.hxx> + +#include <odb/sqlite/version.hxx> +#include <odb/sqlite/forward.hxx> +#include <odb/sqlite/binding.hxx> +#include <odb/sqlite/sqlite-types.hxx> +#include <odb/sqlite/query.hxx> + +namespace odb +{ + // _version + // + template <> + class access::composite_value_traits< ::bpkg::_version, id_sqlite > + { + public: + typedef ::bpkg::_version value_type; + + struct image_type + { + // epoch + // + long long epoch_value; + bool epoch_null; + + // canonical_upstream + // + details::buffer canonical_upstream_value; + std::size_t canonical_upstream_size; + bool canonical_upstream_null; + + // canonical_release + // + details::buffer canonical_release_value; + std::size_t canonical_release_size; + bool canonical_release_null; + + // revision + // + long long revision_value; + bool revision_null; + + // iteration + // + long long iteration_value; + bool iteration_null; + + // upstream + // + details::buffer upstream_value; + std::size_t upstream_size; + bool upstream_null; + + // release + // + details::buffer release_value; + std::size_t release_size; + bool release_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 7UL; + }; + + // language + // + template <> + class access::composite_value_traits< ::bpkg::language, id_sqlite > + { + public: + typedef ::bpkg::language value_type; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // impl + // + long long impl_value; + bool impl_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // version_constraint + // + template <> + class access::composite_value_traits< ::bpkg::version_constraint, id_sqlite > + { + public: + typedef ::bpkg::version_constraint value_type; + + struct image_type + { + // min_version + // + composite_value_traits< ::bpkg::_version, id_sqlite >::image_type min_version_value; + + // max_version + // + composite_value_traits< ::bpkg::_version, id_sqlite >::image_type max_version_value; + + // min_open + // + long long min_open_value; + bool min_open_null; + + // max_open + // + long long max_open_value; + bool max_open_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 16UL; + }; + + // dependency + // + template <> + class access::composite_value_traits< ::bpkg::dependency, id_sqlite > + { + public: + typedef ::bpkg::dependency value_type; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // constraint + // + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::image_type constraint_value; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 17UL; + }; + + // dependency_alternative + // + template <> + class access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite > + { + public: + typedef ::bpkg::dependency_alternative value_type; + + struct image_type + { + // enable + // + details::buffer enable_value; + std::size_t enable_size; + bool enable_null; + + // reflect + // + details::buffer reflect_value; + std::size_t reflect_size; + bool reflect_null; + + // prefer + // + details::buffer prefer_value; + std::size_t prefer_size; + bool prefer_null; + + // accept + // + details::buffer accept_value; + std::size_t accept_size; + bool accept_null; + + // require + // + details::buffer require_value; + std::size_t require_size; + bool require_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 5UL; + }; + + // dependency_alternatives + // + template <> + class access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite > + { + public: + typedef ::bpkg::dependency_alternatives value_type; + + struct image_type + { + // buildtime + // + long long buildtime_value; + bool buildtime_null; + + // comment + // + details::buffer comment_value; + std::size_t comment_size; + bool comment_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // test_dependency + // + template <> + class access::composite_value_traits< ::bpkg::test_dependency, id_sqlite > + { + public: + typedef ::bpkg::test_dependency value_type; + + struct image_type: composite_value_traits< ::bpkg::dependency, id_sqlite >::image_type + { + // type + // + details::buffer type_value; + std::size_t type_size; + bool type_null; + + // buildtime + // + long long buildtime_value; + bool buildtime_null; + + // enable + // + details::buffer enable_value; + std::size_t enable_size; + bool enable_null; + + // reflect + // + details::buffer reflect_value; + std::size_t reflect_size; + bool reflect_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 21UL; + }; + + // buildfile + // + template <> + class access::composite_value_traits< ::bpkg::buildfile, id_sqlite > + { + public: + typedef ::bpkg::buildfile value_type; + + struct image_type + { + // path + // + details::buffer path_value; + std::size_t path_size; + bool path_null; + + // content + // + details::buffer content_value; + std::size_t content_size; + bool content_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // distribution_name_value + // + template <> + class access::composite_value_traits< ::bpkg::distribution_name_value, id_sqlite > + { + public: + typedef ::bpkg::distribution_name_value value_type; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // value + // + details::buffer value_value; + std::size_t value_size; + bool value_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // configuration + // + template <typename A> + struct query_columns< ::bpkg::configuration, id_sqlite, A > + { + // id + // + typedef + sqlite::query_column< + sqlite::value_traits< + long unsigned int, + sqlite::id_integer >::query_type, + sqlite::id_integer > + id_type_; + + static const id_type_ id; + + // uuid + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + uuid_type_; + + static const uuid_type_ uuid; + + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // type + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + type_type_; + + static const type_type_ type; + + // path + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + path_type_; + + static const path_type_ path; + + // expl + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + expl_type_; + + static const expl_type_ expl; + }; + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::id_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + id (A::table_name, "\"id\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::uuid_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + uuid (A::table_name, "\"uuid\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::name_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::type_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + type (A::table_name, "\"type\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::path_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + path (A::table_name, "\"path\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::configuration, id_sqlite, A >::expl_type_ + query_columns< ::bpkg::configuration, id_sqlite, A >:: + expl (A::table_name, "\"explicit\"", 0); + + template <typename A> + struct pointer_query_columns< ::bpkg::configuration, id_sqlite, A >: + query_columns< ::bpkg::configuration, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::configuration, id_sqlite >: + public access::object_traits< ::bpkg::configuration > + { + public: + struct id_image_type + { + long long id_value; + bool id_null; + + std::size_t version; + }; + + struct image_type + { + // id + // + long long id_value; + bool id_null; + + // uuid + // + details::buffer uuid_value; + std::size_t uuid_size; + bool uuid_null; + + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // type + // + details::buffer type_value; + std::size_t type_size; + bool type_null; + + // path + // + details::buffer path_value; + std::size_t path_size; + bool path_null; + + // expl + // + long long expl_value; + bool expl_null; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + using object_traits<object_type>::id; + + static id_type + id (const id_image_type&); + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 6UL; + static const std::size_t id_column_count = 1UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::configuration, id_common >: + public access::object_traits_impl< ::bpkg::configuration, id_sqlite > + { + }; + + // canonical_version + // + template <> + class access::composite_value_traits< ::bpkg::canonical_version, id_sqlite > + { + public: + typedef ::bpkg::canonical_version value_type; + + struct image_type + { + // epoch + // + long long epoch_value; + bool epoch_null; + + // canonical_upstream + // + details::buffer canonical_upstream_value; + std::size_t canonical_upstream_size; + bool canonical_upstream_null; + + // canonical_release + // + details::buffer canonical_release_value; + std::size_t canonical_release_size; + bool canonical_release_null; + + // revision + // + long long revision_value; + bool revision_null; + + // iteration + // + long long iteration_value; + bool iteration_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 5UL; + }; + + // upstream_version + // + template <> + class access::composite_value_traits< ::bpkg::upstream_version, id_sqlite > + { + public: + typedef ::bpkg::upstream_version value_type; + + struct image_type + { + // upstream_ + // + details::buffer upstream_value; + std::size_t upstream_size; + bool upstream_null; + + // release_ + // + details::buffer release_value; + std::size_t release_size; + bool release_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // _repository_location + // + template <> + class access::composite_value_traits< ::bpkg::_repository_location, id_sqlite > + { + public: + typedef ::bpkg::_repository_location value_type; + + struct image_type + { + // url + // + details::buffer url_value; + std::size_t url_size; + bool url_null; + + // type + // + details::buffer type_value; + std::size_t type_size; + bool type_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // repository_fragment + // + template <typename A> + struct query_columns< ::bpkg::repository_fragment, id_sqlite, A > + { + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // location + // + struct location_class_ + { + location_class_ () + { + } + + // url + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + url_type_; + + static const url_type_ url; + + // type + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + type_type_; + + static const type_type_ type; + }; + + static const location_class_ location; + }; + + template <typename A> + const typename query_columns< ::bpkg::repository_fragment, id_sqlite, A >::name_type_ + query_columns< ::bpkg::repository_fragment, id_sqlite, A >:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location_class_::url_type_ + query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location_class_:: + url (A::table_name, "\"url\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location_class_::type_type_ + query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location_class_:: + type (A::table_name, "\"type\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location_class_ + query_columns< ::bpkg::repository_fragment, id_sqlite, A >::location; + + template <typename A> + struct pointer_query_columns< ::bpkg::repository_fragment, id_sqlite, A >: + query_columns< ::bpkg::repository_fragment, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >: + public access::object_traits< ::bpkg::repository_fragment > + { + public: + struct id_image_type + { + details::buffer id_value; + std::size_t id_size; + bool id_null; + + std::size_t version; + }; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // location + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::image_type location_value; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + // complements + // + struct complements_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 2UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::repository_fragment::dependencies container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::value_type value_type; + + typedef set_functions<value_type> functions_type; + typedef sqlite::container_statements< complements_traits > statements_type; + + struct data_image_type + { + // value + // + details::buffer value_value; + std::size_t value_size; + bool value_null; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const value_type&); + + static void + init (value_type&, + const data_image_type&, + database*); + + static void + insert (const value_type&, void*); + + static bool + select (value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // prerequisites + // + struct prerequisites_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 2UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::repository_fragment::dependencies container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::value_type value_type; + + typedef set_functions<value_type> functions_type; + typedef sqlite::container_statements< prerequisites_traits > statements_type; + + struct data_image_type + { + // value + // + details::buffer value_value; + std::size_t value_size; + bool value_null; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const value_type&); + + static void + init (value_type&, + const data_image_type&, + database*); + + static void + insert (const value_type&, void*); + + static bool + select (value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + using object_traits<object_type>::id; + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 3UL; + static const std::size_t id_column_count = 1UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, const object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::repository_fragment, id_common >: + public access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > + { + }; + + // repository_fragment_count + // + template <> + class access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >: + public access::view_traits< ::bpkg::repository_fragment_count > + { + public: + struct image_type + { + // result + // + long long result_value; + bool result_null; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 1UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::repository_fragment_count, id_common >: + public access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite > + { + }; + + // fragment_type + // + template <> + class access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite > + { + public: + typedef ::bpkg::repository::fragment_type value_type; + + struct image_type + { + // friendly_name + // + details::buffer friendly_name_value; + std::size_t friendly_name_size; + bool friendly_name_null; + + // fragment + // + details::buffer fragment_value; + std::size_t fragment_size; + bool fragment_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // repository + // + template <typename A> + struct query_columns< ::bpkg::repository, id_sqlite, A > + { + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // location + // + struct location_class_ + { + location_class_ () + { + } + + // url + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + url_type_; + + static const url_type_ url; + + // type + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + type_type_; + + static const type_type_ type; + }; + + static const location_class_ location; + + // certificate + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + certificate_type_; + + static const certificate_type_ certificate; + + // local + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + local_type_; + + static const local_type_ local; + }; + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::name_type_ + query_columns< ::bpkg::repository, id_sqlite, A >:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::location_class_::url_type_ + query_columns< ::bpkg::repository, id_sqlite, A >::location_class_:: + url (A::table_name, "\"url\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::location_class_::type_type_ + query_columns< ::bpkg::repository, id_sqlite, A >::location_class_:: + type (A::table_name, "\"type\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::location_class_ + query_columns< ::bpkg::repository, id_sqlite, A >::location; + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::certificate_type_ + query_columns< ::bpkg::repository, id_sqlite, A >:: + certificate (A::table_name, "\"certificate\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::repository, id_sqlite, A >::local_type_ + query_columns< ::bpkg::repository, id_sqlite, A >:: + local (A::table_name, "\"local\"", 0); + + template <typename A> + struct pointer_query_columns< ::bpkg::repository, id_sqlite, A >: + query_columns< ::bpkg::repository, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::repository, id_sqlite >: + public access::object_traits< ::bpkg::repository > + { + public: + struct id_image_type + { + details::buffer id_value; + std::size_t id_size; + bool id_null; + + std::size_t version; + }; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // location + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::image_type location_value; + + // certificate + // + details::buffer certificate_value; + std::size_t certificate_size; + bool certificate_null; + + // local + // + long long local_value; + bool local_null; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + // fragments + // + struct fragments_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 4UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::repository::fragments_type container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< fragments_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + using object_traits<object_type>::id; + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 5UL; + static const std::size_t id_column_count = 1UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, const object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::repository, id_common >: + public access::object_traits_impl< ::bpkg::repository, id_sqlite > + { + }; + + // repository_count + // + template <> + class access::view_traits_impl< ::bpkg::repository_count, id_sqlite >: + public access::view_traits< ::bpkg::repository_count > + { + public: + struct image_type + { + // result + // + long long result_value; + bool result_null; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 1UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::repository_count, id_common >: + public access::view_traits_impl< ::bpkg::repository_count, id_sqlite > + { + }; + + // package_location + // + template <> + class access::composite_value_traits< ::bpkg::package_location, id_sqlite > + { + public: + typedef ::bpkg::package_location value_type; + + struct image_type + { + // repository_fragment + // + details::buffer repository_fragment_value; + std::size_t repository_fragment_size; + bool repository_fragment_null; + + // location + // + details::buffer location_value; + std::size_t location_size; + bool location_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // dependency_alternatives_ex + // + template <> + class access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite > + { + public: + typedef ::bpkg::dependency_alternatives_ex value_type; + + struct image_type: composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::image_type + { + // type + // + details::buffer type_value; + std::size_t type_size; + bool type_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 3UL; + }; + + // available_package_id + // + template <> + class access::composite_value_traits< ::bpkg::available_package_id, id_sqlite > + { + public: + typedef ::bpkg::available_package_id value_type; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // version + // + composite_value_traits< ::bpkg::canonical_version, id_sqlite >::image_type version_value; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 6UL; + }; + + // _dependency_alternative_key + // + template <> + class access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite > + { + public: + typedef ::bpkg::available_package::_dependency_alternative_key value_type; + + struct image_type + { + // outer + // + long long outer_value; + bool outer_null; + + // inner + // + long long inner_value; + bool inner_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // _dependency_key + // + template <> + class access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite > + { + public: + typedef ::bpkg::available_package::_dependency_key value_type; + + struct image_type + { + // outer + // + long long outer_value; + bool outer_null; + + // middle + // + long long middle_value; + bool middle_null; + + // inner + // + long long inner_value; + bool inner_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 3UL; + }; + + // available_package + // + template <typename A> + struct query_columns< ::bpkg::available_package, id_sqlite, A > + { + // id + // + struct id_class_ + { + id_class_ () + { + } + + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // version + // + struct version_class_1_ + { + version_class_1_ () + { + } + + // epoch + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + epoch_type_; + + static const epoch_type_ epoch; + + // canonical_upstream + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + canonical_upstream_type_; + + static const canonical_upstream_type_ canonical_upstream; + + // canonical_release + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + canonical_release_type_; + + static const canonical_release_type_ canonical_release; + + // revision + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + revision_type_; + + static const revision_type_ revision; + + // iteration + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + iteration_type_; + + static const iteration_type_ iteration; + }; + + static const version_class_1_ version; + }; + + static const id_class_ id; + + // version + // + struct version_class_ + { + version_class_ () + { + } + + // upstream + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + upstream_type_; + + static const upstream_type_ upstream; + + // release + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + release_type_; + + static const release_type_ release; + }; + + static const version_class_ version; + + // upstream_version + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + upstream_version_type_; + + static const upstream_version_type_ upstream_version; + + // type + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + type_type_; + + static const type_type_ type; + + // project + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::butl::project_name, + sqlite::id_text >::query_type, + sqlite::id_text > + project_type_; + + static const project_type_ project; + + // alt_naming + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + alt_naming_type_; + + static const alt_naming_type_ alt_naming; + + // bootstrap_build + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + bootstrap_build_type_; + + static const bootstrap_build_type_ bootstrap_build; + + // root_build + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + root_build_type_; + + static const root_build_type_ root_build; + + // sha256sum + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + sha256sum_type_; + + static const sha256sum_type_ sha256sum; + }; + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::name_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_::epoch_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_:: + epoch (A::table_name, "\"version_epoch\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_::canonical_upstream_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_:: + canonical_upstream (A::table_name, "\"version_canonical_upstream\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_::canonical_release_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_:: + canonical_release (A::table_name, "\"version_canonical_release\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_::revision_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_:: + revision (A::table_name, "\"version_revision\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_::iteration_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_:: + iteration (A::table_name, "\"version_iteration\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version_class_1_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_::version; + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::id_class_ + query_columns< ::bpkg::available_package, id_sqlite, A >::id; + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::version_class_::upstream_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::version_class_:: + upstream (A::table_name, "\"version_upstream\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::version_class_::release_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >::version_class_:: + release (A::table_name, "\"version_release\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::version_class_ + query_columns< ::bpkg::available_package, id_sqlite, A >::version; + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::upstream_version_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + upstream_version (A::table_name, "\"upstream_version\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::type_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + type (A::table_name, "\"type\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::project_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + project (A::table_name, "\"project\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::alt_naming_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + alt_naming (A::table_name, "\"alt_naming\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::bootstrap_build_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + bootstrap_build (A::table_name, "\"bootstrap_build\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::root_build_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + root_build (A::table_name, "\"root_build\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::available_package, id_sqlite, A >::sha256sum_type_ + query_columns< ::bpkg::available_package, id_sqlite, A >:: + sha256sum (A::table_name, "\"sha256sum\"", 0); + + template <typename A> + struct pointer_query_columns< ::bpkg::available_package, id_sqlite, A >: + query_columns< ::bpkg::available_package, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::available_package, id_sqlite >: + public access::object_traits< ::bpkg::available_package > + { + public: + struct id_image_type + { + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::image_type id_value; + + std::size_t version; + }; + + struct image_type + { + // id + // + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::image_type id_value; + + // version + // + composite_value_traits< ::bpkg::available_package::upstream_version_type, id_sqlite >::image_type version_value; + + // upstream_version + // + details::buffer upstream_version_value; + std::size_t upstream_version_size; + bool upstream_version_null; + + // type + // + details::buffer type_value; + std::size_t type_size; + bool type_null; + + // project + // + details::buffer project_value; + std::size_t project_size; + bool project_null; + + // alt_naming + // + long long alt_naming_value; + bool alt_naming_null; + + // bootstrap_build + // + details::buffer bootstrap_build_value; + std::size_t bootstrap_build_size; + bool bootstrap_build_null; + + // root_build + // + details::buffer root_build_value; + std::size_t root_build_size; + bool root_build_null; + + // sha256sum + // + details::buffer sha256sum_value; + std::size_t sha256sum_size; + bool sha256sum_null; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + // languages + // + struct languages_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 9UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::butl::small_vector< ::bpkg::language, 1 > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< languages_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // locations + // + struct locations_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 8UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::butl::small_vector< ::bpkg::package_location, 1 > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< locations_traits > statements_type; + + struct data_image_type + { + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const value_type&); + + static void + init (value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // dependencies + // + struct dependencies_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 10UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::available_package::dependencies_type container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< dependencies_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // dependency_alternatives + // + struct dependency_alternatives_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 13UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::std::map< ::odb::nested_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency_alternative > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::key_type key_type; + typedef container_traits_type::value_type value_type; + + typedef map_functions<key_type, value_type> functions_type; + typedef sqlite::container_statements< dependency_alternatives_traits > statements_type; + + struct data_image_type + { + // key + // + composite_value_traits< key_type, id_sqlite >::image_type key_value; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const key_type*, + const value_type&); + + static void + init (key_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (const key_type&, const value_type&, void*); + + static bool + select (key_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // dependency_alternative_dependencies + // + struct dependency_alternative_dependencies_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 26UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::std::map< ::odb::nested2_key< ::bpkg::dependency_alternatives_ex >, ::bpkg::dependency > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::key_type key_type; + typedef container_traits_type::value_type value_type; + + typedef map_functions<key_type, value_type> functions_type; + typedef sqlite::container_statements< dependency_alternative_dependencies_traits > statements_type; + + struct data_image_type + { + // key + // + composite_value_traits< key_type, id_sqlite >::image_type key_value; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const key_type*, + const value_type&); + + static void + init (key_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (const key_type&, const value_type&, void*); + + static bool + select (key_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // tests + // + struct tests_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 28UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::butl::small_vector< ::bpkg::test_dependency, 1 > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< tests_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // buildfiles + // + struct buildfiles_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 9UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::std::vector< ::bpkg::buildfile > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< buildfiles_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // distribution_values + // + struct distribution_values_traits + { + static const std::size_t id_column_count = 6UL; + static const std::size_t data_column_count = 9UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::std::vector< ::bpkg::distribution_name_value > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< distribution_values_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // languages_section + // + struct languages_section_traits + { + typedef object_traits_impl<object_type, id_sqlite>::image_type image_type; + typedef object_traits_impl<object_type, id_sqlite>::id_image_type id_image_type; + + static const std::size_t id_column_count = 6UL; + static const std::size_t managed_optimistic_load_column_count = 0UL; + static const std::size_t load_column_count = 0UL; + static const std::size_t managed_optimistic_update_column_count = 0UL; + static const std::size_t update_column_count = 0UL; + + static const bool versioned = false; + + static void + load (extra_statement_cache_type&, object_type&); + + static void + update (extra_statement_cache_type&, const object_type&); + }; + + using object_traits<object_type>::id; + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 15UL; + static const std::size_t id_column_count = 6UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, const object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static bool + load (connection&, object_type&, section&); + + static bool + update (connection&, const object_type&, const section&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::available_package, id_common >: + public access::object_traits_impl< ::bpkg::available_package, id_sqlite > + { + }; + + // available_package_count + // + template <> + class access::view_traits_impl< ::bpkg::available_package_count, id_sqlite >: + public access::view_traits< ::bpkg::available_package_count > + { + public: + struct image_type + { + // result + // + long long result_value; + bool result_null; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 1UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::available_package_count, id_common >: + public access::view_traits_impl< ::bpkg::available_package_count, id_sqlite > + { + }; + + // available_test + // + template <> + class access::view_traits_impl< ::bpkg::available_test, id_sqlite >: + public access::view_traits< ::bpkg::available_test > + { + public: + struct image_type + { + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::image_type package_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct package_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 15UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::available_test, id_common >: + public access::view_traits_impl< ::bpkg::available_test, id_sqlite > + { + }; + + // available_main + // + template <> + class access::view_traits_impl< ::bpkg::available_main, id_sqlite >: + public access::view_traits< ::bpkg::available_main > + { + public: + struct image_type + { + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::image_type package_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct package_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 15UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::available_main, id_common >: + public access::view_traits_impl< ::bpkg::available_main, id_sqlite > + { + }; + + // prerequisite_info + // + template <> + class access::composite_value_traits< ::bpkg::prerequisite_info, id_sqlite > + { + public: + typedef ::bpkg::prerequisite_info value_type; + + struct image_type + { + // constraint + // + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::image_type constraint_value; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 16UL; + }; + + // _selected_package_ref + // + template <> + class access::composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite > + { + public: + typedef ::bpkg::_selected_package_ref value_type; + + struct image_type + { + // configuration + // + details::buffer configuration_value; + std::size_t configuration_size; + bool configuration_null; + + // prerequisite + // + details::buffer prerequisite_value; + std::size_t prerequisite_size; + bool prerequisite_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // config_variable + // + template <> + class access::composite_value_traits< ::bpkg::config_variable, id_sqlite > + { + public: + typedef ::bpkg::config_variable value_type; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // source + // + details::buffer source_value; + std::size_t source_size; + bool source_null; + }; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static bool + init (image_type&, + const value_type&, + sqlite::statement_kind); + + static void + init (value_type&, + const image_type&, + database*); + + static bool + get_null (const image_type&); + + static void + set_null (image_type&, + sqlite::statement_kind); + + static const std::size_t column_count = 2UL; + }; + + // selected_package + // + template <typename A> + struct query_columns< ::bpkg::selected_package, id_sqlite, A > + { + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::bpkg::package_name, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // version + // + struct version_class_ + { + version_class_ () + { + } + + // epoch + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint16_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + epoch_type_; + + static const epoch_type_ epoch; + + // canonical_upstream + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + canonical_upstream_type_; + + static const canonical_upstream_type_ canonical_upstream; + + // canonical_release + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + canonical_release_type_; + + static const canonical_release_type_ canonical_release; + + // revision + // + typedef + sqlite::query_column< + sqlite::value_traits< + short unsigned int, + sqlite::id_integer >::query_type, + sqlite::id_integer > + revision_type_; + + static const revision_type_ revision; + + // iteration + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint32_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + iteration_type_; + + static const iteration_type_ iteration; + + // upstream + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + upstream_type_; + + static const upstream_type_ upstream; + + // release + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + release_type_; + + static const release_type_ release; + }; + + static const version_class_ version; + + // state + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + state_type_; + + static const state_type_ state; + + // substate + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + substate_type_; + + static const substate_type_ substate; + + // hold_package + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + hold_package_type_; + + static const hold_package_type_ hold_package; + + // hold_version + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + hold_version_type_; + + static const hold_version_type_ hold_version; + + // repository_fragment + // + struct repository_fragment_class_ + { + repository_fragment_class_ () + { + } + + // url + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + url_type_; + + static const url_type_ url; + + // type + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + type_type_; + + static const type_type_ type; + }; + + static const repository_fragment_class_ repository_fragment; + + // archive + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + archive_type_; + + static const archive_type_ archive; + + // purge_archive + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + purge_archive_type_; + + static const purge_archive_type_ purge_archive; + + // src_root + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + src_root_type_; + + static const src_root_type_ src_root; + + // purge_src + // + typedef + sqlite::query_column< + sqlite::value_traits< + bool, + sqlite::id_integer >::query_type, + sqlite::id_integer > + purge_src_type_; + + static const purge_src_type_ purge_src; + + // manifest_checksum + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + manifest_checksum_type_; + + static const manifest_checksum_type_ manifest_checksum; + + // buildfiles_checksum + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + buildfiles_checksum_type_; + + static const buildfiles_checksum_type_ buildfiles_checksum; + + // out_root + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::basic_string< char >, + sqlite::id_text >::query_type, + sqlite::id_text > + out_root_type_; + + static const out_root_type_ out_root; + + // config_checksum + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + config_checksum_type_; + + static const config_checksum_type_ config_checksum; + }; + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::name_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::epoch_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + epoch (A::table_name, "\"version_epoch\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::canonical_upstream_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + canonical_upstream (A::table_name, "\"version_canonical_upstream\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::canonical_release_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + canonical_release (A::table_name, "\"version_canonical_release\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::revision_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + revision (A::table_name, "\"version_revision\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::iteration_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + iteration (A::table_name, "\"version_iteration\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::upstream_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + upstream (A::table_name, "\"version_upstream\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_::release_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_:: + release (A::table_name, "\"version_release\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::version_class_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::version; + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::state_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + state (A::table_name, "\"state\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::substate_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + substate (A::table_name, "\"substate\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::hold_package_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + hold_package (A::table_name, "\"hold_package\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::hold_version_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + hold_version (A::table_name, "\"hold_version\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment_class_::url_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment_class_:: + url (A::table_name, "\"repository_fragment_url\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment_class_::type_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment_class_:: + type (A::table_name, "\"repository_fragment_type\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment_class_ + query_columns< ::bpkg::selected_package, id_sqlite, A >::repository_fragment; + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::archive_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + archive (A::table_name, "\"archive\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::purge_archive_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + purge_archive (A::table_name, "\"purge_archive\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::src_root_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + src_root (A::table_name, "\"src_root\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::purge_src_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + purge_src (A::table_name, "\"purge_src\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::manifest_checksum_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + manifest_checksum (A::table_name, "\"manifest_checksum\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::buildfiles_checksum_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + buildfiles_checksum (A::table_name, "\"buildfiles_checksum\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::out_root_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + out_root (A::table_name, "\"out_root\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::selected_package, id_sqlite, A >::config_checksum_type_ + query_columns< ::bpkg::selected_package, id_sqlite, A >:: + config_checksum (A::table_name, "\"config_checksum\"", 0); + + template <typename A> + struct pointer_query_columns< ::bpkg::selected_package, id_sqlite, A >: + query_columns< ::bpkg::selected_package, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::selected_package, id_sqlite >: + public access::object_traits< ::bpkg::selected_package > + { + public: + struct id_image_type + { + details::buffer id_value; + std::size_t id_size; + bool id_null; + + std::size_t version; + }; + + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // version + // + composite_value_traits< ::bpkg::_version, id_sqlite >::image_type version_value; + + // state + // + details::buffer state_value; + std::size_t state_size; + bool state_null; + + // substate + // + details::buffer substate_value; + std::size_t substate_size; + bool substate_null; + + // hold_package + // + long long hold_package_value; + bool hold_package_null; + + // hold_version + // + long long hold_version_value; + bool hold_version_null; + + // repository_fragment + // + composite_value_traits< ::bpkg::_repository_location, id_sqlite >::image_type repository_fragment_value; + + // archive + // + details::buffer archive_value; + std::size_t archive_size; + bool archive_null; + + // purge_archive + // + long long purge_archive_value; + bool purge_archive_null; + + // src_root + // + details::buffer src_root_value; + std::size_t src_root_size; + bool src_root_null; + + // purge_src + // + long long purge_src_value; + bool purge_src_null; + + // manifest_checksum + // + details::buffer manifest_checksum_value; + std::size_t manifest_checksum_size; + bool manifest_checksum_null; + + // buildfiles_checksum + // + details::buffer buildfiles_checksum_value; + std::size_t buildfiles_checksum_size; + bool buildfiles_checksum_null; + + // out_root + // + details::buffer out_root_value; + std::size_t out_root_size; + bool out_root_null; + + // config_checksum + // + details::buffer config_checksum_value; + std::size_t config_checksum_size; + bool config_checksum_null; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + // prerequisites + // + struct prerequisites_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 19UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::package_prerequisites container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::key_type key_type; + typedef container_traits_type::value_type value_type; + + typedef map_functions<key_type, value_type> functions_type; + typedef sqlite::container_statements< prerequisites_traits > statements_type; + + struct data_image_type + { + // key + // + composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >::image_type key_value; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + const key_type*, + const value_type&); + + static void + init (key_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (const key_type&, const value_type&, void*); + + static bool + select (key_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // dependency_alternatives + // + struct dependency_alternatives_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 3UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::bpkg::selected_package::indexes_type container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< dependency_alternatives_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + long long value_value; + bool value_null; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // config_variables + // + struct config_variables_traits + { + static const std::size_t id_column_count = 1UL; + static const std::size_t data_column_count = 4UL; + + static const bool versioned = false; + + static const char insert_statement[]; + static const char select_statement[]; + static const char delete_statement[]; + + typedef ::std::vector< ::bpkg::config_variable > container_type; + typedef + odb::access::container_traits<container_type> + container_traits_type; + typedef container_traits_type::index_type index_type; + typedef container_traits_type::value_type value_type; + + typedef ordered_functions<index_type, value_type> functions_type; + typedef sqlite::container_statements< config_variables_traits > statements_type; + + struct data_image_type + { + // index + // + long long index_value; + bool index_null; + + // value + // + composite_value_traits< value_type, id_sqlite >::image_type value_value; + + std::size_t version; + }; + + static void + bind (sqlite::bind*, + const sqlite::bind* id, + std::size_t id_size, + data_image_type&); + + static void + grow (data_image_type&, + bool*); + + static void + init (data_image_type&, + index_type*, + const value_type&); + + static void + init (index_type&, + value_type&, + const data_image_type&, + database*); + + static void + insert (index_type, const value_type&, void*); + + static bool + select (index_type&, value_type&, void*); + + static void + delete_ (void*); + + static void + persist (const container_type&, + statements_type&); + + static void + load (container_type&, + statements_type&); + + static void + update (const container_type&, + statements_type&); + + static void + erase (statements_type&); + }; + + // dependency_alternatives_section + // + struct dependency_alternatives_section_traits + { + typedef object_traits_impl<object_type, id_sqlite>::image_type image_type; + typedef object_traits_impl<object_type, id_sqlite>::id_image_type id_image_type; + + static const std::size_t id_column_count = 1UL; + static const std::size_t managed_optimistic_load_column_count = 0UL; + static const std::size_t load_column_count = 0UL; + static const std::size_t managed_optimistic_update_column_count = 0UL; + static const std::size_t update_column_count = 0UL; + + static const bool versioned = false; + + static void + load (extra_statement_cache_type&, object_type&); + + static void + update (extra_statement_cache_type&, const object_type&); + }; + + using object_traits<object_type>::id; + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 22UL; + static const std::size_t id_column_count = 1UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, const object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static bool + load (connection&, object_type&, section&); + + static bool + update (connection&, const object_type&, const section&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::selected_package, id_common >: + public access::object_traits_impl< ::bpkg::selected_package, id_sqlite > + { + }; + + // certificate + // + template <typename A> + struct query_columns< ::bpkg::certificate, id_sqlite, A > + { + // id + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + id_type_; + + static const id_type_ id; + + // fingerprint + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + fingerprint_type_; + + static const fingerprint_type_ fingerprint; + + // name + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + name_type_; + + static const name_type_ name; + + // organization + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + organization_type_; + + static const organization_type_ organization; + + // email + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::std::string, + sqlite::id_text >::query_type, + sqlite::id_text > + email_type_; + + static const email_type_ email; + + // start_date + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + start_date_type_; + + static const start_date_type_ start_date; + + // end_date + // + typedef + sqlite::query_column< + sqlite::value_traits< + ::uint64_t, + sqlite::id_integer >::query_type, + sqlite::id_integer > + end_date_type_; + + static const end_date_type_ end_date; + }; + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::id_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + id (A::table_name, "\"id\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::fingerprint_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + fingerprint (A::table_name, "\"fingerprint\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::name_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + name (A::table_name, "\"name\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::organization_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + organization (A::table_name, "\"organization\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::email_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + email (A::table_name, "\"email\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::start_date_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + start_date (A::table_name, "\"start_date\"", 0); + + template <typename A> + const typename query_columns< ::bpkg::certificate, id_sqlite, A >::end_date_type_ + query_columns< ::bpkg::certificate, id_sqlite, A >:: + end_date (A::table_name, "\"end_date\"", 0); + + template <typename A> + struct pointer_query_columns< ::bpkg::certificate, id_sqlite, A >: + query_columns< ::bpkg::certificate, id_sqlite, A > + { + }; + + template <> + class access::object_traits_impl< ::bpkg::certificate, id_sqlite >: + public access::object_traits< ::bpkg::certificate > + { + public: + struct id_image_type + { + details::buffer id_value; + std::size_t id_size; + bool id_null; + + std::size_t version; + }; + + struct image_type + { + // id + // + details::buffer id_value; + std::size_t id_size; + bool id_null; + + // fingerprint + // + details::buffer fingerprint_value; + std::size_t fingerprint_size; + bool fingerprint_null; + + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // organization + // + details::buffer organization_value; + std::size_t organization_size; + bool organization_null; + + // email + // + details::buffer email_value; + std::size_t email_size; + bool email_null; + + // start_date + // + long long start_date_value; + bool start_date_null; + + // end_date + // + long long end_date_value; + bool end_date_null; + + std::size_t version; + }; + + struct extra_statement_cache_type; + + using object_traits<object_type>::id; + + static id_type + id (const image_type&); + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&, + sqlite::statement_kind); + + static void + bind (sqlite::bind*, id_image_type&); + + static bool + init (image_type&, + const object_type&, + sqlite::statement_kind); + + static void + init (object_type&, + const image_type&, + database*); + + static void + init (id_image_type&, const id_type&); + + typedef sqlite::object_statements<object_type> statements_type; + + typedef sqlite::query_base query_base_type; + + static const std::size_t column_count = 7UL; + static const std::size_t id_column_count = 1UL; + static const std::size_t inverse_column_count = 0UL; + static const std::size_t readonly_column_count = 0UL; + static const std::size_t managed_optimistic_column_count = 0UL; + + static const std::size_t separate_load_column_count = 0UL; + static const std::size_t separate_update_column_count = 0UL; + + static const bool versioned = false; + + static const char persist_statement[]; + static const char find_statement[]; + static const char update_statement[]; + static const char erase_statement[]; + static const char query_statement[]; + static const char erase_query_statement[]; + + static const char table_name[]; + + static void + persist (database&, const object_type&); + + static pointer_type + find (database&, const id_type&); + + static bool + find (database&, const id_type&, object_type&); + + static bool + reload (database&, object_type&); + + static void + update (database&, const object_type&); + + static void + erase (database&, const id_type&); + + static void + erase (database&, const object_type&); + + static result<object_type> + query (database&, const query_base_type&); + + static unsigned long long + erase_query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + + public: + static bool + find_ (statements_type&, + const id_type*); + + static void + load_ (statements_type&, + object_type&, + bool reload); + }; + + template <> + class access::object_traits_impl< ::bpkg::certificate, id_common >: + public access::object_traits_impl< ::bpkg::certificate, id_sqlite > + { + }; + + // package_dependent + // + template <> + class access::view_traits_impl< ::bpkg::package_dependent, id_sqlite >: + public access::view_traits< ::bpkg::package_dependent > + { + public: + struct image_type + { + // name + // + details::buffer name_value; + std::size_t name_size; + bool name_null; + + // constraint + // + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::image_type constraint_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns + { + }; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 17UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::package_dependent, id_common >: + public access::view_traits_impl< ::bpkg::package_dependent, id_sqlite > + { + }; + + // fragment_repository_count + // + template <> + class access::view_traits_impl< ::bpkg::fragment_repository_count, id_sqlite >: + public access::view_traits< ::bpkg::fragment_repository_count > + { + public: + struct image_type + { + // result + // + long long result_value; + bool result_null; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns + { + }; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 1UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::fragment_repository_count, id_common >: + public access::view_traits_impl< ::bpkg::fragment_repository_count, id_sqlite > + { + }; + + // fragment_repository + // + template <> + class access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >: + public access::view_traits< ::bpkg::fragment_repository > + { + public: + struct image_type + { + // object + // + object_traits_impl< ::bpkg::repository, id_sqlite >::image_type object_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 5UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::fragment_repository, id_common >: + public access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite > + { + }; + + // repository_complement_dependent + // + template <> + class access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >: + public access::view_traits< ::bpkg::repository_complement_dependent > + { + public: + struct image_type + { + // object + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::image_type object_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct complement_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 3UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::repository_complement_dependent, id_common >: + public access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite > + { + }; + + // repository_prerequisite_dependent + // + template <> + class access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >: + public access::view_traits< ::bpkg::repository_prerequisite_dependent > + { + public: + struct image_type + { + // object + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::image_type object_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct prerequisite_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 3UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_common >: + public access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite > + { + }; + + // repository_fragment_package + // + template <> + class access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >: + public access::view_traits< ::bpkg::repository_fragment_package > + { + public: + struct image_type + { + // package + // + object_traits_impl< ::bpkg::available_package, id_sqlite >::image_type package_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct package_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 15UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::repository_fragment_package, id_common >: + public access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite > + { + }; + + // package_repository_fragment + // + template <> + class access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >: + public access::view_traits< ::bpkg::package_repository_fragment > + { + public: + struct image_type + { + // package_id + // + composite_value_traits< ::bpkg::available_package_id, id_sqlite >::image_type package_id_value; + + // repository_fragment + // + object_traits_impl< ::bpkg::repository_fragment, id_sqlite >::image_type repository_fragment_value; + + std::size_t version; + }; + + typedef sqlite::view_statements<view_type> statements_type; + + struct package_tag; + + typedef sqlite::query_base query_base_type; + struct query_columns; + + static const bool versioned = false; + + static bool + grow (image_type&, + bool*); + + static void + bind (sqlite::bind*, + image_type&); + + static void + init (view_type&, + const image_type&, + database*); + + static const std::size_t column_count = 9UL; + + static query_base_type + query_statement (const query_base_type&); + + static result<view_type> + query (database&, const query_base_type&); + + static odb::details::shared_ptr<prepared_query_impl> + prepare_query (connection&, const char*, const query_base_type&); + + static odb::details::shared_ptr<result_impl> + execute_query (prepared_query_impl&); + }; + + template <> + class access::view_traits_impl< ::bpkg::package_repository_fragment, id_common >: + public access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite > + { + }; + + // configuration + // + // repository_fragment + // + // repository_fragment_count + // + struct access::view_traits_impl< ::bpkg::repository_fragment_count, id_sqlite >::query_columns: + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + { + }; + + // repository + // + // repository_count + // + struct access::view_traits_impl< ::bpkg::repository_count, id_sqlite >::query_columns: + odb::pointer_query_columns< + ::bpkg::repository, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository, id_sqlite > > + { + }; + + // available_package + // + // available_package_count + // + struct access::view_traits_impl< ::bpkg::available_package_count, id_sqlite >::query_columns: + odb::pointer_query_columns< + ::bpkg::available_package, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::available_package, id_sqlite > > + { + }; + + // available_test + // + template <> + struct alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_test, id_sqlite >::package_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::available_test, id_sqlite >::query_columns: + odb::pointer_query_columns< + ::bpkg::available_package, + id_sqlite, + odb::alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_test, id_sqlite >::package_tag> > + { + }; + + // available_main + // + template <> + struct alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_main, id_sqlite >::package_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::available_main, id_sqlite >::query_columns: + odb::pointer_query_columns< + ::bpkg::available_package, + id_sqlite, + odb::alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::available_main, id_sqlite >::package_tag> > + { + }; + + // selected_package + // + // certificate + // + // fragment_repository + // + struct access::view_traits_impl< ::bpkg::fragment_repository, id_sqlite >::query_columns + { + // repository + // + typedef + odb::pointer_query_columns< + ::bpkg::repository, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository, id_sqlite > > + repository; + + // repository_fragment + // + typedef + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + repository_fragment; + }; + + // repository_complement_dependent + // + template <> + struct alias_traits< + ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::complement_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::query_columns + { + // complement + // + typedef + odb::pointer_query_columns< + ::bpkg::repository, + id_sqlite, + odb::alias_traits< ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_complement_dependent, id_sqlite >::complement_tag> > + complement; + + // repository_fragment + // + typedef + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + repository_fragment; + }; + + // repository_prerequisite_dependent + // + template <> + struct alias_traits< + ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::prerequisite_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::query_columns + { + // prerequisite + // + typedef + odb::pointer_query_columns< + ::bpkg::repository, + id_sqlite, + odb::alias_traits< ::bpkg::repository, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_prerequisite_dependent, id_sqlite >::prerequisite_tag> > + prerequisite; + + // repository_fragment + // + typedef + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + repository_fragment; + }; + + // repository_fragment_package + // + template <> + struct alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::package_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::query_columns + { + // repository_fragment + // + typedef + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + repository_fragment; + + // package + // + typedef + odb::pointer_query_columns< + ::bpkg::available_package, + id_sqlite, + odb::alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::repository_fragment_package, id_sqlite >::package_tag> > + package; + }; + + // package_repository_fragment + // + template <> + struct alias_traits< + ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::package_tag> + { + static const char table_name[]; + }; + + struct access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::query_columns + { + // repository_fragment + // + typedef + odb::pointer_query_columns< + ::bpkg::repository_fragment, + id_sqlite, + odb::access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite > > + repository_fragment; + + // package + // + typedef + odb::pointer_query_columns< + ::bpkg::available_package, + id_sqlite, + odb::alias_traits< ::bpkg::available_package, + id_sqlite, + access::view_traits_impl< ::bpkg::package_repository_fragment, id_sqlite >::package_tag> > + package; + }; +} + +#include <bpkg/package-odb.ixx> + +#include <odb/post.hxx> + +#endif // BPKG_PACKAGE_ODB_HXX diff --git a/bpkg/package-odb.ixx b/bpkg/package-odb.ixx new file mode 100644 index 0000000..a831734 --- /dev/null +++ b/bpkg/package-odb.ixx @@ -0,0 +1,1038 @@ +// -*- C++ -*- +// +// This file was generated by ODB, object-relational mapping (ORM) +// compiler for C++. +// + +namespace odb +{ + // configuration + // + + inline + access::object_traits< ::bpkg::configuration >::id_type + access::object_traits< ::bpkg::configuration >:: + id (const object_type& o) + { + return o.id; + } + + inline + void access::object_traits< ::bpkg::configuration >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::configuration >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_fragment + // + + inline + access::object_traits< ::bpkg::repository_fragment >::id_type + access::object_traits< ::bpkg::repository_fragment >:: + id (const object_type& o) + { + return o.name; + } + + inline + void access::object_traits< ::bpkg::repository_fragment >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::repository_fragment >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_fragment_count + // + + inline + void access::view_traits< ::bpkg::repository_fragment_count >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository + // + + inline + access::object_traits< ::bpkg::repository >::id_type + access::object_traits< ::bpkg::repository >:: + id (const object_type& o) + { + return o.name; + } + + inline + void access::object_traits< ::bpkg::repository >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::repository >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_count + // + + inline + void access::view_traits< ::bpkg::repository_count >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // available_package + // + + inline + access::object_traits< ::bpkg::available_package >::id_type + access::object_traits< ::bpkg::available_package >:: + id (const object_type& o) + { + return o.id; + } + + inline + void access::object_traits< ::bpkg::available_package >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::available_package >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // available_package_count + // + + inline + void access::view_traits< ::bpkg::available_package_count >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // available_test + // + + inline + void access::view_traits< ::bpkg::available_test >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // available_main + // + + inline + void access::view_traits< ::bpkg::available_main >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // selected_package + // + + inline + access::object_traits< ::bpkg::selected_package >::id_type + access::object_traits< ::bpkg::selected_package >:: + id (const object_type& o) + { + return o.name; + } + + inline + void access::object_traits< ::bpkg::selected_package >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::selected_package >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // certificate + // + + inline + access::object_traits< ::bpkg::certificate >::id_type + access::object_traits< ::bpkg::certificate >:: + id (const object_type& o) + { + return o.id; + } + + inline + void access::object_traits< ::bpkg::certificate >:: + callback (database& db, object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + inline + void access::object_traits< ::bpkg::certificate >:: + callback (database& db, const object_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // package_dependent + // + + inline + void access::view_traits< ::bpkg::package_dependent >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // fragment_repository_count + // + + inline + void access::view_traits< ::bpkg::fragment_repository_count >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // fragment_repository + // + + inline + void access::view_traits< ::bpkg::fragment_repository >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_complement_dependent + // + + inline + void access::view_traits< ::bpkg::repository_complement_dependent >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_prerequisite_dependent + // + + inline + void access::view_traits< ::bpkg::repository_prerequisite_dependent >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // repository_fragment_package + // + + inline + void access::view_traits< ::bpkg::repository_fragment_package >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } + + // package_repository_fragment + // + + inline + void access::view_traits< ::bpkg::package_repository_fragment >:: + callback (database& db, view_type& x, callback_event e) + { + ODB_POTENTIALLY_UNUSED (db); + ODB_POTENTIALLY_UNUSED (x); + ODB_POTENTIALLY_UNUSED (e); + } +} + +#include <odb/schema-version.hxx> + +namespace odb +{ + // _version + // + + inline + bool access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.epoch_null; + r = r && i.canonical_upstream_null; + r = r && i.canonical_release_null; + r = r && i.revision_null; + r = r && i.iteration_null; + r = r && i.upstream_null; + r = r && i.release_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::_version, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.epoch_null = true; + i.canonical_upstream_null = true; + i.canonical_release_null = true; + i.revision_null = true; + i.iteration_null = true; + i.upstream_null = true; + i.release_null = true; + } + + // language + // + + inline + bool access::composite_value_traits< ::bpkg::language, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.name_null; + r = r && i.impl_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::language, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.name_null = true; + i.impl_null = true; + } + + // version_constraint + // + + inline + bool access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && composite_value_traits< ::bpkg::_version, id_sqlite >::get_null (i.min_version_value); + r = r && composite_value_traits< ::bpkg::_version, id_sqlite >::get_null (i.max_version_value); + r = r && i.min_open_null; + r = r && i.max_open_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::version_constraint, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + composite_value_traits< ::bpkg::_version, id_sqlite >::set_null (i.min_version_value, sk); + composite_value_traits< ::bpkg::_version, id_sqlite >::set_null (i.max_version_value, sk); + i.min_open_null = true; + i.max_open_null = true; + } + + // dependency + // + + inline + bool access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.name_null; + r = r && composite_value_traits< ::bpkg::version_constraint, id_sqlite >::get_null (i.constraint_value); + return r; + } + + inline + void access::composite_value_traits< ::bpkg::dependency, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.name_null = true; + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::set_null (i.constraint_value, sk); + } + + // dependency_alternative + // + + inline + bool access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.enable_null; + r = r && i.reflect_null; + r = r && i.prefer_null; + r = r && i.accept_null; + r = r && i.require_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::dependency_alternative, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.enable_null = true; + i.reflect_null = true; + i.prefer_null = true; + i.accept_null = true; + i.require_null = true; + } + + // dependency_alternatives + // + + inline + bool access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.buildtime_null; + r = r && i.comment_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.buildtime_null = true; + i.comment_null = true; + } + + // test_dependency + // + + inline + bool access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && composite_value_traits< ::bpkg::dependency, id_sqlite >::get_null (i); + r = r && i.type_null; + r = r && i.buildtime_null; + r = r && i.enable_null; + r = r && i.reflect_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::test_dependency, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + composite_value_traits< ::bpkg::dependency, id_sqlite >::set_null (i, sk); + i.type_null = true; + i.buildtime_null = true; + i.enable_null = true; + i.reflect_null = true; + } + + // buildfile + // + + inline + bool access::composite_value_traits< ::bpkg::buildfile, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.path_null; + r = r && i.content_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::buildfile, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.path_null = true; + i.content_null = true; + } + + // distribution_name_value + // + + inline + bool access::composite_value_traits< ::bpkg::distribution_name_value, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.name_null; + r = r && i.value_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::distribution_name_value, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.name_null = true; + i.value_null = true; + } + + // configuration + // + + inline + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + inline + void access::object_traits_impl< ::bpkg::configuration, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool) + { + ODB_POTENTIALLY_UNUSED (sts); + ODB_POTENTIALLY_UNUSED (obj); + } + + // canonical_version + // + + inline + bool access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.epoch_null; + r = r && i.canonical_upstream_null; + r = r && i.canonical_release_null; + r = r && i.revision_null; + r = r && i.iteration_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::canonical_version, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.epoch_null = true; + i.canonical_upstream_null = true; + i.canonical_release_null = true; + i.revision_null = true; + i.iteration_null = true; + } + + // upstream_version + // + + inline + bool access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.upstream_null; + r = r && i.release_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::upstream_version, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.upstream_null = true; + i.release_null = true; + } + + // _repository_location + // + + inline + bool access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.url_null; + r = r && i.type_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::_repository_location, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.url_null = true; + i.type_null = true; + } + + // repository_fragment + // + + inline + void access::object_traits_impl< ::bpkg::repository_fragment, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + // repository_fragment_count + // + + // fragment_type + // + + inline + bool access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.friendly_name_null; + r = r && i.fragment_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::repository::fragment_type, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.friendly_name_null = true; + i.fragment_null = true; + } + + // repository + // + + inline + void access::object_traits_impl< ::bpkg::repository, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + // repository_count + // + + // package_location + // + + inline + bool access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.repository_fragment_null; + r = r && i.location_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::package_location, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.repository_fragment_null = true; + i.location_null = true; + } + + // dependency_alternatives_ex + // + + inline + bool access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::get_null (i); + r = r && i.type_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::dependency_alternatives_ex, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + composite_value_traits< ::bpkg::dependency_alternatives, id_sqlite >::set_null (i, sk); + i.type_null = true; + } + + // available_package_id + // + + inline + bool access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.name_null; + r = r && composite_value_traits< ::bpkg::canonical_version, id_sqlite >::get_null (i.version_value); + return r; + } + + inline + void access::composite_value_traits< ::bpkg::available_package_id, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.name_null = true; + composite_value_traits< ::bpkg::canonical_version, id_sqlite >::set_null (i.version_value, sk); + } + + // _dependency_alternative_key + // + + inline + bool access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.outer_null; + r = r && i.inner_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::available_package::_dependency_alternative_key, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.outer_null = true; + i.inner_null = true; + } + + // _dependency_key + // + + inline + bool access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.outer_null; + r = r && i.middle_null; + r = r && i.inner_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::available_package::_dependency_key, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.outer_null = true; + i.middle_null = true; + i.inner_null = true; + } + + // available_package + // + + inline + void access::object_traits_impl< ::bpkg::available_package, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + // available_package_count + // + + // available_test + // + + // available_main + // + + // prerequisite_info + // + + inline + bool access::composite_value_traits< ::bpkg::prerequisite_info, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && composite_value_traits< ::bpkg::version_constraint, id_sqlite >::get_null (i.constraint_value); + return r; + } + + inline + void access::composite_value_traits< ::bpkg::prerequisite_info, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + composite_value_traits< ::bpkg::version_constraint, id_sqlite >::set_null (i.constraint_value, sk); + } + + // _selected_package_ref + // + + inline + bool access::composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.configuration_null; + r = r && i.prerequisite_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::_selected_package_ref, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.configuration_null = true; + i.prerequisite_null = true; + } + + // config_variable + // + + inline + bool access::composite_value_traits< ::bpkg::config_variable, id_sqlite >:: + get_null (const image_type& i) + { + bool r (true); + r = r && i.name_null; + r = r && i.source_null; + return r; + } + + inline + void access::composite_value_traits< ::bpkg::config_variable, id_sqlite >:: + set_null (image_type& i, + sqlite::statement_kind sk) + { + ODB_POTENTIALLY_UNUSED (sk); + + using namespace sqlite; + + i.name_null = true; + i.source_null = true; + } + + // selected_package + // + + inline + void access::object_traits_impl< ::bpkg::selected_package, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + // certificate + // + + inline + void access::object_traits_impl< ::bpkg::certificate, id_sqlite >:: + erase (database& db, const object_type& obj) + { + callback (db, obj, callback_event::pre_erase); + erase (db, id (obj)); + callback (db, obj, callback_event::post_erase); + } + + inline + void access::object_traits_impl< ::bpkg::certificate, id_sqlite >:: + load_ (statements_type& sts, + object_type& obj, + bool) + { + ODB_POTENTIALLY_UNUSED (sts); + ODB_POTENTIALLY_UNUSED (obj); + } + + // package_dependent + // + + // fragment_repository_count + // + + // fragment_repository + // + + // repository_complement_dependent + // + + // repository_prerequisite_dependent + // + + // repository_fragment_package + // + + // package_repository_fragment + // +} + diff --git a/bpkg/pkg-bindist-options.cxx b/bpkg/pkg-bindist-options.cxx new file mode 100644 index 0000000..cceb8b7 --- /dev/null +++ b/bpkg/pkg-bindist-options.cxx @@ -0,0 +1,3081 @@ +// -*- 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/pkg-bindist-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_bindist_common_options + // + + pkg_bindist_common_options:: + pkg_bindist_common_options () + : distribution_ (), + distribution_specified_ (false), + architecture_ (), + architecture_specified_ (false), + recursive_ ("none"), + recursive_specified_ (false), + private__ (), + output_root_ (), + output_root_specified_ (false), + wipe_output_ (), + keep_output_ (), + allow_dependent_config_ (), + os_release_id_ (), + os_release_id_specified_ (false), + os_release_version_id_ (), + os_release_version_id_specified_ (false), + os_release_name_ (), + os_release_name_specified_ (false) + { + } + + bool pkg_bindist_common_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 pkg_bindist_common_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 pkg_bindist_common_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 pkg_bindist_common_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 pkg_bindist_common_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 pkg_bindist_common_options:: + merge (const pkg_bindist_common_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.distribution_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->distribution_, a.distribution_); + this->distribution_specified_ = true; + } + + if (a.architecture_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->architecture_, a.architecture_); + this->architecture_specified_ = true; + } + + if (a.recursive_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->recursive_, a.recursive_); + this->recursive_specified_ = true; + } + + if (a.private__) + { + ::bpkg::cli::parser< bool>::merge ( + this->private__, a.private__); + } + + if (a.output_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->output_root_, a.output_root_); + this->output_root_specified_ = true; + } + + if (a.wipe_output_) + { + ::bpkg::cli::parser< bool>::merge ( + this->wipe_output_, a.wipe_output_); + } + + if (a.keep_output_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_output_, a.keep_output_); + } + + if (a.allow_dependent_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->allow_dependent_config_, a.allow_dependent_config_); + } + + if (a.os_release_id_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_id_, a.os_release_id_); + this->os_release_id_specified_ = true; + } + + if (a.os_release_version_id_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_version_id_, a.os_release_version_id_); + this->os_release_version_id_specified_ = true; + } + + if (a.os_release_name_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->os_release_name_, a.os_release_name_); + this->os_release_name_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_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[1mPKG-BINDIST OPTIONS\033[0m" << ::std::endl + << ::std::endl + << "See the following sections below for distribution-specific options:" << ::std::endl + << ::std::endl + << "PKG-BINDIST DEBIAN OPTIONS" << ::std::endl + << ::std::endl + << "PKG-BINDIST FEDORA OPTIONS" << ::std::endl + << ::std::endl + << "PKG-BINDIST ARCHIVE OPTIONS" << ::std::endl; + + os << std::endl + << "\033[1m--distribution\033[0m \033[4mname\033[0m Alternative system/distribution package manager to" << ::std::endl + << " generate the binary package for. The valid \033[4mname\033[0m" << ::std::endl + << " values are \033[1mdebian\033[0m (Debian and alike, such as Ubuntu," << ::std::endl + << " etc), \033[1mfedora\033[0m (Fedora and alike, such as RHEL, CentOS," << ::std::endl + << " etc), and \033[1marchive\033[0m (installation archive on any" << ::std::endl + << " operating system). Note that some package managers" << ::std::endl + << " may only be supported when running on certain host" << ::std::endl + << " operating systems." << ::std::endl; + + os << std::endl + << "\033[1m--architecture\033[0m \033[4mname\033[0m Alternative architecture to generate the binary" << ::std::endl + << " package for. The valid \033[4mname\033[0m values are" << ::std::endl + << " system/distribution package manager-specific. If" << ::std::endl + << " unspecified, the host architecture is used." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m \033[4mmode\033[0m Bundle or generate dependencies of the specified" << ::std::endl + << " packages. The \033[4mmode\033[0m value can be either \033[1mauto\033[0m, in which" << ::std::endl + << " case only the required files from each dependency" << ::std::endl + << " package are bundled, \033[1mfull\033[0m, in which case all the" << ::std::endl + << " files are bundled, or \033[1mseparate\033[0m, in which case a" << ::std::endl + << " separate binary package is generated for each" << ::std::endl + << " non-system dependency. It can also be \033[1mnone\033[0m which is" << ::std::endl + << " equivalent to not specifying this option (primarily" << ::std::endl + << " useful for overriding a previously-specified value)." << ::std::endl + << ::std::endl + << " Specifically, in the \033[1mauto\033[0m mode any required files," << ::std::endl + << " such as shared libraries, are pulled implicitly by" << ::std::endl + << " the \033[1minstall\033[0m build system operation, for example, as" << ::std::endl + << " part of installing an executable from one of the" << ::std::endl + << " specified packages. In contrast, in the \033[1mfull\033[0m mode," << ::std::endl + << " each dependency package is installed explicitly and" << ::std::endl + << " completely, as if they were specified as additional" << ::std::endl + << " package on the command line. The \033[1mseparate\033[0m mode is" << ::std::endl + << " equivalent to invoking the \033[1mpkg-bindist\033[0m command on" << ::std::endl + << " each dependency package. See also the \033[1m--private\033[0m" << ::std::endl + << " option." << ::std::endl; + + os << std::endl + << "\033[1m--private\033[0m Enable the private installation subdirectory" << ::std::endl + << " functionality using the package name as the private" << ::std::endl + << " subdirectory. This is primarily useful when bundling" << ::std::endl + << " dependencies, such as shared libraries, of an" << ::std::endl + << " executable that is being installed into a shared" << ::std::endl + << " location, such as \033[1m/usr/\033[0m. See the" << ::std::endl + << " \033[1mconfig.install.private\033[0m configuration variable" << ::std::endl + << " documentation in the build system manual for details." << ::std::endl + << " This option only makes sense together with the" << ::std::endl + << " \033[1m--recursive\033[0m option \033[1mauto\033[0m and \033[1mfull\033[0m modes." << ::std::endl; + + os << std::endl + << "\033[1m--output-root\033[0m|\033[1m-o\033[0m \033[4mdir\033[0m Directory for intermediate files and subdirectories" << ::std::endl + << " as well as the resulting binary package. Note that" << ::std::endl + << " this option may be required for some system package" << ::std::endl + << " managers and may not be specified for others." << ::std::endl; + + os << std::endl + << "\033[1m--wipe-output\033[0m Wipe the output root directory (either specified with" << ::std::endl + << " \033[4m--output-root\033[0m or system package manager-specific)" << ::std::endl + << " clean before using it to generate the binary package." << ::std::endl; + + os << std::endl + << "\033[1m--keep-output\033[0m Keep intermediate files in the output root directory" << ::std::endl + << " (either specified with \033[4m--output-root\033[0m or system" << ::std::endl + << " package manager-specific) that were used to generate" << ::std::endl + << " the binary package. This is primarily useful for" << ::std::endl + << " troubleshooting." << ::std::endl; + + os << std::endl + << "\033[1m--allow-dependent-config\033[0m Allow configuration that is imposed by dependent" << ::std::endl + << " packages. Normally this is undesirable because the" << ::std::endl + << " resulting binary packages become configured" << ::std::endl + << " specificaly for particular dependent packages." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-id\033[0m \033[4mv\033[0m Override the \033[1mID\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent. Note that unlike the rest of the" << ::std::endl + << " \033[1m--os-release-*\033[0m options, this option suppresses" << ::std::endl + << " automatic detection of the host operating system" << ::std::endl + << " information." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-version-id\033[0m \033[4mv\033[0m Override the \033[1mVERSION_ID\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent." << ::std::endl; + + os << std::endl + << "\033[1m--os-release-name\033[0m \033[4mv\033[0m Override the \033[1mNAME\033[0m component in \033[1mos-release(5)\033[0m or" << ::std::endl + << " equivalent." << ::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 (*) (pkg_bindist_common_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_common_options_map; + + static _cli_pkg_bindist_common_options_map _cli_pkg_bindist_common_options_map_; + + struct _cli_pkg_bindist_common_options_map_init + { + _cli_pkg_bindist_common_options_map_init () + { + _cli_pkg_bindist_common_options_map_["--distribution"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::distribution_, + &pkg_bindist_common_options::distribution_specified_ >; + _cli_pkg_bindist_common_options_map_["--architecture"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::architecture_, + &pkg_bindist_common_options::architecture_specified_ >; + _cli_pkg_bindist_common_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::recursive_, + &pkg_bindist_common_options::recursive_specified_ >; + _cli_pkg_bindist_common_options_map_["--private"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::private__ >; + _cli_pkg_bindist_common_options_map_["--output-root"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, dir_path, &pkg_bindist_common_options::output_root_, + &pkg_bindist_common_options::output_root_specified_ >; + _cli_pkg_bindist_common_options_map_["-o"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, dir_path, &pkg_bindist_common_options::output_root_, + &pkg_bindist_common_options::output_root_specified_ >; + _cli_pkg_bindist_common_options_map_["--wipe-output"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::wipe_output_ >; + _cli_pkg_bindist_common_options_map_["--keep-output"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::keep_output_ >; + _cli_pkg_bindist_common_options_map_["--allow-dependent-config"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, &pkg_bindist_common_options::allow_dependent_config_ >; + _cli_pkg_bindist_common_options_map_["--os-release-id"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_id_, + &pkg_bindist_common_options::os_release_id_specified_ >; + _cli_pkg_bindist_common_options_map_["--os-release-version-id"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_version_id_, + &pkg_bindist_common_options::os_release_version_id_specified_ >; + _cli_pkg_bindist_common_options_map_["--os-release-name"] = + &::bpkg::cli::thunk< pkg_bindist_common_options, string, &pkg_bindist_common_options::os_release_name_, + &pkg_bindist_common_options::os_release_name_specified_ >; + } + }; + + static _cli_pkg_bindist_common_options_map_init _cli_pkg_bindist_common_options_map_init_; + + bool pkg_bindist_common_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_common_options_map::const_iterator i (_cli_pkg_bindist_common_options_map_.find (o)); + + if (i != _cli_pkg_bindist_common_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_bindist_common_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; + } + + // pkg_bindist_debian_options + // + + pkg_bindist_debian_options:: + pkg_bindist_debian_options () + : debian_prepare_only_ (), + debian_buildflags_ ("assign"), + debian_buildflags_specified_ (false), + debian_maint_option_ (), + debian_maint_option_specified_ (false), + debian_build_option_ (), + debian_build_option_specified_ (false), + debian_build_meta_ (), + debian_build_meta_specified_ (false), + debian_section_ (), + debian_section_specified_ (false), + debian_priority_ (), + debian_priority_specified_ (false), + debian_maintainer_ (), + debian_maintainer_specified_ (false), + debian_architecture_ (), + debian_architecture_specified_ (false), + debian_main_langdep_ (), + debian_main_langdep_specified_ (false), + debian_dev_langdep_ (), + debian_dev_langdep_specified_ (false), + debian_main_extradep_ (), + debian_main_extradep_specified_ (false), + debian_dev_extradep_ (), + debian_dev_extradep_specified_ (false) + { + } + + bool pkg_bindist_debian_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 pkg_bindist_debian_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 pkg_bindist_debian_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 pkg_bindist_debian_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 pkg_bindist_debian_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 pkg_bindist_debian_options:: + merge (const pkg_bindist_debian_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.debian_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->debian_prepare_only_, a.debian_prepare_only_); + } + + if (a.debian_buildflags_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_buildflags_, a.debian_buildflags_); + this->debian_buildflags_specified_ = true; + } + + if (a.debian_maint_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->debian_maint_option_, a.debian_maint_option_); + this->debian_maint_option_specified_ = true; + } + + if (a.debian_build_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->debian_build_option_, a.debian_build_option_); + this->debian_build_option_specified_ = true; + } + + if (a.debian_build_meta_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_build_meta_, a.debian_build_meta_); + this->debian_build_meta_specified_ = true; + } + + if (a.debian_section_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_section_, a.debian_section_); + this->debian_section_specified_ = true; + } + + if (a.debian_priority_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_priority_, a.debian_priority_); + this->debian_priority_specified_ = true; + } + + if (a.debian_maintainer_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_maintainer_, a.debian_maintainer_); + this->debian_maintainer_specified_ = true; + } + + if (a.debian_architecture_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_architecture_, a.debian_architecture_); + this->debian_architecture_specified_ = true; + } + + if (a.debian_main_langdep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_main_langdep_, a.debian_main_langdep_); + this->debian_main_langdep_specified_ = true; + } + + if (a.debian_dev_langdep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_dev_langdep_, a.debian_dev_langdep_); + this->debian_dev_langdep_specified_ = true; + } + + if (a.debian_main_extradep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_main_extradep_, a.debian_main_extradep_); + this->debian_main_extradep_specified_ = true; + } + + if (a.debian_dev_extradep_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->debian_dev_extradep_, a.debian_dev_extradep_); + this->debian_dev_extradep_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_debian_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[1mDEBIAN DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The Debian binary packages are generated by producing the standard" << ::std::endl + << "\033[1mdebian/control\033[0m, \033[1mdebian/rules\033[0m, and other package metadata files and then" << ::std::endl + << "invoking \033[1mdpkg-buildpackage(1)\033[0m to build the binary package from that. In" << ::std::endl + << "particular, the \033[1mdebian/rules\033[0m implemenation is based on the \033[1mdh(1)\033[0m command" << ::std::endl + << "sequencer. While this approach is normally used to build packages from source," << ::std::endl + << "this implementation \"pretends\" that this is what's happening by overriding a" << ::std::endl + << "number of \033[1mdh\033[0m targets to invoke the \033[1mbuild2\033[0m build system on the required packages" << ::std::endl + << "directly in their \033[1mbpkg\033[0m configuration locations." << ::std::endl + << ::std::endl + << "The \033[1mdpkg-dev\033[0m (or \033[1mbuild-essential\033[0m) and \033[1mdebhelper\033[0m Debian packages must be" << ::std::endl + << "installed before invocation. Typical invocation:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist -o /tmp/output/ libhello" << ::std::endl + << ::std::endl + << "Unless the \033[1m--recursive\033[0m option \033[1mauto\033[0m or \033[1mfull\033[0m modes are specified, dependencies of" << ::std::endl + << "the specified package are translated to dependencies in the resulting binary" << ::std::endl + << "package using names and versions that refer to packages that would be generated" << ::std::endl + << "by the \033[1mpkg-bindist\033[0m command (called \"non-native\" packages). If instead you would" << ::std::endl + << "like certain dependencies to refer to binary packages provided by the" << ::std::endl + << "distribution (called \"native\" packages), then you need to arrange for them to" << ::std::endl + << "be built as system (see \033[1mbpkg-pkg-build(1)\033[0m for details). For example, if our" << ::std::endl + << "\033[1mlibhello\033[0m has a dependency on \033[1mlibsqlite3\033[0m and we would like the binary package" << ::std::endl + << "for \033[1mlibhello\033[0m to refer to \033[1mlibsqlite3\033[0m from Debian (or alike), then the \033[1mpkg-build\033[0m" << ::std::endl + << "command would need to be (\033[1m--sys-install\033[0m is optional):" << ::std::endl + << ::std::endl + << "bpkg build --sys-install libhello ?sys:libsqlite3" << ::std::endl + << ::std::endl + << "Such a package with native dependencies can then be installed (including any" << ::std::endl + << "missing native dependencies) using the \033[1mapt\033[0m or \033[1mapt-get\033[0m \033[1minstall\033[0m command. Note" << ::std::endl + << "that the specified \033[1m.deb\033[0m file must include a directory separator (/\033[0m) in order to" << ::std::endl + << "be recognized as a file rather than a package name. For example:" << ::std::endl + << ::std::endl + << "sudo apt-get install ./libhello_1.2.3-0~debian11_amd64.deb \\" << ::std::endl + << " ./libhello-dev_1.2.3-0~debian11_amd64.deb" << ::std::endl + << ::std::endl + << "See Debian Package Mapping for Production (bpkg#bindist-mapping-debian-produce)" << ::std::endl + << "for details on \033[1mbpkg\033[0m to Debian package name and version mapping." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST DEBIAN OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--debian-prepare-only\033[0m Prepare all the package metadata files (\033[1mcontrol\033[0m," << ::std::endl + << " \033[1mrules\033[0m, etc) but do not invoke \033[1mdpkg-buildpackage\033[0m to" << ::std::endl + << " generate the binary package, printing its command" << ::std::endl + << " line instead unless requested to be quiet. Implies" << ::std::endl + << " \033[1m--keep-output\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-buildflags\033[0m \033[4mmode\033[0m Package build flags (\033[1mdpkg-buildflags\033[0m) usage mode." << ::std::endl + << " Valid \033[4mmode\033[0m values are \033[1massign\033[0m (use the build flags" << ::std::endl + << " instead of configured), \033[1mappend\033[0m (use the build flags" << ::std::endl + << " in addition to configured, putting them last)," << ::std::endl + << " \033[1mprepend\033[0m (use the build flags in addition to" << ::std::endl + << " configured, putting them first), and \033[1mignore\033[0m (ignore" << ::std::endl + << " build flags). The default mode is \033[1massign\033[0m. Note that" << ::std::endl + << " compiler mode options, if any, are used as" << ::std::endl + << " configured." << ::std::endl; + + os << std::endl + << "\033[1m--debian-maint-option\033[0m \033[4mo\033[0m Alternative options to specify in the" << ::std::endl + << " \033[1mDEB_BUILD_MAINT_OPTIONS\033[0m variable of the \033[1mrules\033[0m file." << ::std::endl + << " To specify multiple maintainer options repeat this" << ::std::endl + << " option and/or specify them as a single value" << ::std::endl + << " separated with spaces." << ::std::endl; + + os << std::endl + << "\033[1m--debian-build-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mdpkg-buildpackage\033[0m" << ::std::endl + << " program. Repeat this option to specify multiple build" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--debian-build-meta\033[0m \033[4mdata\033[0m Alternative or additional build metadata to include" << ::std::endl + << " in the binary package version. If the specified value" << ::std::endl + << " starts/ends with \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is" << ::std::endl + << " added after/before the default metadata. Otherwise it" << ::std::endl + << " is used as is instead of the default metadata. If" << ::std::endl + << " empty value is specified, then no build metadata is" << ::std::endl + << " included. By default, the build metadata is the \033[1mID\033[0m" << ::std::endl + << " and \033[1mVERSION_ID\033[0m components from \033[1mos-release(5)\033[0m, for" << ::std::endl + << " example, \033[1mdebian10\033[0m in version \033[1m1.2.3-0~debian10\033[0m. See" << ::std::endl + << " also \033[1m--os-release-*\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-section\033[0m \033[4mv\033[0m Alternative \033[1mSection\033[0m \033[1mcontrol\033[0m file field value for the" << ::std::endl + << " main binary package. The default is either \033[1mlibs\033[0m or" << ::std::endl + << " \033[1mdevel\033[0m, depending on the package type." << ::std::endl; + + os << std::endl + << "\033[1m--debian-priority\033[0m \033[4mv\033[0m Alternative \033[1mPriority\033[0m \033[1mcontrol\033[0m file field value. The" << ::std::endl + << " default is \033[1moptional\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-maintainer\033[0m \033[4mv\033[0m Alternative \033[1mMaintainer\033[0m \033[1mcontrol\033[0m file field value. The" << ::std::endl + << " default is the \033[1mpackage-email\033[0m value from package" << ::std::endl + << " \033[1mmanifest\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--debian-architecture\033[0m \033[4mv\033[0m Alternative \033[1mArchitecture\033[0m \033[1mcontrol\033[0m file field value for" << ::std::endl + << " the main binary package, normally \033[1mall\033[0m" << ::std::endl + << " (architecture-independent). The default is \033[1many\033[0m" << ::std::endl + << " (architecture-dependent)." << ::std::endl; + + os << std::endl + << "\033[1m--debian-main-langdep\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mlibc6\033[0m, \033[1mlibstdc++6\033[0m, etc) in the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the main binary package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-dev-langdep\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mlibc-dev\033[0m, \033[1mlibstdc++-dev\033[0m, etc) in the \033[1mDepends\033[0m \033[1mcontrol\033[0m" << ::std::endl + << " file field value of the development (\033[1m-dev\033[0m) binary" << ::std::endl + << " package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-main-extradep\033[0m \033[4mv\033[0m Extra dependencies to add to the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the main binary package." << ::std::endl; + + os << std::endl + << "\033[1m--debian-dev-extradep\033[0m \033[4mv\033[0m Extra dependencies to add to the \033[1mDepends\033[0m \033[1mcontrol\033[0m file" << ::std::endl + << " field value of the development (\033[1m-dev\033[0m) binary package." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_debian_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_debian_options_map; + + static _cli_pkg_bindist_debian_options_map _cli_pkg_bindist_debian_options_map_; + + struct _cli_pkg_bindist_debian_options_map_init + { + _cli_pkg_bindist_debian_options_map_init () + { + _cli_pkg_bindist_debian_options_map_["--debian-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, &pkg_bindist_debian_options::debian_prepare_only_ >; + _cli_pkg_bindist_debian_options_map_["--debian-buildflags"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_buildflags_, + &pkg_bindist_debian_options::debian_buildflags_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-maint-option"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, strings, &pkg_bindist_debian_options::debian_maint_option_, + &pkg_bindist_debian_options::debian_maint_option_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-build-option"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, strings, &pkg_bindist_debian_options::debian_build_option_, + &pkg_bindist_debian_options::debian_build_option_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-build-meta"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_build_meta_, + &pkg_bindist_debian_options::debian_build_meta_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-section"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_section_, + &pkg_bindist_debian_options::debian_section_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-priority"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_priority_, + &pkg_bindist_debian_options::debian_priority_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-maintainer"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_maintainer_, + &pkg_bindist_debian_options::debian_maintainer_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-architecture"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_architecture_, + &pkg_bindist_debian_options::debian_architecture_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-main-langdep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_main_langdep_, + &pkg_bindist_debian_options::debian_main_langdep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-dev-langdep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_dev_langdep_, + &pkg_bindist_debian_options::debian_dev_langdep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-main-extradep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_main_extradep_, + &pkg_bindist_debian_options::debian_main_extradep_specified_ >; + _cli_pkg_bindist_debian_options_map_["--debian-dev-extradep"] = + &::bpkg::cli::thunk< pkg_bindist_debian_options, string, &pkg_bindist_debian_options::debian_dev_extradep_, + &pkg_bindist_debian_options::debian_dev_extradep_specified_ >; + } + }; + + static _cli_pkg_bindist_debian_options_map_init _cli_pkg_bindist_debian_options_map_init_; + + bool pkg_bindist_debian_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_debian_options_map::const_iterator i (_cli_pkg_bindist_debian_options_map_.find (o)); + + if (i != _cli_pkg_bindist_debian_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_debian_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; + } + + // pkg_bindist_fedora_options + // + + pkg_bindist_fedora_options:: + pkg_bindist_fedora_options () + : fedora_prepare_only_ (), + fedora_buildflags_ ("assign"), + fedora_buildflags_specified_ (false), + fedora_build_option_ (), + fedora_build_option_specified_ (false), + fedora_query_option_ (), + fedora_query_option_specified_ (false), + fedora_dist_tag_ (), + fedora_dist_tag_specified_ (false), + fedora_packager_ (), + fedora_packager_specified_ (false), + fedora_build_arch_ (), + fedora_build_arch_specified_ (false), + fedora_main_langreq_ (), + fedora_main_langreq_specified_ (false), + fedora_devel_langreq_ (), + fedora_devel_langreq_specified_ (false), + fedora_stat_langreq_ (), + fedora_stat_langreq_specified_ (false), + fedora_main_extrareq_ (), + fedora_main_extrareq_specified_ (false), + fedora_devel_extrareq_ (), + fedora_devel_extrareq_specified_ (false), + fedora_stat_extrareq_ (), + fedora_stat_extrareq_specified_ (false) + { + } + + bool pkg_bindist_fedora_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 pkg_bindist_fedora_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 pkg_bindist_fedora_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 pkg_bindist_fedora_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 pkg_bindist_fedora_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 pkg_bindist_fedora_options:: + merge (const pkg_bindist_fedora_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.fedora_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->fedora_prepare_only_, a.fedora_prepare_only_); + } + + if (a.fedora_buildflags_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_buildflags_, a.fedora_buildflags_); + this->fedora_buildflags_specified_ = true; + } + + if (a.fedora_build_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_build_option_, a.fedora_build_option_); + this->fedora_build_option_specified_ = true; + } + + if (a.fedora_query_option_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_query_option_, a.fedora_query_option_); + this->fedora_query_option_specified_ = true; + } + + if (a.fedora_dist_tag_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_dist_tag_, a.fedora_dist_tag_); + this->fedora_dist_tag_specified_ = true; + } + + if (a.fedora_packager_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_packager_, a.fedora_packager_); + this->fedora_packager_specified_ = true; + } + + if (a.fedora_build_arch_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->fedora_build_arch_, a.fedora_build_arch_); + this->fedora_build_arch_specified_ = true; + } + + if (a.fedora_main_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_main_langreq_, a.fedora_main_langreq_); + this->fedora_main_langreq_specified_ = true; + } + + if (a.fedora_devel_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_devel_langreq_, a.fedora_devel_langreq_); + this->fedora_devel_langreq_specified_ = true; + } + + if (a.fedora_stat_langreq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_stat_langreq_, a.fedora_stat_langreq_); + this->fedora_stat_langreq_specified_ = true; + } + + if (a.fedora_main_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_main_extrareq_, a.fedora_main_extrareq_); + this->fedora_main_extrareq_specified_ = true; + } + + if (a.fedora_devel_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_devel_extrareq_, a.fedora_devel_extrareq_); + this->fedora_devel_extrareq_specified_ = true; + } + + if (a.fedora_stat_extrareq_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->fedora_stat_extrareq_, a.fedora_stat_extrareq_); + this->fedora_stat_extrareq_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_fedora_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[1mFEDORA DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The Fedora binary packages are generated by producing the standard RPM spec" << ::std::endl + << "file and then invoking \033[1mrpmbuild(8)\033[0m to build the binary package from that. While" << ::std::endl + << "this approach is normally used to build packages from source, this" << ::std::endl + << "implementation \"pretends\" that this is what's happening by overriding a number" << ::std::endl + << "of RPM spec file sections to invoke the \033[1mbuild2\033[0m build system on the required" << ::std::endl + << "packages directly in their \033[1mbpkg\033[0m configuration locations." << ::std::endl + << ::std::endl + << "The \033[1mrpmdevtools\033[0m Fedora package must be installed before invocation. Typical" << ::std::endl + << "invocation:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist libhello" << ::std::endl + << ::std::endl + << "The resulting binary packages are placed into the standard \033[1mrpmbuild\033[0m output" << ::std::endl + << "directory (normally \033[1m~/rpmbuild/RPMS/\033[0m\033[4march\033[0m\033[1m/\033[0m\033[0m)." << ::std::endl + << ::std::endl + << "Unless the \033[1m--recursive\033[0m option \033[1mauto\033[0m or \033[1mfull\033[0m modes are specified, dependencies of" << ::std::endl + << "the specified package are translated to dependencies in the resulting binary" << ::std::endl + << "package using names and versions that refer to packages that would be generated" << ::std::endl + << "by the \033[1mpkg-bindist\033[0m command (called \"non-native\" packages). If instead you would" << ::std::endl + << "like certain dependencies to refer to binary packages provided by the" << ::std::endl + << "distribution (called \"native\" packages), then you need to arrange for them to" << ::std::endl + << "be built as system (see \033[1mbpkg-pkg-build(1)\033[0m for details). For example, if our" << ::std::endl + << "\033[1mlibhello\033[0m has a dependency on \033[1mlibsqlite3\033[0m and we would like the binary package" << ::std::endl + << "for \033[1mlibhello\033[0m to refer to \033[1msqlite-libs\033[0m from Fedora (or alike), then the" << ::std::endl + << "\033[1mpkg-build\033[0m command would need to be (\033[1m--sys-install\033[0m is optional):" << ::std::endl + << ::std::endl + << "bpkg build --sys-install libhello ?sys:libsqlite3" << ::std::endl + << ::std::endl + << "Such a package with native dependencies can then be installed (including any" << ::std::endl + << "missing native dependencies) using the \033[1mdnf install\033[0m command. For example:" << ::std::endl + << ::std::endl + << "sudo dnf install libhello-1.2.3-1.fc35.x86_64.rpm \\" << ::std::endl + << " libhello-devel-1.2.3-1.fc35.x86_64.rpm" << ::std::endl + << ::std::endl + << "See Fedora Package Mapping for Production (bpkg#bindist-mapping-fedora-produce)" << ::std::endl + << "for details on \033[1mbpkg\033[0m to Fedora package name and version mapping." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST FEDORA OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--fedora-prepare-only\033[0m Prepare the RPM spec file but do not invoke \033[1mrpmbuild\033[0m" << ::std::endl + << " to generate the binary package, printing its command" << ::std::endl + << " line instead unless requested to be quiet." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-buildflags\033[0m \033[4mmode\033[0m Package build flags (\033[1m%{build_*flags}\033[0m macros) usage" << ::std::endl + << " mode. Valid \033[4mmode\033[0m values are \033[1massign\033[0m (use the build" << ::std::endl + << " flags instead of configured), \033[1mappend\033[0m (use the build" << ::std::endl + << " flags in addition to configured, putting them last)," << ::std::endl + << " \033[1mprepend\033[0m (use the build flags in addition to" << ::std::endl + << " configured, putting them first), and \033[1mignore\033[0m (ignore" << ::std::endl + << " build flags). The default mode is \033[1massign\033[0m. Note that" << ::std::endl + << " compiler mode options, if any, are used as" << ::std::endl + << " configured." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-build-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mrpmbuild\033[0m program. If" << ::std::endl + << " specified, these options must be consistent with the" << ::std::endl + << " query options (\033[1m--fedora-query-option\033[0m) to result in" << ::std::endl + << " identical macro expansions. Repeat this option to" << ::std::endl + << " specify multiple build options." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-query-option\033[0m \033[4mo\033[0m Additional option to pass to the \033[1mrpm\033[0m program. This" << ::std::endl + << " program is used to query RPM macro values which" << ::std::endl + << " affect the binary package. If specified, these" << ::std::endl + << " options must be consistent with the build options" << ::std::endl + << " (\033[1m--fedora-build-option\033[0m) to result in identical macro" << ::std::endl + << " expansions. Repeat this option to specify multiple" << ::std::endl + << " query options." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-dist-tag\033[0m \033[4mtag\033[0m Alternative or additional distribution tag to use in" << ::std::endl + << " the binary package release. If the specified value" << ::std::endl + << " starts/ends with \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is" << ::std::endl + << " added after/before the default distribution tag." << ::std::endl + << " Otherwise it is used as is instead of the default" << ::std::endl + << " tag. If empty value is specified, then no" << ::std::endl + << " distribution tag is included. The default is a value" << ::std::endl + << " that identifies the distribution being used to build" << ::std::endl + << " the package, for example, \033[1mfc35\033[0m for Fedora 35 or \033[1mel8\033[0m" << ::std::endl + << " for RHEL 8." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-packager\033[0m \033[4mv\033[0m Alternative \033[1mPackager\033[0m RPM spec file directive value." << ::std::endl + << " The default is the \033[1mpackage-email\033[0m value from package" << ::std::endl + << " \033[1mmanifest\033[0m. If empty value is specified, then the" << ::std::endl + << " \033[1mPackager\033[0m directive is omitted from the spec file." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-build-arch\033[0m \033[4mv\033[0m \033[1mBuildArch\033[0m RPM spec file directive value for the main" << ::std::endl + << " binary package, normally \033[1mnoarch\033[0m" << ::std::endl + << " (architecture-independent). By default the directive" << ::std::endl + << " is omitted, assuming that the package is" << ::std::endl + << " architecture-dependent." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-main-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc\033[0m, \033[1mlibstdc++\033[0m, etc) of the main binary package by" << ::std::endl + << " replacing the corresponding \033[1mRequires\033[0m RPM spec file" << ::std::endl + << " directives. If empty value is specified then no" << ::std::endl + << " language runtime dependencies are specified. Repeat" << ::std::endl + << " this option to specify multiple language runtime" << ::std::endl + << " dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-devel-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc-devel\033[0m, \033[1mlibstdc++-devel\033[0m, etc) of the development" << ::std::endl + << " (\033[1m-devel\033[0m) binary package by replacing the" << ::std::endl + << " corresponding \033[1mRequires\033[0m RPM spec file directives. If" << ::std::endl + << " empty value is specified then no language runtime" << ::std::endl + << " dependencies are specified. Repeat this option to" << ::std::endl + << " specify multiple language runtime dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-stat-langreq\033[0m \033[4mv\033[0m Override the language runtime dependencies (such as" << ::std::endl + << " \033[1mglibc-static\033[0m, \033[1mlibstdc++-static\033[0m, etc) of the static" << ::std::endl + << " libraries (\033[1m-static\033[0m) binary package by replacing the" << ::std::endl + << " corresponding \033[1mRequires\033[0m RPM spec file directives. If" << ::std::endl + << " empty value is specified then no language runtime" << ::std::endl + << " dependencies are specified. Repeat this option to" << ::std::endl + << " specify multiple language runtime dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-main-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the main binary package as" << ::std::endl + << " an additional \033[1mRequires\033[0m RPM spec file directive." << ::std::endl + << " Repeat this option to specify multiple extra" << ::std::endl + << " dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-devel-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the development (\033[1m-devel\033[0m)" << ::std::endl + << " binary package as an additional \033[1mRequires\033[0m RPM spec" << ::std::endl + << " file directive. Repeat this option to specify" << ::std::endl + << " multiple extra dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--fedora-stat-extrareq\033[0m \033[4mv\033[0m Extra dependency to add to the static libraries" << ::std::endl + << " (\033[1m-static\033[0m) binary package as an additional \033[1mRequires\033[0m" << ::std::endl + << " RPM spec file directive. Repeat this option to" << ::std::endl + << " specify multiple extra dependencies." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_fedora_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_fedora_options_map; + + static _cli_pkg_bindist_fedora_options_map _cli_pkg_bindist_fedora_options_map_; + + struct _cli_pkg_bindist_fedora_options_map_init + { + _cli_pkg_bindist_fedora_options_map_init () + { + _cli_pkg_bindist_fedora_options_map_["--fedora-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, &pkg_bindist_fedora_options::fedora_prepare_only_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-buildflags"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_buildflags_, + &pkg_bindist_fedora_options::fedora_buildflags_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-build-option"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_build_option_, + &pkg_bindist_fedora_options::fedora_build_option_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-query-option"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_query_option_, + &pkg_bindist_fedora_options::fedora_query_option_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-dist-tag"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_dist_tag_, + &pkg_bindist_fedora_options::fedora_dist_tag_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-packager"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_packager_, + &pkg_bindist_fedora_options::fedora_packager_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-build-arch"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, string, &pkg_bindist_fedora_options::fedora_build_arch_, + &pkg_bindist_fedora_options::fedora_build_arch_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-main-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_main_langreq_, + &pkg_bindist_fedora_options::fedora_main_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-devel-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_devel_langreq_, + &pkg_bindist_fedora_options::fedora_devel_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-stat-langreq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_stat_langreq_, + &pkg_bindist_fedora_options::fedora_stat_langreq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-main-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_main_extrareq_, + &pkg_bindist_fedora_options::fedora_main_extrareq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-devel-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_devel_extrareq_, + &pkg_bindist_fedora_options::fedora_devel_extrareq_specified_ >; + _cli_pkg_bindist_fedora_options_map_["--fedora-stat-extrareq"] = + &::bpkg::cli::thunk< pkg_bindist_fedora_options, strings, &pkg_bindist_fedora_options::fedora_stat_extrareq_, + &pkg_bindist_fedora_options::fedora_stat_extrareq_specified_ >; + } + }; + + static _cli_pkg_bindist_fedora_options_map_init _cli_pkg_bindist_fedora_options_map_init_; + + bool pkg_bindist_fedora_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_fedora_options_map::const_iterator i (_cli_pkg_bindist_fedora_options_map_.find (o)); + + if (i != _cli_pkg_bindist_fedora_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_fedora_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; + } + + // pkg_bindist_archive_options + // + + pkg_bindist_archive_options:: + pkg_bindist_archive_options () + : archive_prepare_only_ (), + archive_type_ (), + archive_type_specified_ (false), + archive_lang_ (), + archive_lang_specified_ (false), + archive_lang_impl_ (), + archive_lang_impl_specified_ (false), + archive_no_cpu_ (), + archive_no_os_ (), + archive_build_meta_ (), + archive_build_meta_specified_ (false), + archive_install_root_ (), + archive_install_root_specified_ (false), + archive_install_config_ (), + archive_split_ (), + archive_split_specified_ (false) + { + } + + bool pkg_bindist_archive_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 pkg_bindist_archive_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 pkg_bindist_archive_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 pkg_bindist_archive_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 pkg_bindist_archive_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 pkg_bindist_archive_options:: + merge (const pkg_bindist_archive_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.archive_prepare_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_prepare_only_, a.archive_prepare_only_); + } + + if (a.archive_type_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->archive_type_, a.archive_type_); + this->archive_type_specified_ = true; + } + + if (a.archive_lang_specified_) + { + ::bpkg::cli::parser< std::multimap<string, string>>::merge ( + this->archive_lang_, a.archive_lang_); + this->archive_lang_specified_ = true; + } + + if (a.archive_lang_impl_specified_) + { + ::bpkg::cli::parser< std::multimap<string, string>>::merge ( + this->archive_lang_impl_, a.archive_lang_impl_); + this->archive_lang_impl_specified_ = true; + } + + if (a.archive_no_cpu_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_no_cpu_, a.archive_no_cpu_); + } + + if (a.archive_no_os_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_no_os_, a.archive_no_os_); + } + + if (a.archive_build_meta_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->archive_build_meta_, a.archive_build_meta_); + this->archive_build_meta_specified_ = true; + } + + if (a.archive_install_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->archive_install_root_, a.archive_install_root_); + this->archive_install_root_specified_ = true; + } + + if (a.archive_install_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->archive_install_config_, a.archive_install_config_); + } + + if (a.archive_split_specified_) + { + ::bpkg::cli::parser< std::map<string, string>>::merge ( + this->archive_split_, a.archive_split_); + this->archive_split_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_bindist_archive_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[1mARCHIVE DESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The installation archive binary packages are generated by invoking the \033[1mbuild2\033[0m" << ::std::endl + << "build system on the required packages directly in their \033[1mbpkg\033[0m configuration" << ::std::endl + << "locations and installing them into the binary package directory using the" << ::std::endl + << "\033[1mconfig.install.chroot\033[0m mechanism. Then this directory is packaged with \033[1mtar\033[0m or" << ::std::endl + << "\033[1mzip\033[0m to produce one or more binary package archives." << ::std::endl + << ::std::endl + << "The generation of installation archive packages is never the default and should" << ::std::endl + << "be requested explicitly with the \033[1m--distribution=archive\033[0m option. The" << ::std::endl + << "installation directory layout and the package archives to generate can be" << ::std::endl + << "specified with the \033[1m--archive-install-*\033[0m and \033[1m--archive-type\033[0m options (refer to" << ::std::endl + << "their documentation for defaults)." << ::std::endl + << ::std::endl + << "The binary package directory (the top-level directory inside the archive) as" << ::std::endl + << "well as the archive file base (the file name without the extension) are the" << ::std::endl + << "same and have the following form:" << ::std::endl + << ::std::endl + << "\033[4mpackage\033[0m-\033[4mversion\033[0m-\033[4mbuild_metadata\033[0m\033[0m" << ::std::endl + << ::std::endl + << "Where \033[4mpackage\033[0m is the package name and \033[4mversion\033[0m is the \033[1mbpkg\033[0m package version." << ::std::endl + << "Unless overridden with the \033[1m--archive-build-meta\033[0m option, \033[4mbuild_metadata\033[0m has the" << ::std::endl + << "following form:" << ::std::endl + << ::std::endl + << "\033[4mcpu\033[0m-\033[4mos\033[0m[-\033[4mlangrt\033[0m...]\033[0m" << ::std::endl + << ::std::endl + << "Where \033[4mcpu\033[0m is the target CPU (for example, \033[1mx86_64\033[0m or \033[1maarch64\033[0m; omitted if" << ::std::endl + << "\033[1m--archive-no-cpu\033[0m is specified), \033[4mos\033[0m is the \033[1mID\033[0m and \033[1mVERSION_ID\033[0m components from" << ::std::endl + << "\033[1mos-release(5)\033[0m (or equivalent, for example, \033[1mdebian11\033[0m or \033[1mwindows10\033[0m; omitted if" << ::std::endl + << "\033[1m--archive-no-os\033[0m is specified), and \033[4mlangrt\033[0m are the language runtimes as mapped" << ::std::endl + << "by the \033[1m--archive-lang*\033[0m options (for example, \033[1mgcc12\033[0m or \033[1mmsvc17.4\033[0m)." << ::std::endl + << ::std::endl + << "For example, given the following invocation on Debian 11 running on \033[1mx86_64\033[0m:" << ::std::endl + << ::std::endl + << "bpkg build libhello" << ::std::endl + << "bpkg test libhello" << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " -o /tmp/output/ \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --archive-lang cc=gcc12 \\" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "We will end up with the package archive in the following form:" << ::std::endl + << ::std::endl + << "libhello-1.2.3-x86_64-debian11-gcc12.tar.xz" << ::std::endl + << ::std::endl + << "The recommended language runtime id format is the runtime name followed by the" << ::std::endl + << "version, for example, \033[1mgcc12\033[0m or \033[1mmsvc17.4\033[0m. Note that its purpose is not to" << ::std::endl + << "provide a precise specification of requirements but rather to help the user of" << ::std::endl + << "a binary package to pick the appropriate variant. Refer to the \033[1m--archive-lang*\033[0m" << ::std::endl + << "options documentation for details on the mapping semantics." << ::std::endl + << ::std::endl + << "Instead of mapping languages individually you can specify entire build metadata" << ::std::endl + << "as a single value with the \033[1m--archive-build-meta\033[0m (it is also possible to add" << ::std::endl + << "additional metadata; see the option documentation for details). For example:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " -o /tmp/output/ \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --archive-build-meta=x86_64-linux-glibc" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "This will produce the package archive in the following form:" << ::std::endl + << ::std::endl + << "libhello-1.2.3-x86_64-linux-glibc.tar.xz" << ::std::endl + << ::std::endl + << "To install the binary package from archive simply unpack it using \033[1mtar\033[0m or \033[1mzip\033[0m." << ::std::endl + << "You can use the \033[1m--strip-components\033[0m \033[1mtar\033[0m option to remove the top-level package" << ::std::endl + << "directory (the same can be achieved for \033[1mzip\033[0m archives by using \033[1mbsdtar\033[0m on" << ::std::endl + << "Windows). For example, to unpack the package contents so that they end up in" << ::std::endl + << "\033[1m/usr/local/\033[0m:" << ::std::endl + << ::std::endl + << "sudo tar -xf libhello-1.2.3-x86_64-debian11-gcc12.tar.xz \\" << ::std::endl + << " -C / --strip-components=1" << ::std::endl + << ::std::endl + << "If you expect the binary package to be unpacked into a directory other than its" << ::std::endl + << "original installation directory (\033[1m--archive-install-root\033[0m), then it's recommended" << ::std::endl + << "to make it relocatable by specifying the \033[1mconfig.install.relocatable=true\033[0m" << ::std::endl + << "configuration variable. For example:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " ... \\" << ::std::endl + << " config.install.relocatable=true \\" << ::std::endl + << " libhello" << ::std::endl + << ::std::endl + << "Note that not all source packages support relocatable installation (see" << ::std::endl + << "Rolocatable Installation (b#install-reloc) for details)." << ::std::endl + << ::std::endl + << "Another mechanism that can useful when generating archive packages is the" << ::std::endl + << "ability to filter the files being installed. This, for example, can be used to" << ::std::endl + << "create binary packages that don't contain any development-related files. See" << ::std::endl + << "Installation Filtering (b#install-filter) for details. See also the" << ::std::endl + << "\033[1m--archive-split\033[0m option." << ::std::endl + << ::std::endl + << "The installation archive package can be generated for a target other than the" << ::std::endl + << "host by specifying the target triplet with the \033[1m--architecture\033[0m option. In this" << ::std::endl + << "case the \033[1mbpkg\033[0m configuration is assumed to be appropriately configured for" << ::std::endl + << "cross-compiling to the specified target. You will also need to explicitly" << ::std::endl + << "specify the \033[1m--archive-install-root\033[0m option (or \033[1m--archive-install-config\033[0m) as well" << ::std::endl + << "as the \033[1m--os-release-id\033[0m option (and likely want to specify other \033[1m--os-release-*\033[0m" << ::std::endl + << "options). For example, for cross-compiling from Linux to Windows using the" << ::std::endl + << "MinGW GCC toolchain:" << ::std::endl + << ::std::endl + << "bpkg bindist \\" << ::std::endl + << " --distribution=archive \\" << ::std::endl + << " --architecture=x86_64-w64-mingw32 \\" << ::std::endl + << " --os-release-id=windows \\" << ::std::endl + << " --os-release-name=Windows \\" << ::std::endl + << " --os-release-version-id=10 \\" << ::std::endl + << " --archive-install-root / \\" << ::std::endl + << " --archive-lang cc=mingw_w64_gcc12 \\" << ::std::endl + << " ..." << ::std::endl; + + os << std::endl + << "\033[1mPKG-BINDIST ARCHIVE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--archive-prepare-only\033[0m Prepare all the package contents but do not create" << ::std::endl + << " the binary package archive, printing its directory" << ::std::endl + << " instead unless requested to be quiet. Implies" << ::std::endl + << " \033[1m--keep-output\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--archive-type\033[0m \033[4mext\033[0m Archive type to create specified as a file extension," << ::std::endl + << " for example, \033[1mtar.xz\033[0m, \033[1mtar.gz\033[0m, \033[1mtar\033[0m, \033[1mzip\033[0m. Repeat this" << ::std::endl + << " option to generate multiple archive types. If" << ::std::endl + << " unspecified, then a default type appropriate for the" << ::std::endl + << " target operating system is used, currently \033[1mzip\033[0m for" << ::std::endl + << " Windows and \033[1mtar.xz\033[0m for POSIX. Note, however, that" << ::std::endl + << " these defaults may change in the future." << ::std::endl; + + os << std::endl + << "\033[1m--archive-lang\033[0m \033[4mln\033[0m=\033[4mrt\033[0m Map interface language name \033[4mln\033[0m to runtime id \033[4mrt\033[0m. If" << ::std::endl + << " no mapping is found for an interface language in this" << ::std::endl + << " map, then fallback to the \033[1m--archive-lang-impl\033[0m map. If" << ::std::endl + << " still no mapping is found, then fail. If the" << ::std::endl + << " information about an interface language is" << ::std::endl + << " unimportant and should be ignored, then empty runtime" << ::std::endl + << " id can be specified. Note that the mapping specified" << ::std::endl + << " with this option is only considered if the package" << ::std::endl + << " type is a library (for other package types all" << ::std::endl + << " languages used are implementation). Note also that" << ::std::endl + << " multiple runtime ids specified for the same language" << ::std::endl + << " are combined except for an empty id, which is treated" << ::std::endl + << " as a request to clear previous entries." << ::std::endl; + + os << std::endl + << "\033[1m--archive-lang-impl\033[0m \033[4mln\033[0m=\033[4mrt\033[0m Map implementation language name \033[4mln\033[0m to runtime id \033[4mrt\033[0m." << ::std::endl + << " If no mapping is found for an implementation language" << ::std::endl + << " in this map, then assume the information about this" << ::std::endl + << " implementation language is unimportant and ignore it" << ::std::endl + << " (examples of such cases include static linking as" << ::std::endl + << " well as a language runtime that is always present)." << ::std::endl + << " See \033[1m--archive-lang\033[0m for background." << ::std::endl; + + os << std::endl + << "\033[1m--archive-no-cpu\033[0m Assume the package is CPU architecture-independent" << ::std::endl + << " and omit it from the binary package directory name" << ::std::endl + << " and archive file base." << ::std::endl; + + os << std::endl + << "\033[1m--archive-no-os\033[0m Assume the package is operating system-independent" << ::std::endl + << " and omit it from the binary package directory name" << ::std::endl + << " and archive file base." << ::std::endl; + + os << std::endl + << "\033[1m--archive-build-meta\033[0m \033[4mdata\033[0m Alternative or additional build metadata to include" << ::std::endl + << " after the version in the binary package directory and" << ::std::endl + << " file names. If the specified value starts/ends with" << ::std::endl + << " \033[1m+\033[0m then the value (with \033[1m+\033[0m removed) is added" << ::std::endl + << " after/before the default metadata. Otherwise it is" << ::std::endl + << " used as is instead of the default metadata. If empty" << ::std::endl + << " value is specified, then no build metadata is" << ::std::endl + << " included." << ::std::endl; + + os << std::endl + << "\033[1m--archive-install-root\033[0m \033[4md\033[0m Alternative installation root directory. The default" << ::std::endl + << " is \033[1m/usr/local/\033[0m on POSIX and \033[1mC:\\\033[0m\033[4mproject\033[0m\033[1m\\\033[0m\033[0m on Windows," << ::std::endl + << " where \033[4mproject\033[0m is the \033[1mproject\033[0m" << ::std::endl + << " (bpkg#manifest-package-project) package manifest" << ::std::endl + << " value." << ::std::endl; + + os << std::endl + << "\033[1m--archive-install-config\033[0m Use the installation directory layout" << ::std::endl + << " (\033[1mconfig.install.*\033[0m variables) as configured instead of" << ::std::endl + << " overriding them with defaults appropriate for the" << ::std::endl + << " target operating system. Note that this includes" << ::std::endl + << " \033[1mconfig.install.private\033[0m and \033[1mconfig.bin.rpath\033[0m if needed" << ::std::endl + << " for a private installation. Note also that the" << ::std::endl + << " \033[1mconfig.install.root\033[0m value is still overridden with" << ::std::endl + << " the \033[1m--archive-install-root\033[0m option value if specified." << ::std::endl; + + os << std::endl + << "\033[1m--archive-split\033[0m \033[4mkey\033[0m=\033[4mfilt\033[0m Split the installation into multiple binary packages." << ::std::endl + << " Specifically, for each \033[4mkey\033[0m=\033[4mfilt\033[0m pair, perform the" << ::std::endl + << " \033[1minstall\033[0m operation with \033[1mconfig.install.filter=\033[0m\033[4mfilt\033[0m\033[0m and" << ::std::endl + << " package the resulting files as" << ::std::endl + << " \033[4mpackage-key-version-build_metadata\033[0m omitting the \033[4m-key\033[0m" << ::std::endl + << " part if \033[4mkey\033[0m is empty. Note that wildcard patterns in" << ::std::endl + << " \033[4mfilt\033[0m must be quoted. See Installation Filtering" << ::std::endl + << " (b#install-filter) for background." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_archive_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_archive_options_map; + + static _cli_pkg_bindist_archive_options_map _cli_pkg_bindist_archive_options_map_; + + struct _cli_pkg_bindist_archive_options_map_init + { + _cli_pkg_bindist_archive_options_map_init () + { + _cli_pkg_bindist_archive_options_map_["--archive-prepare-only"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_prepare_only_ >; + _cli_pkg_bindist_archive_options_map_["--archive-type"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, strings, &pkg_bindist_archive_options::archive_type_, + &pkg_bindist_archive_options::archive_type_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-lang"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::multimap<string, string>, &pkg_bindist_archive_options::archive_lang_, + &pkg_bindist_archive_options::archive_lang_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-lang-impl"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::multimap<string, string>, &pkg_bindist_archive_options::archive_lang_impl_, + &pkg_bindist_archive_options::archive_lang_impl_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-no-cpu"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_no_cpu_ >; + _cli_pkg_bindist_archive_options_map_["--archive-no-os"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_no_os_ >; + _cli_pkg_bindist_archive_options_map_["--archive-build-meta"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, string, &pkg_bindist_archive_options::archive_build_meta_, + &pkg_bindist_archive_options::archive_build_meta_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-install-root"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, dir_path, &pkg_bindist_archive_options::archive_install_root_, + &pkg_bindist_archive_options::archive_install_root_specified_ >; + _cli_pkg_bindist_archive_options_map_["--archive-install-config"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, &pkg_bindist_archive_options::archive_install_config_ >; + _cli_pkg_bindist_archive_options_map_["--archive-split"] = + &::bpkg::cli::thunk< pkg_bindist_archive_options, std::map<string, string>, &pkg_bindist_archive_options::archive_split_, + &pkg_bindist_archive_options::archive_split_specified_ >; + } + }; + + static _cli_pkg_bindist_archive_options_map_init _cli_pkg_bindist_archive_options_map_init_; + + bool pkg_bindist_archive_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_archive_options_map::const_iterator i (_cli_pkg_bindist_archive_options_map_.find (o)); + + if (i != _cli_pkg_bindist_archive_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_bindist_archive_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; + } + + // pkg_bindist_options + // + + pkg_bindist_options:: + pkg_bindist_options () + { + } + + bool pkg_bindist_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 pkg_bindist_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 pkg_bindist_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 pkg_bindist_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 pkg_bindist_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 pkg_bindist_options:: + merge (const pkg_bindist_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // pkg_bindist_common_options base + // + ::bpkg::pkg_bindist_common_options::merge (a); + + // pkg_bindist_debian_options base + // + ::bpkg::pkg_bindist_debian_options::merge (a); + + // pkg_bindist_fedora_options base + // + ::bpkg::pkg_bindist_fedora_options::merge (a); + + // pkg_bindist_archive_options base + // + ::bpkg::pkg_bindist_archive_options::merge (a); + } + + ::bpkg::cli::usage_para pkg_bindist_options:: + print_usage (::std::ostream& os, ::bpkg::cli::usage_para p) + { + CLI_POTENTIALLY_UNUSED (os); + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_bindist_options&, ::bpkg::cli::scanner&)> + _cli_pkg_bindist_options_map; + + static _cli_pkg_bindist_options_map _cli_pkg_bindist_options_map_; + + struct _cli_pkg_bindist_options_map_init + { + _cli_pkg_bindist_options_map_init () + { + } + }; + + static _cli_pkg_bindist_options_map_init _cli_pkg_bindist_options_map_init_; + + bool pkg_bindist_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_bindist_options_map::const_iterator i (_cli_pkg_bindist_options_map_.find (o)); + + if (i != _cli_pkg_bindist_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // pkg_bindist_common_options base + // + if (::bpkg::pkg_bindist_common_options::_parse (o, s)) + return true; + + // pkg_bindist_debian_options base + // + if (::bpkg::pkg_bindist_debian_options::_parse (o, s)) + return true; + + // pkg_bindist_fedora_options base + // + if (::bpkg::pkg_bindist_fedora_options::_parse (o, s)) + return true; + + // pkg_bindist_archive_options base + // + if (::bpkg::pkg_bindist_archive_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_bindist_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_pkg_bindist_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 pkg-bindist\033[0m|\033[1mbindist\033[0m [\033[1m--output-root\033[0m|\033[1m-o\033[0m \033[4mdir\033[0m] [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-bindist\033[0m command generates a binary distribution package for the" << ::std::endl + << "specified package. If additional packages are specified, then they are bundled" << ::std::endl + << "in the same distribution package. All the specified packages must have been" << ::std::endl + << "previously configured with \033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m. For some" << ::std::endl + << "system package managers a directory for intermediate files and subdirectories" << ::std::endl + << "as well as the resulting binary package may have to be specified explicitly" << ::std::endl + << "with the \033[1m--output-root\033[0m|\033[1m-o\033[0m\033[0m option." << ::std::endl + << ::std::endl + << "Underneath, this command roughly performs the following steps: First it" << ::std::endl + << "installs the specified packages similar to the \033[1mbpkg-pkg-install(1)\033[0m command" << ::std::endl + << "except that it may override the installation locations (via the" << ::std::endl + << "\033[1mconfig.install.*\033[0m variables) to match the distribution's layout. Then it" << ::std::endl + << "generates any necessary distribution package metadata files based on the" << ::std::endl + << "information from the package \033[1mmanifest\033[0m files. Finally, it invokes the" << ::std::endl + << "distribution-specific command to produce the binary package. Unless overridden" << ::std::endl + << "with the \033[1m--architecture\033[0m and \033[1m--distribution\033[0m options, the binary package is" << ::std::endl + << "generated for the host architecture using the host's standard system package" << ::std::endl + << "manager. Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be" << ::std::endl + << "passed to the build system during the installation step. See the following" << ::std::endl + << "distribution-specific description sections below for details and invocation" << ::std::endl + << "examples:" << ::std::endl + << ::std::endl + << "DEBIAN DESCRIPTION" << ::std::endl + << ::std::endl + << "FEDORA DESCRIPTION" << ::std::endl + << ::std::endl + << "ARCHIVE DESCRIPTION" << ::std::endl + << ::std::endl + << "The specified packages may have dependencies and the default behavior is to not" << ::std::endl + << "bundle them but rather to specify them as dependencies in the corresponding" << ::std::endl + << "distribution package metadata, if applicable. This default behavior can be" << ::std::endl + << "overridden with the \033[1m--recursive\033[0m option (see the option description for the" << ::std::endl + << "available modes). Note, however, that dependencies that are satisfied by system" << ::std::endl + << "packages are always specified as dependencies in the distribution package" << ::std::endl + << "metadata (if applicable)." << ::std::endl; + + p = ::bpkg::pkg_bindist_common_options::print_usage (os, ::bpkg::cli::usage_para::text); + + p = ::bpkg::pkg_bindist_debian_options::print_usage (os, p); + + p = ::bpkg::pkg_bindist_fedora_options::print_usage (os, p); + + p = ::bpkg::pkg_bindist_archive_options::print_usage (os, p); + + if (p != ::bpkg::cli::usage_para::none) + os << ::std::endl; + + os << "\033[1mSTRUCTURED RESULT\033[0m" << ::std::endl + << ::std::endl + << "Instead of printing to \033[1mstderr\033[0m the list of generated binary packages in a format" << ::std::endl + << "more suitable for human consumption, the \033[1mpkg-bindist\033[0m command can be instructed" << ::std::endl + << "to write it to \033[1mstdout\033[0m in a machine-readable form by specifying the" << ::std::endl + << "\033[1m--structured-result\033[0m option. Currently, the only recognized format value for" << ::std::endl + << "this option is \033[1mjson\033[0m with the output being a JSON object that is a serialized" << ::std::endl + << "representation of the following C++ struct \033[1mbindist_result\033[0m:" << ::std::endl + << ::std::endl + << "struct os_release" << ::std::endl + << "{" << ::std::endl + << " string name_id; // ID" << ::std::endl + << " vector<string> like_ids; // ID_LIKE" << ::std::endl + << " optional<string> version_id; // VERSION_ID" << ::std::endl + << " optional<string> variant_id; // VARIANT_ID" << ::std::endl + << ::std::endl + << " optional<string> name; // NAME" << ::std::endl + << " optional<string> version_codename; // VERSION_CODENAME" << ::std::endl + << " optional<string> variant; // VARIANT" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct file" << ::std::endl + << "{" << ::std::endl + << " string type;" << ::std::endl + << " string path;" << ::std::endl + << " optional<string> system_name;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct package" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << " string version;" << ::std::endl + << " optional<string> system_version;" << ::std::endl + << " vector<file> files;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct bindist_result" << ::std::endl + << "{" << ::std::endl + << " string distribution; // --distribution or auto-detected" << ::std::endl + << " string architecture; // --architecture or auto-detected" << ::std::endl + << " os_release os_release; // --os-release-* or auto-detected" << ::std::endl + << " optional<string> recursive; // --recursive" << ::std::endl + << " bool private; // --private" << ::std::endl + << " bool dependent_config; // See --allow-dependent-config" << ::std::endl + << ::std::endl + << " package package;" << ::std::endl + << " vector<package> dependencies; // Only in --recursive=separate" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "For example:" << ::std::endl + << ::std::endl + << "{" << ::std::endl + << " \"distribution\": \"debian\"," << ::std::endl + << " \"architecture\": \"amd64\"," << ::std::endl + << " \"os_release\": {" << ::std::endl + << " \"name_id\": \"debian\"," << ::std::endl + << " \"version_id\": \"11\"," << ::std::endl + << " \"name\": \"Debian GNU/Linux\"" << ::std::endl + << " }," << ::std::endl + << " \"package\": {" << ::std::endl + << " \"name\": \"libfoo\"," << ::std::endl + << " \"version\": \"2.5.0-b.23\"," << ::std::endl + << " \"system_version\": \"2.5.0~b.23-0~debian11\"," << ::std::endl + << " \"files\": [" << ::std::endl + << " {" << ::std::endl + << " \"type\": \"main.deb\"," << ::std::endl + << " \"path\": \"/tmp/libfoo_2.5.0~b.23-0~debian11_amd64.deb\"," << ::std::endl + << " \"system_name\": \"libfoo\"" << ::std::endl + << " }," << ::std::endl + << " {" << ::std::endl + << " \"type\": \"dev.deb\"," << ::std::endl + << " \"path\": \"/tmp/libfoo-dev_2.5.0~b.23-0~debian11_amd64.deb\"," << ::std::endl + << " \"system_name\": \"libfoo-dev\"" << ::std::endl + << " }," << ::std::endl + << " ..." << ::std::endl + << " ]" << ::std::endl + << " }" << ::std::endl + << "}" << ::std::endl + << ::std::endl + << "See the JSON OUTPUT section in \033[1mbpkg-common-options(1)\033[0m for details on the" << ::std::endl + << "overall properties of this format and the semantics of the \033[1mstruct\033[0m" << ::std::endl + << "serialization." << ::std::endl + << ::std::endl + << "The \033[1mfile::type\033[0m member is a distribution-specific value that classifies the" << ::std::endl + << "file. For the \033[1mdebian\033[0m distribution the possible values are \033[1mmain.deb\033[0m, \033[1mdev.deb\033[0m," << ::std::endl + << "\033[1mdoc.deb\033[0m, \033[1mcommon.deb\033[0m, \033[1mdbgsym.deb\033[0m, \033[1mchanges\033[0m (\033[1m.changes\033[0m file), and \033[1mbuildid\033[0m" << ::std::endl + << "(\033[1m.buildid\033[0m file); see Debian Package Mapping for Production" << ::std::endl + << "(bpkg#bindist-mapping-debian-produce) for background. For the \033[1mfedora\033[0m" << ::std::endl + << "distribution the possible values are \033[1mmain.rpm\033[0m, \033[1mdevel.rpm\033[0m, \033[1mstatic.rpm\033[0m, \033[1mdoc.rpm\033[0m," << ::std::endl + << "\033[1mcommon.rpm\033[0m, and \033[1mdebuginfo.rpm\033[0m; see Fedora Package Mapping for Production" << ::std::endl + << "(bpkg#bindist-mapping-fedora-produce) for background. For the \033[1marchive\033[0m" << ::std::endl + << "distribution this is the archive type (\033[1m--archive-type\033[0m), for example, \033[1mtar.xz\033[0m or" << ::std::endl + << "\033[1mzip\033[0m, potentially prefixed with \033[4mkey\033[0m if the \033[1m--archive-split\033[0m functionality is" << ::std::endl + << "used, for example, \033[1mdev.tar.xz\033[0m." << ::std::endl + << ::std::endl + << "The \033[1mpackage::system_version\033[0m and/or \033[1mfile::system_name\033[0m members are absent if not" << ::std::endl + << "applicable to the distribution. The \033[1mfile::system_name\033[0m member is also absent if" << ::std::endl + << "the file is not a binary package (for example, \033[1m.changes\033[0m and \033[1m.buildid\033[0m files in" << ::std::endl + << "the \033[1mdebian\033[0m distribution)." << ::std::endl; + + p = ::bpkg::pkg_bindist_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[1mpkg-bindist\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-pkg-bindist.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-bindist\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/pkg-bindist-options.hxx b/bpkg/pkg-bindist-options.hxx new file mode 100644 index 0000000..97b6a3b --- /dev/null +++ b/bpkg/pkg-bindist-options.hxx @@ -0,0 +1,742 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_BINDIST_OPTIONS_HXX +#define BPKG_PKG_BINDIST_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <map> + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_bindist_common_options: public ::bpkg::configuration_options + { + public: + pkg_bindist_common_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 pkg_bindist_common_options&); + + // Option accessors. + // + const string& + distribution () const; + + bool + distribution_specified () const; + + const string& + architecture () const; + + bool + architecture_specified () const; + + const string& + recursive () const; + + bool + recursive_specified () const; + + const bool& + private_ () const; + + const dir_path& + output_root () const; + + bool + output_root_specified () const; + + const bool& + wipe_output () const; + + const bool& + keep_output () const; + + const bool& + allow_dependent_config () const; + + const string& + os_release_id () const; + + bool + os_release_id_specified () const; + + const string& + os_release_version_id () const; + + bool + os_release_version_id_specified () const; + + const string& + os_release_name () const; + + bool + os_release_name_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: + string distribution_; + bool distribution_specified_; + string architecture_; + bool architecture_specified_; + string recursive_; + bool recursive_specified_; + bool private__; + dir_path output_root_; + bool output_root_specified_; + bool wipe_output_; + bool keep_output_; + bool allow_dependent_config_; + string os_release_id_; + bool os_release_id_specified_; + string os_release_version_id_; + bool os_release_version_id_specified_; + string os_release_name_; + bool os_release_name_specified_; + }; + + class pkg_bindist_debian_options + { + public: + pkg_bindist_debian_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 pkg_bindist_debian_options&); + + // Option accessors. + // + const bool& + debian_prepare_only () const; + + const string& + debian_buildflags () const; + + bool + debian_buildflags_specified () const; + + const strings& + debian_maint_option () const; + + bool + debian_maint_option_specified () const; + + const strings& + debian_build_option () const; + + bool + debian_build_option_specified () const; + + const string& + debian_build_meta () const; + + bool + debian_build_meta_specified () const; + + const string& + debian_section () const; + + bool + debian_section_specified () const; + + const string& + debian_priority () const; + + bool + debian_priority_specified () const; + + const string& + debian_maintainer () const; + + bool + debian_maintainer_specified () const; + + const string& + debian_architecture () const; + + bool + debian_architecture_specified () const; + + const string& + debian_main_langdep () const; + + bool + debian_main_langdep_specified () const; + + const string& + debian_dev_langdep () const; + + bool + debian_dev_langdep_specified () const; + + const string& + debian_main_extradep () const; + + bool + debian_main_extradep_specified () const; + + const string& + debian_dev_extradep () const; + + bool + debian_dev_extradep_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: + bool debian_prepare_only_; + string debian_buildflags_; + bool debian_buildflags_specified_; + strings debian_maint_option_; + bool debian_maint_option_specified_; + strings debian_build_option_; + bool debian_build_option_specified_; + string debian_build_meta_; + bool debian_build_meta_specified_; + string debian_section_; + bool debian_section_specified_; + string debian_priority_; + bool debian_priority_specified_; + string debian_maintainer_; + bool debian_maintainer_specified_; + string debian_architecture_; + bool debian_architecture_specified_; + string debian_main_langdep_; + bool debian_main_langdep_specified_; + string debian_dev_langdep_; + bool debian_dev_langdep_specified_; + string debian_main_extradep_; + bool debian_main_extradep_specified_; + string debian_dev_extradep_; + bool debian_dev_extradep_specified_; + }; + + class pkg_bindist_fedora_options + { + public: + pkg_bindist_fedora_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 pkg_bindist_fedora_options&); + + // Option accessors. + // + const bool& + fedora_prepare_only () const; + + const string& + fedora_buildflags () const; + + bool + fedora_buildflags_specified () const; + + const strings& + fedora_build_option () const; + + bool + fedora_build_option_specified () const; + + const strings& + fedora_query_option () const; + + bool + fedora_query_option_specified () const; + + const string& + fedora_dist_tag () const; + + bool + fedora_dist_tag_specified () const; + + const string& + fedora_packager () const; + + bool + fedora_packager_specified () const; + + const string& + fedora_build_arch () const; + + bool + fedora_build_arch_specified () const; + + const strings& + fedora_main_langreq () const; + + bool + fedora_main_langreq_specified () const; + + const strings& + fedora_devel_langreq () const; + + bool + fedora_devel_langreq_specified () const; + + const strings& + fedora_stat_langreq () const; + + bool + fedora_stat_langreq_specified () const; + + const strings& + fedora_main_extrareq () const; + + bool + fedora_main_extrareq_specified () const; + + const strings& + fedora_devel_extrareq () const; + + bool + fedora_devel_extrareq_specified () const; + + const strings& + fedora_stat_extrareq () const; + + bool + fedora_stat_extrareq_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: + bool fedora_prepare_only_; + string fedora_buildflags_; + bool fedora_buildflags_specified_; + strings fedora_build_option_; + bool fedora_build_option_specified_; + strings fedora_query_option_; + bool fedora_query_option_specified_; + string fedora_dist_tag_; + bool fedora_dist_tag_specified_; + string fedora_packager_; + bool fedora_packager_specified_; + string fedora_build_arch_; + bool fedora_build_arch_specified_; + strings fedora_main_langreq_; + bool fedora_main_langreq_specified_; + strings fedora_devel_langreq_; + bool fedora_devel_langreq_specified_; + strings fedora_stat_langreq_; + bool fedora_stat_langreq_specified_; + strings fedora_main_extrareq_; + bool fedora_main_extrareq_specified_; + strings fedora_devel_extrareq_; + bool fedora_devel_extrareq_specified_; + strings fedora_stat_extrareq_; + bool fedora_stat_extrareq_specified_; + }; + + class pkg_bindist_archive_options + { + public: + pkg_bindist_archive_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 pkg_bindist_archive_options&); + + // Option accessors. + // + const bool& + archive_prepare_only () const; + + const strings& + archive_type () const; + + bool + archive_type_specified () const; + + const std::multimap<string, string>& + archive_lang () const; + + bool + archive_lang_specified () const; + + const std::multimap<string, string>& + archive_lang_impl () const; + + bool + archive_lang_impl_specified () const; + + const bool& + archive_no_cpu () const; + + const bool& + archive_no_os () const; + + const string& + archive_build_meta () const; + + bool + archive_build_meta_specified () const; + + const dir_path& + archive_install_root () const; + + bool + archive_install_root_specified () const; + + const bool& + archive_install_config () const; + + const std::map<string, string>& + archive_split () const; + + bool + archive_split_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: + bool archive_prepare_only_; + strings archive_type_; + bool archive_type_specified_; + std::multimap<string, string> archive_lang_; + bool archive_lang_specified_; + std::multimap<string, string> archive_lang_impl_; + bool archive_lang_impl_specified_; + bool archive_no_cpu_; + bool archive_no_os_; + string archive_build_meta_; + bool archive_build_meta_specified_; + dir_path archive_install_root_; + bool archive_install_root_specified_; + bool archive_install_config_; + std::map<string, string> archive_split_; + bool archive_split_specified_; + }; + + class pkg_bindist_options: public ::bpkg::pkg_bindist_common_options, + public ::bpkg::pkg_bindist_debian_options, + public ::bpkg::pkg_bindist_fedora_options, + public ::bpkg::pkg_bindist_archive_options + { + public: + pkg_bindist_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 pkg_bindist_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_pkg_bindist_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-bindist-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_BINDIST_OPTIONS_HXX diff --git a/bpkg/pkg-bindist-options.ixx b/bpkg/pkg-bindist-options.ixx new file mode 100644 index 0000000..3a5ef7c --- /dev/null +++ b/bpkg/pkg-bindist-options.ixx @@ -0,0 +1,537 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_bindist_common_options + // + + inline const string& pkg_bindist_common_options:: + distribution () const + { + return this->distribution_; + } + + inline bool pkg_bindist_common_options:: + distribution_specified () const + { + return this->distribution_specified_; + } + + inline const string& pkg_bindist_common_options:: + architecture () const + { + return this->architecture_; + } + + inline bool pkg_bindist_common_options:: + architecture_specified () const + { + return this->architecture_specified_; + } + + inline const string& pkg_bindist_common_options:: + recursive () const + { + return this->recursive_; + } + + inline bool pkg_bindist_common_options:: + recursive_specified () const + { + return this->recursive_specified_; + } + + inline const bool& pkg_bindist_common_options:: + private_ () const + { + return this->private__; + } + + inline const dir_path& pkg_bindist_common_options:: + output_root () const + { + return this->output_root_; + } + + inline bool pkg_bindist_common_options:: + output_root_specified () const + { + return this->output_root_specified_; + } + + inline const bool& pkg_bindist_common_options:: + wipe_output () const + { + return this->wipe_output_; + } + + inline const bool& pkg_bindist_common_options:: + keep_output () const + { + return this->keep_output_; + } + + inline const bool& pkg_bindist_common_options:: + allow_dependent_config () const + { + return this->allow_dependent_config_; + } + + inline const string& pkg_bindist_common_options:: + os_release_id () const + { + return this->os_release_id_; + } + + inline bool pkg_bindist_common_options:: + os_release_id_specified () const + { + return this->os_release_id_specified_; + } + + inline const string& pkg_bindist_common_options:: + os_release_version_id () const + { + return this->os_release_version_id_; + } + + inline bool pkg_bindist_common_options:: + os_release_version_id_specified () const + { + return this->os_release_version_id_specified_; + } + + inline const string& pkg_bindist_common_options:: + os_release_name () const + { + return this->os_release_name_; + } + + inline bool pkg_bindist_common_options:: + os_release_name_specified () const + { + return this->os_release_name_specified_; + } + + // pkg_bindist_debian_options + // + + inline const bool& pkg_bindist_debian_options:: + debian_prepare_only () const + { + return this->debian_prepare_only_; + } + + inline const string& pkg_bindist_debian_options:: + debian_buildflags () const + { + return this->debian_buildflags_; + } + + inline bool pkg_bindist_debian_options:: + debian_buildflags_specified () const + { + return this->debian_buildflags_specified_; + } + + inline const strings& pkg_bindist_debian_options:: + debian_maint_option () const + { + return this->debian_maint_option_; + } + + inline bool pkg_bindist_debian_options:: + debian_maint_option_specified () const + { + return this->debian_maint_option_specified_; + } + + inline const strings& pkg_bindist_debian_options:: + debian_build_option () const + { + return this->debian_build_option_; + } + + inline bool pkg_bindist_debian_options:: + debian_build_option_specified () const + { + return this->debian_build_option_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_build_meta () const + { + return this->debian_build_meta_; + } + + inline bool pkg_bindist_debian_options:: + debian_build_meta_specified () const + { + return this->debian_build_meta_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_section () const + { + return this->debian_section_; + } + + inline bool pkg_bindist_debian_options:: + debian_section_specified () const + { + return this->debian_section_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_priority () const + { + return this->debian_priority_; + } + + inline bool pkg_bindist_debian_options:: + debian_priority_specified () const + { + return this->debian_priority_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_maintainer () const + { + return this->debian_maintainer_; + } + + inline bool pkg_bindist_debian_options:: + debian_maintainer_specified () const + { + return this->debian_maintainer_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_architecture () const + { + return this->debian_architecture_; + } + + inline bool pkg_bindist_debian_options:: + debian_architecture_specified () const + { + return this->debian_architecture_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_main_langdep () const + { + return this->debian_main_langdep_; + } + + inline bool pkg_bindist_debian_options:: + debian_main_langdep_specified () const + { + return this->debian_main_langdep_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_dev_langdep () const + { + return this->debian_dev_langdep_; + } + + inline bool pkg_bindist_debian_options:: + debian_dev_langdep_specified () const + { + return this->debian_dev_langdep_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_main_extradep () const + { + return this->debian_main_extradep_; + } + + inline bool pkg_bindist_debian_options:: + debian_main_extradep_specified () const + { + return this->debian_main_extradep_specified_; + } + + inline const string& pkg_bindist_debian_options:: + debian_dev_extradep () const + { + return this->debian_dev_extradep_; + } + + inline bool pkg_bindist_debian_options:: + debian_dev_extradep_specified () const + { + return this->debian_dev_extradep_specified_; + } + + // pkg_bindist_fedora_options + // + + inline const bool& pkg_bindist_fedora_options:: + fedora_prepare_only () const + { + return this->fedora_prepare_only_; + } + + inline const string& pkg_bindist_fedora_options:: + fedora_buildflags () const + { + return this->fedora_buildflags_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_buildflags_specified () const + { + return this->fedora_buildflags_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_build_option () const + { + return this->fedora_build_option_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_build_option_specified () const + { + return this->fedora_build_option_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_query_option () const + { + return this->fedora_query_option_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_query_option_specified () const + { + return this->fedora_query_option_specified_; + } + + inline const string& pkg_bindist_fedora_options:: + fedora_dist_tag () const + { + return this->fedora_dist_tag_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_dist_tag_specified () const + { + return this->fedora_dist_tag_specified_; + } + + inline const string& pkg_bindist_fedora_options:: + fedora_packager () const + { + return this->fedora_packager_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_packager_specified () const + { + return this->fedora_packager_specified_; + } + + inline const string& pkg_bindist_fedora_options:: + fedora_build_arch () const + { + return this->fedora_build_arch_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_build_arch_specified () const + { + return this->fedora_build_arch_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_main_langreq () const + { + return this->fedora_main_langreq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_main_langreq_specified () const + { + return this->fedora_main_langreq_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_devel_langreq () const + { + return this->fedora_devel_langreq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_devel_langreq_specified () const + { + return this->fedora_devel_langreq_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_stat_langreq () const + { + return this->fedora_stat_langreq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_stat_langreq_specified () const + { + return this->fedora_stat_langreq_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_main_extrareq () const + { + return this->fedora_main_extrareq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_main_extrareq_specified () const + { + return this->fedora_main_extrareq_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_devel_extrareq () const + { + return this->fedora_devel_extrareq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_devel_extrareq_specified () const + { + return this->fedora_devel_extrareq_specified_; + } + + inline const strings& pkg_bindist_fedora_options:: + fedora_stat_extrareq () const + { + return this->fedora_stat_extrareq_; + } + + inline bool pkg_bindist_fedora_options:: + fedora_stat_extrareq_specified () const + { + return this->fedora_stat_extrareq_specified_; + } + + // pkg_bindist_archive_options + // + + inline const bool& pkg_bindist_archive_options:: + archive_prepare_only () const + { + return this->archive_prepare_only_; + } + + inline const strings& pkg_bindist_archive_options:: + archive_type () const + { + return this->archive_type_; + } + + inline bool pkg_bindist_archive_options:: + archive_type_specified () const + { + return this->archive_type_specified_; + } + + inline const std::multimap<string, string>& pkg_bindist_archive_options:: + archive_lang () const + { + return this->archive_lang_; + } + + inline bool pkg_bindist_archive_options:: + archive_lang_specified () const + { + return this->archive_lang_specified_; + } + + inline const std::multimap<string, string>& pkg_bindist_archive_options:: + archive_lang_impl () const + { + return this->archive_lang_impl_; + } + + inline bool pkg_bindist_archive_options:: + archive_lang_impl_specified () const + { + return this->archive_lang_impl_specified_; + } + + inline const bool& pkg_bindist_archive_options:: + archive_no_cpu () const + { + return this->archive_no_cpu_; + } + + inline const bool& pkg_bindist_archive_options:: + archive_no_os () const + { + return this->archive_no_os_; + } + + inline const string& pkg_bindist_archive_options:: + archive_build_meta () const + { + return this->archive_build_meta_; + } + + inline bool pkg_bindist_archive_options:: + archive_build_meta_specified () const + { + return this->archive_build_meta_specified_; + } + + inline const dir_path& pkg_bindist_archive_options:: + archive_install_root () const + { + return this->archive_install_root_; + } + + inline bool pkg_bindist_archive_options:: + archive_install_root_specified () const + { + return this->archive_install_root_specified_; + } + + inline const bool& pkg_bindist_archive_options:: + archive_install_config () const + { + return this->archive_install_config_; + } + + inline const std::map<string, string>& pkg_bindist_archive_options:: + archive_split () const + { + return this->archive_split_; + } + + inline bool pkg_bindist_archive_options:: + archive_split_specified () const + { + return this->archive_split_specified_; + } + + // pkg_bindist_options + // +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-build-options.cxx b/bpkg/pkg-build-options.cxx new file mode 100644 index 0000000..20d04f7 --- /dev/null +++ b/bpkg/pkg-build-options.cxx @@ -0,0 +1,1846 @@ +// -*- 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/pkg-build-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_build_pkg_options + // + + pkg_build_pkg_options:: + pkg_build_pkg_options () + : upgrade_ (), + patch_ (), + deorphan_ (), + immediate_ (), + recursive_ (), + upgrade_immediate_ (), + patch_immediate_ (), + deorphan_immediate_ (), + upgrade_recursive_ (), + patch_recursive_ (), + deorphan_recursive_ (), + dependency_ (), + keep_out_ (), + disfigure_ (), + checkout_root_ (), + checkout_root_specified_ (false), + checkout_purge_ (), + config_name_ (), + config_name_specified_ (false), + config_id_ (), + config_id_specified_ (false), + config_uuid_ (), + config_uuid_specified_ (false) + { + } + + bool pkg_build_pkg_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 pkg_build_pkg_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 pkg_build_pkg_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 pkg_build_pkg_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 pkg_build_pkg_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 pkg_build_pkg_options:: + merge (const pkg_build_pkg_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + if (a.upgrade_) + { + ::bpkg::cli::parser< bool>::merge ( + this->upgrade_, a.upgrade_); + } + + if (a.patch_) + { + ::bpkg::cli::parser< bool>::merge ( + this->patch_, a.patch_); + } + + if (a.deorphan_) + { + ::bpkg::cli::parser< bool>::merge ( + this->deorphan_, a.deorphan_); + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + + if (a.upgrade_immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->upgrade_immediate_, a.upgrade_immediate_); + } + + if (a.patch_immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->patch_immediate_, a.patch_immediate_); + } + + if (a.deorphan_immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->deorphan_immediate_, a.deorphan_immediate_); + } + + if (a.upgrade_recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->upgrade_recursive_, a.upgrade_recursive_); + } + + if (a.patch_recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->patch_recursive_, a.patch_recursive_); + } + + if (a.deorphan_recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->deorphan_recursive_, a.deorphan_recursive_); + } + + if (a.dependency_) + { + ::bpkg::cli::parser< bool>::merge ( + this->dependency_, a.dependency_); + } + + if (a.keep_out_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_out_, a.keep_out_); + } + + if (a.disfigure_) + { + ::bpkg::cli::parser< bool>::merge ( + this->disfigure_, a.disfigure_); + } + + if (a.checkout_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->checkout_root_, a.checkout_root_); + this->checkout_root_specified_ = true; + } + + if (a.checkout_purge_) + { + ::bpkg::cli::parser< bool>::merge ( + this->checkout_purge_, a.checkout_purge_); + } + + if (a.config_name_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->config_name_, a.config_name_); + this->config_name_specified_ = true; + } + + if (a.config_id_specified_) + { + ::bpkg::cli::parser< vector<uint64_t>>::merge ( + this->config_id_, a.config_id_); + this->config_id_specified_ = true; + } + + if (a.config_uuid_specified_) + { + ::bpkg::cli::parser< vector<uuid>>::merge ( + this->config_uuid_, a.config_uuid_); + this->config_uuid_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_build_pkg_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[1mPKG-BUILD PACKAGE OPTIONS\033[0m" << ::std::endl + << ::std::endl + << "The following options (as well as additional configuration variables) can be" << ::std::endl + << "grouped to apply to a specific \033[4mpkg-spec\033[0m as well as specified globally, in which" << ::std::endl + << "case they apply to all the specified packages (see \033[1mbpkg-argument-grouping(1)\033[0m" << ::std::endl + << "for details)." << ::std::endl; + + os << std::endl + << "\033[1m--upgrade\033[0m|\033[1m-u\033[0m Upgrade packages to the latest available version that" << ::std::endl + << " satisfies all the constraints." << ::std::endl; + + os << std::endl + << "\033[1m--patch\033[0m|\033[1m-p\033[0m Upgrade packages to the latest available patch" << ::std::endl + << " version that satisfies all the constraints." << ::std::endl; + + os << std::endl + << "\033[1m--deorphan\033[0m Replace orphaned packages with the best matching" << ::std::endl + << " available package versions which satisfy all the" << ::std::endl + << " constraints." << ::std::endl + << ::std::endl + << " It may happen that a built package no longer has the" << ::std::endl + << " corresponding package available in the repository it" << ::std::endl + << " came from (for example, as a result of" << ::std::endl + << " \033[1mbpkg-rep-fetch(1)\033[0m or \033[1mbpkg-rep-remove(1)\033[0m). Such a" << ::std::endl + << " package is called an \033[4morphan\033[0m. Without the \033[1m--deorphan\033[0m" << ::std::endl + << " option, upgrading, downgrading, or patching an orphan" << ::std::endl + << " will leave it unchanged if a more suitable version of" << ::std::endl + << " the package is not available. If the \033[1m--deorphan\033[0m" << ::std::endl + << " option is specified, then an orphan will be replaced" << ::std::endl + << " with a non-orphan. In this case, if \033[1m--upgrade\033[0m," << ::std::endl + << " \033[1m--patch\033[0m, or the package version is specified, then" << ::std::endl + << " the new version is selected accordingly. Otherwise," << ::std::endl + << " the closest version to the orphaned version is" << ::std::endl + << " selected using the following preference order: (1)" << ::std::endl + << " same version, revision, and iteration, (2) latest" << ::std::endl + << " iteration of same version and revision, (3) later" << ::std::endl + << " revision of same version, (4) later patch of same" << ::std::endl + << " version, (5) later minor of same version, (6) latest" << ::std::endl + << " available version, including earlier (see Package" << ::std::endl + << " Version (bpkg#package-version) for details)." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also upgrade, patch, or deorphan immediate" << ::std::endl + << " dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also upgrade, patch, or deorphan all dependencies," << ::std::endl + << " recursively." << ::std::endl; + + os << std::endl + << "\033[1m--upgrade-immediate\033[0m Upgrade immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--patch-immediate\033[0m Patch immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--deorphan-immediate\033[0m Deorphan immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--upgrade-recursive\033[0m Upgrade all dependencies, recursively." << ::std::endl; + + os << std::endl + << "\033[1m--patch-recursive\033[0m Patch all dependencies, recursively." << ::std::endl; + + os << std::endl + << "\033[1m--deorphan-recursive\033[0m Deorphan all dependencies, recursively." << ::std::endl; + + os << std::endl + << "\033[1m--dependency\033[0m Build, upgrade, or downgrade a package as a" << ::std::endl + << " dependency rather than to hold." << ::std::endl; + + os << std::endl + << "\033[1m--keep-out\033[0m Keep output directories of external packages between" << ::std::endl + << " upgrades and downgrades. Refer to" << ::std::endl + << " \033[1mbpkg-pkg-disfigure(1)\033[0m for details." << ::std::endl; + + os << std::endl + << "\033[1m--disfigure\033[0m Disfigure packages between upgrades and downgrades" << ::std::endl + << " effectively causing a from-scratch reconfiguration." << ::std::endl; + + os << std::endl + << "\033[1m--checkout-root\033[0m \033[4mdir\033[0m Check out packages that come from version" << ::std::endl + << " control-based repositories into the specified" << ::std::endl + << " directory rather than into the configuration" << ::std::endl + << " directory. Refer to the \033[1m--output-root\033[0m option in" << ::std::endl + << " \033[1mbpkg-pkg-checkout(1)\033[0m for details." << ::std::endl; + + os << std::endl + << "\033[1m--checkout-purge\033[0m Remove the checked out package (source) directories" << ::std::endl + << " when the packages are purged. Refer to the" << ::std::endl + << " \033[1m--output-purge\033[0m option in \033[1mbpkg-pkg-checkout(1)\033[0m for" << ::std::endl + << " details." << ::std::endl; + + os << std::endl + << "\033[1m--config-name\033[0m \033[4mname\033[0m Name of the linked configuration to build this" << ::std::endl + << " package(s) in. By default, the package is built in" << ::std::endl + << " the current configuration. Repeat this option to" << ::std::endl + << " specify multiple configurations." << ::std::endl; + + os << std::endl + << "\033[1m--config-id\033[0m \033[4mnum\033[0m Numeric id of the linked configuration to build this" << ::std::endl + << " package(s) in. By default, the package is built in" << ::std::endl + << " the current configuration. Repeat this option to" << ::std::endl + << " specify multiple configurations." << ::std::endl; + + os << std::endl + << "\033[1m--config-uuid\033[0m \033[4muuid\033[0m UUID of the linked configuration to build this" << ::std::endl + << " package(s) in. By default, the package is built in" << ::std::endl + << " the current configuration. Repeat this this option to" << ::std::endl + << " specify multiple configurations." << ::std::endl; + + p = ::bpkg::cli::usage_para::option; + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_build_pkg_options&, ::bpkg::cli::scanner&)> + _cli_pkg_build_pkg_options_map; + + static _cli_pkg_build_pkg_options_map _cli_pkg_build_pkg_options_map_; + + struct _cli_pkg_build_pkg_options_map_init + { + _cli_pkg_build_pkg_options_map_init () + { + _cli_pkg_build_pkg_options_map_["--upgrade"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::upgrade_ >; + _cli_pkg_build_pkg_options_map_["-u"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::upgrade_ >; + _cli_pkg_build_pkg_options_map_["--patch"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::patch_ >; + _cli_pkg_build_pkg_options_map_["-p"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::patch_ >; + _cli_pkg_build_pkg_options_map_["--deorphan"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::deorphan_ >; + _cli_pkg_build_pkg_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::immediate_ >; + _cli_pkg_build_pkg_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::immediate_ >; + _cli_pkg_build_pkg_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::recursive_ >; + _cli_pkg_build_pkg_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::recursive_ >; + _cli_pkg_build_pkg_options_map_["--upgrade-immediate"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::upgrade_immediate_ >; + _cli_pkg_build_pkg_options_map_["--patch-immediate"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::patch_immediate_ >; + _cli_pkg_build_pkg_options_map_["--deorphan-immediate"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::deorphan_immediate_ >; + _cli_pkg_build_pkg_options_map_["--upgrade-recursive"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::upgrade_recursive_ >; + _cli_pkg_build_pkg_options_map_["--patch-recursive"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::patch_recursive_ >; + _cli_pkg_build_pkg_options_map_["--deorphan-recursive"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::deorphan_recursive_ >; + _cli_pkg_build_pkg_options_map_["--dependency"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::dependency_ >; + _cli_pkg_build_pkg_options_map_["--keep-out"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::keep_out_ >; + _cli_pkg_build_pkg_options_map_["--disfigure"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::disfigure_ >; + _cli_pkg_build_pkg_options_map_["--checkout-root"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, dir_path, &pkg_build_pkg_options::checkout_root_, + &pkg_build_pkg_options::checkout_root_specified_ >; + _cli_pkg_build_pkg_options_map_["--checkout-purge"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, &pkg_build_pkg_options::checkout_purge_ >; + _cli_pkg_build_pkg_options_map_["--config-name"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, strings, &pkg_build_pkg_options::config_name_, + &pkg_build_pkg_options::config_name_specified_ >; + _cli_pkg_build_pkg_options_map_["--config-id"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, vector<uint64_t>, &pkg_build_pkg_options::config_id_, + &pkg_build_pkg_options::config_id_specified_ >; + _cli_pkg_build_pkg_options_map_["--config-uuid"] = + &::bpkg::cli::thunk< pkg_build_pkg_options, vector<uuid>, &pkg_build_pkg_options::config_uuid_, + &pkg_build_pkg_options::config_uuid_specified_ >; + } + }; + + static _cli_pkg_build_pkg_options_map_init _cli_pkg_build_pkg_options_map_init_; + + bool pkg_build_pkg_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_build_pkg_options_map::const_iterator i (_cli_pkg_build_pkg_options_map_.find (o)); + + if (i != _cli_pkg_build_pkg_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + return false; + } + + bool pkg_build_pkg_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; + } + + // pkg_build_options + // + + pkg_build_options:: + pkg_build_options () + : yes_ (), + for__ (), + for__specified_ (false), + keep_unused_ (), + update_dependent_ (), + leave_dependent_ (), + configure_only_ (), + print_only_ (), + plan_ (), + plan_specified_ (false), + no_fetch_ (), + fetch_shallow_ (), + mask_repository_ (), + mask_repository_specified_ (false), + mask_repository_uuid_ (), + mask_repository_uuid_specified_ (false), + no_refinement_ (), + no_move_ (), + noop_exit_ (), + noop_exit_specified_ (false), + rebuild_checksum_ (), + rebuild_checksum_specified_ (false), + no_private_config_ (), + no_private_config_specified_ (false), + sys_no_query_ (), + sys_install_ (), + sys_no_fetch_ (), + sys_no_stub_ (), + sys_yes_ (), + sys_sudo_ ("sudo"), + sys_sudo_specified_ (false), + sys_distribution_ (), + sys_distribution_specified_ (false), + sys_architecture_ (), + sys_architecture_specified_ (false), + directory_ (), + directory_specified_ (false) + { + } + + bool pkg_build_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 pkg_build_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 pkg_build_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 pkg_build_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 pkg_build_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 pkg_build_options:: + merge (const pkg_build_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + // pkg_build_pkg_options base + // + ::bpkg::pkg_build_pkg_options::merge (a); + + if (a.yes_) + { + ::bpkg::cli::parser< bool>::merge ( + this->yes_, a.yes_); + } + + if (a.for__specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->for__, a.for__); + this->for__specified_ = true; + } + + if (a.keep_unused_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_unused_, a.keep_unused_); + } + + if (a.update_dependent_) + { + ::bpkg::cli::parser< bool>::merge ( + this->update_dependent_, a.update_dependent_); + } + + if (a.leave_dependent_) + { + ::bpkg::cli::parser< bool>::merge ( + this->leave_dependent_, a.leave_dependent_); + } + + if (a.configure_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->configure_only_, a.configure_only_); + } + + if (a.print_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->print_only_, a.print_only_); + } + + if (a.plan_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->plan_, a.plan_); + this->plan_specified_ = true; + } + + if (a.no_fetch_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_fetch_, a.no_fetch_); + } + + if (a.fetch_shallow_) + { + ::bpkg::cli::parser< bool>::merge ( + this->fetch_shallow_, a.fetch_shallow_); + } + + if (a.mask_repository_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->mask_repository_, a.mask_repository_); + this->mask_repository_specified_ = true; + } + + if (a.mask_repository_uuid_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->mask_repository_uuid_, a.mask_repository_uuid_); + this->mask_repository_uuid_specified_ = true; + } + + if (a.no_refinement_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_refinement_, a.no_refinement_); + } + + if (a.no_move_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_move_, a.no_move_); + } + + if (a.noop_exit_specified_) + { + ::bpkg::cli::parser< uint16_t>::merge ( + this->noop_exit_, a.noop_exit_); + this->noop_exit_specified_ = true; + } + + if (a.rebuild_checksum_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->rebuild_checksum_, a.rebuild_checksum_); + this->rebuild_checksum_specified_ = true; + } + + if (a.no_private_config_specified_) + { + ::bpkg::cli::parser< uint16_t>::merge ( + this->no_private_config_, a.no_private_config_); + this->no_private_config_specified_ = true; + } + + if (a.sys_no_query_) + { + ::bpkg::cli::parser< bool>::merge ( + this->sys_no_query_, a.sys_no_query_); + } + + if (a.sys_install_) + { + ::bpkg::cli::parser< bool>::merge ( + this->sys_install_, a.sys_install_); + } + + if (a.sys_no_fetch_) + { + ::bpkg::cli::parser< bool>::merge ( + this->sys_no_fetch_, a.sys_no_fetch_); + } + + if (a.sys_no_stub_) + { + ::bpkg::cli::parser< bool>::merge ( + this->sys_no_stub_, a.sys_no_stub_); + } + + if (a.sys_yes_) + { + ::bpkg::cli::parser< bool>::merge ( + this->sys_yes_, a.sys_yes_); + } + + if (a.sys_sudo_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->sys_sudo_, a.sys_sudo_); + this->sys_sudo_specified_ = true; + } + + if (a.sys_distribution_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->sys_distribution_, a.sys_distribution_); + this->sys_distribution_specified_ = true; + } + + if (a.sys_architecture_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->sys_architecture_, a.sys_architecture_); + this->sys_architecture_specified_ = true; + } + + if (a.directory_specified_) + { + ::bpkg::cli::parser< dir_paths>::merge ( + this->directory_, a.directory_); + this->directory_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_build_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[1mPKG-BUILD GLOBAL OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--yes\033[0m|\033[1m-y\033[0m Assume the answer to all prompts is \033[1myes\033[0m. Note that" << ::std::endl + << " this excludes the system package manager prompts; see" << ::std::endl + << " \033[1m--sys-yes\033[0m for details." << ::std::endl; + + os << std::endl + << "\033[1m--for\033[0m|\033[1m-f\033[0m \033[4moperation\033[0m Instead of the default \033[1mupdate\033[0m build system operation," << ::std::endl + << " perform the \033[1mupdate-for-\033[0m\033[4moperation\033[0m variant where" << ::std::endl + << " \033[4moperation\033[0m is normally \033[1minstall\033[0m or \033[1mtest\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--keep-unused\033[0m|\033[1m-K\033[0m Don't drop dependency packages that were" << ::std::endl + << " automatically built but will no longer be used." << ::std::endl; + + os << std::endl + << "\033[1m--update-dependent\033[0m|\033[1m-U\033[0m Update without confirmation dependent packages that" << ::std::endl + << " are reconfigured due to their dependencies being" << ::std::endl + << " upgraded or downgraded." << ::std::endl; + + os << std::endl + << "\033[1m--leave-dependent\033[0m|\033[1m-L\033[0m Don't offer to update dependent packages that are" << ::std::endl + << " reconfigured due to their dependencies being upgraded" << ::std::endl + << " or downgraded." << ::std::endl; + + os << std::endl + << "\033[1m--configure-only\033[0m|\033[1m-c\033[0m Configure all the packages but don't update." << ::std::endl; + + os << std::endl + << "\033[1m--print-only\033[0m Print to \033[1mstdout\033[0m what would be done without actually" << ::std::endl + << " doing anything." << ::std::endl; + + os << std::endl + << "\033[1m--plan\033[0m \033[4mheader\033[0m Print the plan (even if \033[1m--yes\033[0m is specified) and start" << ::std::endl + << " it with the \033[4mheader\033[0m line (unless it is empty)." << ::std::endl; + + os << std::endl + << "\033[1m--no-fetch\033[0m Don't fetch repositories specified as part of the" << ::std::endl + << " build command." << ::std::endl; + + os << std::endl + << "\033[1m--fetch-shallow\033[0m Don't re-fetch complement and prerequisite" << ::std::endl + << " repositories of repositories specified as part of the" << ::std::endl + << " build command. Refer to the \033[1m--shallow\033[0m option in" << ::std::endl + << " \033[1mbpkg-rep-fetch(1)\033[0m for details." << ::std::endl; + + os << std::endl + << "\033[1m--mask-repository\033[0m \033[4mrep\033[0m For the duration of the command execution pretend the" << ::std::endl + << " specified repository was removed as if by performing" << ::std::endl + << " the \033[1mrep-remove\033[0m command. The repository can be" << ::std::endl + << " specified either as a repository name or as a" << ::std::endl + << " repository location (URL or a directory path). Note" << ::std::endl + << " that the repository's complement and prerequisite" << ::std::endl + << " repositories are also considered masked, recursively," << ::std::endl + << " unless they are complements and/or prerequisites of" << ::std::endl + << " other unmasked repositories. Repeat this option to" << ::std::endl + << " mask multiple repositories." << ::std::endl; + + os << std::endl + << "\033[1m--mask-repository-uuid\033[0m \033[4mv\033[0m For the duration of the command execution pretend the" << ::std::endl + << " specified repository was removed from the specified" << ::std::endl + << " configuration. Similar to \033[1m--mask-repository\033[0m but only" << ::std::endl + << " masks the repository in a single configuration. The" << ::std::endl + << " option value is a key-value pair in the form:" << ::std::endl + << ::std::endl + << " \033[4mconfig-uuid\033[0m\033[1m=\033[0m\033[4mrep\033[0m\033[0m" << ::std::endl + << ::std::endl + << " Repeat this option to mask multiple repositories." << ::std::endl; + + os << std::endl + << "\033[1m--no-refinement\033[0m Don't try to refine the configuration by offering to" << ::std::endl + << " drop any unused dependencies that were potentially" << ::std::endl + << " left behind on the previous \033[1mpkg-build\033[0m or \033[1mpkg-drop\033[0m" << ::std::endl + << " command execution if the command is otherwise a noop" << ::std::endl + << " (performs no new package builds, upgrades, etc)." << ::std::endl; + + os << std::endl + << "\033[1m--no-move\033[0m Don't move dependency packages between" << ::std::endl + << " configurations. In this mode the \033[1m--config-*\033[0m options" << ::std::endl + << " specify packages' current rather than new locations." << ::std::endl; + + os << std::endl + << "\033[1m--noop-exit\033[0m \033[4mcode\033[0m Exit with the specified error code if the command" << ::std::endl + << " execution is a noop (performs no new package builds," << ::std::endl + << " upgrades, etc)." << ::std::endl; + + os << std::endl + << "\033[1m--rebuild-checksum\033[0m \033[4msum\033[0m Hash the names, versions, and configurations of all" << ::std::endl + << " the packages that would be built. If the resulting" << ::std::endl + << " checksum matches the specified, then exit without" << ::std::endl + << " building anything (potentially with a special error" << ::std::endl + << " code specified with the \033[1m--noop-exit\033[0m option)." << ::std::endl + << " Otherwise, proceed to build as normal. In both cases," << ::std::endl + << " print the resulting checksum to \033[1mstdout\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--no-private-config\033[0m \033[4mcode\033[0m If no configuration of a suitable type is linked to" << ::std::endl + << " build a build-time dependency, instead of" << ::std::endl + << " automatically creating a private configuration of" << ::std::endl + << " this type, exit with the specified error code" << ::std::endl + << " printing to \033[1mstdout\033[0m the dependency chain starting from" << ::std::endl + << " the build-time dependency (together with its" << ::std::endl + << " constraint, if present) and ending with the top-level" << ::std::endl + << " dependent (together with their configuration" << ::std::endl + << " directories), one entry per line. For example:" << ::std::endl + << ::std::endl + << " yacc ^1.0.0" << ::std::endl + << " libbar/1.0.0 /path/to/libbar/cfg/" << ::std::endl + << " libfoo/1.0.0 /path/to/libfoo/cfg/" << ::std::endl + << ::std::endl + << " See \033[1mbpkg-cfg-create(1)\033[0m for details on linked" << ::std::endl + << " configurations." << ::std::endl; + + os << std::endl + << "\033[1m--sys-no-query\033[0m Do not query the system package manager for the" << ::std::endl + << " installed versions of packages specified with the" << ::std::endl + << " \033[1msys\033[0m scheme." << ::std::endl; + + os << std::endl + << "\033[1m--sys-install\033[0m Instruct the system package manager to install" << ::std::endl + << " available versions of packages specified with the" << ::std::endl + << " \033[1msys\033[0m scheme that are not already installed. See also" << ::std::endl + << " the \033[1m--sys-no-fetch\033[0m, \033[1m--sys-yes\033[0m, and \033[1m--sys-sudo\033[0m" << ::std::endl + << " options." << ::std::endl; + + os << std::endl + << "\033[1m--sys-no-fetch\033[0m Do not fetch the system package manager metadata" << ::std::endl + << " before querying for available versions of packages" << ::std::endl + << " specified with the \033[1msys\033[0m scheme. This option only makes" << ::std::endl + << " sense together with \033[1m--sys-install\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--sys-no-stub\033[0m Do no require a stub for packages specified with the" << ::std::endl + << " \033[1msys\033[0m scheme. Note that this option has effect only if" << ::std::endl + << " the system package manager interactions are supported" << ::std::endl + << " and not disabled." << ::std::endl; + + os << std::endl + << "\033[1m--sys-yes\033[0m Assume the answer to the system package manager" << ::std::endl + << " prompts is \033[1myes\033[0m. Note that system package manager" << ::std::endl + << " interactions may break your system and you should" << ::std::endl + << " normally only use this option on throw-away setups" << ::std::endl + << " (test virtual machines, etc)." << ::std::endl; + + os << std::endl + << "\033[1m--sys-sudo\033[0m \033[4mprog\033[0m The \033[1msudo\033[0m program to use for system package manager" << ::std::endl + << " interactions that normally require administrative" << ::std::endl + << " privileges (fetch package metadata, install packages," << ::std::endl + << " etc). If unspecified, \033[1msudo\033[0m is used by default. Pass" << ::std::endl + << " empty or the special \033[1mfalse\033[0m value to disable the use" << ::std::endl + << " of the \033[1msudo\033[0m program. Note that the \033[1msudo\033[0m program is" << ::std::endl + << " normally only needed if the system package" << ::std::endl + << " installation is enabled with the \033[1m--sys-install\033[0m" << ::std::endl + << " option." << ::std::endl; + + os << std::endl + << "\033[1m--sys-distribution\033[0m \033[4mname\033[0m Alternative system/distribution package manager to" << ::std::endl + << " interact with. The valid \033[4mname\033[0m values are \033[1mdebian\033[0m" << ::std::endl + << " (Debian and alike, such as Ubuntu, etc) and \033[1mfedora\033[0m" << ::std::endl + << " (Fedora and alike, such as RHEL, CentOS, etc). Note" << ::std::endl + << " that some package managers may only be supported when" << ::std::endl + << " running on certain host operating systems." << ::std::endl; + + os << std::endl + << "\033[1m--sys-architecture\033[0m \033[4mname\033[0m Alternative architecture to use when interacting with" << ::std::endl + << " the system package manager. The valid \033[4mname\033[0m values are" << ::std::endl + << " system/distribution package manager-specific. If" << ::std::endl + << " unspecified, the host architecture is used." << ::std::endl; + + os << std::endl + << "\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mdir\033[0m Assume current configuration is in \033[4mdir\033[0m rather than in" << ::std::endl + << " the current working directory. Repeat this option to" << ::std::endl + << " specify multiple current configurations. If multiple" << ::std::endl + << " configurations are specified, they need not belong to" << ::std::endl + << " the same linked configuration cluster." << ::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 (*) (pkg_build_options&, ::bpkg::cli::scanner&)> + _cli_pkg_build_options_map; + + static _cli_pkg_build_options_map _cli_pkg_build_options_map_; + + struct _cli_pkg_build_options_map_init + { + _cli_pkg_build_options_map_init () + { + _cli_pkg_build_options_map_["--yes"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::yes_ >; + _cli_pkg_build_options_map_["-y"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::yes_ >; + _cli_pkg_build_options_map_["--for"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::for__, + &pkg_build_options::for__specified_ >; + _cli_pkg_build_options_map_["-f"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::for__, + &pkg_build_options::for__specified_ >; + _cli_pkg_build_options_map_["--keep-unused"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::keep_unused_ >; + _cli_pkg_build_options_map_["-K"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::keep_unused_ >; + _cli_pkg_build_options_map_["--update-dependent"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::update_dependent_ >; + _cli_pkg_build_options_map_["-U"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::update_dependent_ >; + _cli_pkg_build_options_map_["--leave-dependent"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::leave_dependent_ >; + _cli_pkg_build_options_map_["-L"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::leave_dependent_ >; + _cli_pkg_build_options_map_["--configure-only"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::configure_only_ >; + _cli_pkg_build_options_map_["-c"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::configure_only_ >; + _cli_pkg_build_options_map_["--print-only"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::print_only_ >; + _cli_pkg_build_options_map_["--plan"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::plan_, + &pkg_build_options::plan_specified_ >; + _cli_pkg_build_options_map_["--no-fetch"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::no_fetch_ >; + _cli_pkg_build_options_map_["--fetch-shallow"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::fetch_shallow_ >; + _cli_pkg_build_options_map_["--mask-repository"] = + &::bpkg::cli::thunk< pkg_build_options, strings, &pkg_build_options::mask_repository_, + &pkg_build_options::mask_repository_specified_ >; + _cli_pkg_build_options_map_["--mask-repository-uuid"] = + &::bpkg::cli::thunk< pkg_build_options, strings, &pkg_build_options::mask_repository_uuid_, + &pkg_build_options::mask_repository_uuid_specified_ >; + _cli_pkg_build_options_map_["--no-refinement"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::no_refinement_ >; + _cli_pkg_build_options_map_["--no-move"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::no_move_ >; + _cli_pkg_build_options_map_["--noop-exit"] = + &::bpkg::cli::thunk< pkg_build_options, uint16_t, &pkg_build_options::noop_exit_, + &pkg_build_options::noop_exit_specified_ >; + _cli_pkg_build_options_map_["--rebuild-checksum"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::rebuild_checksum_, + &pkg_build_options::rebuild_checksum_specified_ >; + _cli_pkg_build_options_map_["--no-private-config"] = + &::bpkg::cli::thunk< pkg_build_options, uint16_t, &pkg_build_options::no_private_config_, + &pkg_build_options::no_private_config_specified_ >; + _cli_pkg_build_options_map_["--sys-no-query"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::sys_no_query_ >; + _cli_pkg_build_options_map_["--sys-install"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::sys_install_ >; + _cli_pkg_build_options_map_["--sys-no-fetch"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::sys_no_fetch_ >; + _cli_pkg_build_options_map_["--sys-no-stub"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::sys_no_stub_ >; + _cli_pkg_build_options_map_["--sys-yes"] = + &::bpkg::cli::thunk< pkg_build_options, &pkg_build_options::sys_yes_ >; + _cli_pkg_build_options_map_["--sys-sudo"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::sys_sudo_, + &pkg_build_options::sys_sudo_specified_ >; + _cli_pkg_build_options_map_["--sys-distribution"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::sys_distribution_, + &pkg_build_options::sys_distribution_specified_ >; + _cli_pkg_build_options_map_["--sys-architecture"] = + &::bpkg::cli::thunk< pkg_build_options, string, &pkg_build_options::sys_architecture_, + &pkg_build_options::sys_architecture_specified_ >; + _cli_pkg_build_options_map_["--directory"] = + &::bpkg::cli::thunk< pkg_build_options, dir_paths, &pkg_build_options::directory_, + &pkg_build_options::directory_specified_ >; + _cli_pkg_build_options_map_["-d"] = + &::bpkg::cli::thunk< pkg_build_options, dir_paths, &pkg_build_options::directory_, + &pkg_build_options::directory_specified_ >; + } + }; + + static _cli_pkg_build_options_map_init _cli_pkg_build_options_map_init_; + + bool pkg_build_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_build_options_map::const_iterator i (_cli_pkg_build_options_map_.find (o)); + + if (i != _cli_pkg_build_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + // pkg_build_pkg_options base + // + if (::bpkg::pkg_build_pkg_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_build_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_pkg_build_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 pkg-build\033[0m|\033[1mbuild\033[0m [\033[4moptions\033[0m] [\033[1m--upgrade\033[0m|\033[1m-u\033[0m | \033[1m--patch\033[0m|\033[1m-p\033[0m]" << ::std::endl + << " [\033[4mcfg-var\033[0m... \033[1m--\033[0m] \033[4mpkg-spec\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-build\033[0m|\033[1mbuild\033[0m [\033[4moptions\033[0m] \033[1m--upgrade\033[0m|\033[1m-u\033[0m | \033[1m--patch\033[0m|\033[1m-p\033[0m" << ::std::endl + << " [\033[4mcfg-var\033[0m... \033[1m--\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "\033[4mpkg-spec\033[0m = [\033[4mflags\033[0m](([\033[4mscheme\033[0m\033[1m:\033[0m]\033[4mpkg\033[0m[\033[4mver-spec\033[0m])\033[1m,\033[0m...[\033[1m@\033[0m\033[4mrep-loc\033[0m] | " << ::std::endl + << " [\033[1m@\033[0m]\033[4mrep-loc\033[0m | " << ::std::endl + << " \033[4mfile\033[0m | " << ::std::endl + << " \033[4mdir\033[0m\033[1m/\033[0m)" << ::std::endl + << "\033[4mflags\033[0m = \033[1m?\033[0m" << ::std::endl + << "\033[4mscheme\033[0m = \033[1msys\033[0m" << ::std::endl + << "\033[4mver-spec\033[0m = \033[1m/\033[0m\033[4mversion\033[0m | \033[4mversion-constraint\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-build\033[0m command builds one or more packages including all their" << ::std::endl + << "dependencies. Besides building new packages, this command is also used to" << ::std::endl + << "upgrade or downgrade packages that are already present in the configuration." << ::std::endl + << "And unless the \033[1m--keep-unused\033[0m|\033[1m-K\033[0m\033[0m option is specified, \033[1mpkg-build\033[0m will also drop" << ::std::endl + << "dependency packages that would otherwise no longer be used." << ::std::endl + << ::std::endl + << "The first form (one or more packages are specified) builds new or upgrades (by" << ::std::endl + << "default or if \033[1m--upgrade\033[0m is specified) or patches (if \033[1m--patch\033[0m is specified) the" << ::std::endl + << "specified packages. The second form (no arguments but either \033[1m--upgrade\033[0m or" << ::std::endl + << "\033[1m--patch\033[0m is specified) upgrades or patches all the held packages in the" << ::std::endl + << "configuration (see below for details on held package)." << ::std::endl + << ::std::endl + << "In both forms specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m option causes" << ::std::endl + << "\033[1mpkg-build\033[0m to also upgrade or patch the immediate or all dependencies of the" << ::std::endl + << "specified (first form) or held (second form) packages, respectively. Note also" << ::std::endl + << "that in the first form these options can only be specified with an explicit" << ::std::endl + << "\033[1m--upgrade\033[0m or \033[1m--patch\033[0m." << ::std::endl + << ::std::endl + << "Each package can be specified as just the name (\033[4mpkg\033[0m) with optional version" << ::std::endl + << "specification (\033[4mver-spec\033[0m), in which case the source code for the package will be" << ::std::endl + << "automatically fetched from one of the configured repositories. See the" << ::std::endl + << "\033[1mbpkg-rep-add(1)\033[0m and \033[1mbpkg-rep-fetch(1)\033[0m commands for more information on package" << ::std::endl + << "repositories. The version specification (\033[4mver-spec\033[0m) can be either the exact" << ::std::endl + << "version in the \033[1m/\033[0m\033[4mversion\033[0m\033[0m form or the version constraint as described in Package" << ::std::endl + << "Version Constraint (bpkg#package-version-constraint). If \033[4mver-spec\033[0m is not" << ::std::endl + << "specified, then the latest available version will be built. To downgrade, the" << ::std::endl + << "desired version must be specified explicitly. For example:" << ::std::endl + << ::std::endl + << "bpkg build foo libfoo/1.2.3 \"bar < 2.0.0\"" << ::std::endl + << ::std::endl + << "Alternatively, the package repository location (\033[4mrep-loc\033[0m) can be specified as" << ::std::endl + << "part of the build command. In this case, if \033[4mver-spec\033[0m is not specified, then the" << ::std::endl + << "latest available from this repository version will be built. For example:" << ::std::endl + << ::std::endl + << "bpkg build foo,libfoo/1.2.3@https://git.example.org/foo.git#master" << ::std::endl + << ::std::endl + << "If only the location is specified, then the latest versions of all the packages" << ::std::endl + << "available directly from this repository will be built (note that this does not" << ::std::endl + << "include packages available from complement repositories). The \033[1m@\033[0m delimiter can" << ::std::endl + << "be omitted if the location is a URL. For example:" << ::std::endl + << ::std::endl + << "bpkg build https://git.example.org/foo.git#master" << ::std::endl + << "bpkg build @/path/to/repository/" << ::std::endl + << ::std::endl + << "A package name (\033[4mpkg\033[0m) can be prefixed with a package scheme (\033[4mscheme\033[0m). Currently" << ::std::endl + << "the only recognized scheme is \033[1msys\033[0m which instructs \033[1mpkg-build\033[0m to configure the" << ::std::endl + << "package as available from the system rather than building it from source." << ::std::endl + << ::std::endl + << "The system package version (\033[4mver-spec\033[0m) may not be a version constraint but may" << ::std::endl + << "be the special '\033[1m/*\033[0m' value, which indicates that the version should be" << ::std::endl + << "considered unknown but satisfying any version constraint. If unspecified, then" << ::std::endl + << "\033[1mpkg-build\033[0m will attempt to query the system package manager for the installed" << ::std::endl + << "version unless the system package manager is unsupported or this functionality" << ::std::endl + << "is disabled with \033[1m--sys-no-query\033[0m, in which case the '\033[1m/*\033[0m' \033[4mver-spec\033[0m is assumed. If" << ::std::endl + << "the system package manager is supported, then the automatic installation of an" << ::std::endl + << "available package can be requested with the \033[1m--sys-install\033[0m option. Note that if" << ::std::endl + << "the version is not explicitly specified, then at least a stub package must be" << ::std::endl + << "available from one of the repositories unless the \033[1m--sys-no-stub\033[0m option is" << ::std::endl + << "specified." << ::std::endl + << ::std::endl + << "Finally, a package can be specified as either the path to the package archive" << ::std::endl + << "(\033[4mfile\033[0m) or to the package directory (\033[4mdir\033[0m\033[1m/\033[0m; note that it must end with a" << ::std::endl + << "directory separator). See the \033[1mbpkg-pkg-fetch(1)\033[0m and \033[1mbpkg-pkg-unpack(1)\033[0m commands" << ::std::endl + << "for more information on the semantics of specifying the package as an archive" << ::std::endl + << "or a directory." << ::std::endl + << ::std::endl + << "Additional configuration variables (\033[4mcfg-var\033[0m), if any, should be specified" << ::std::endl + << "before packages (\033[4mpkg-spec\033[0m) and should be separated with \033[1m--\033[0m. Such variables are" << ::std::endl + << "effective only when configuring and only for packages that were explicitly" << ::std::endl + << "specified on the command line (unless global overrides). They can also be" << ::std::endl + << "specified to only apply to specific packages using the argument grouping" << ::std::endl + << "mechanism discussed below. See \033[1mbpkg-pkg-configure(1)\033[0m for more information on" << ::std::endl + << "configuration variables." << ::std::endl + << ::std::endl + << "By default a package that is specified explicitly on the command line is built" << ::std::endl + << "to \033[4mhold\033[0m: it will not be considered for automatic removal if it no longer has" << ::std::endl + << "any dependents. Only versions from repositories that were added to the" << ::std::endl + << "configuration (\033[1mbpkg-rep-add(1)\033[0m) are considered as available for build to hold." << ::std::endl + << ::std::endl + << "Alternatively, a package can be built (or, more commonly, upgraded/downgraded)" << ::std::endl + << "as a \033[4mdependency\033[0m by specifying the \033[1m?\033[0m flag (\033[4mflags\033[0m) or the \033[1m--dependency\033[0m option." << ::std::endl + << "Such a package will only be added to the configuration if it actually has any" << ::std::endl + << "dependents and once no longer used, it will be automatically dropped. Only" << ::std::endl + << "versions from prerequisite repositories of dependent packages are considered as" << ::std::endl + << "available for build as a dependency." << ::std::endl + << ::std::endl + << "Packages (both built to hold and as dependencies) that are specified with an" << ::std::endl + << "explicit package version (\033[4mver-spec\033[0m) or as an archive or directory, will have" << ::std::endl + << "their versions held, that is, they will not be automatically upgraded." << ::std::endl + << ::std::endl + << "As an illustration, let's assume in the following example that the stable" << ::std::endl + << "repository contains packages \033[1mfoo\033[0m \033[1m1.0.0\033[0m as well as \033[1mlibfoo\033[0m \033[1m1.0.0\033[0m and \033[1m1.1.0\033[0m while" << ::std::endl + << "testing -- \033[1mlibfoo\033[0m \033[1m2.0.0\033[0m, that testing is complemented by stable, and that \033[1mfoo\033[0m" << ::std::endl + << "depends on \033[1mlibfoo >= 1.0.0\033[0m:" << ::std::endl + << ::std::endl + << "bpkg fetch https://example.org/1/testing" << ::std::endl + << ::std::endl + << "bpkg build foo # build foo 1.0.0 to hold" << ::std::endl + << " # build libfoo 1.1.0 as dependency" << ::std::endl + << ::std::endl + << "bpkg build ?libfoo/1.0.0 # downgrade libfoo 1.0.0 as dependency," << ::std::endl + << " # also hold version 1.0.0" << ::std::endl + << ::std::endl + << "bpkg build ?libfoo/2.0.0 # error: 2.0.0 unavailable in dependent's" << ::std::endl + << " # (foo) repository (stable)" << ::std::endl + << ::std::endl + << "bpkg build libfoo/2.0.0 # upgrade libfoo 2.0.0 to hold," << ::std::endl + << " # also hold version 2.0.0" << ::std::endl + << ::std::endl + << "A package can be built in one of the linked configurations instead of the" << ::std::endl + << "current (or host/build system module, for build-time dependencies)" << ::std::endl + << "configuration by specifying one of the \033[1m--config-*\033[0m options (see" << ::std::endl + << "\033[1mbpkg-cfg-create(1)\033[0m for background on linked configurations). For example:" << ::std::endl + << ::std::endl + << "bpkg build foo { --config-name=alt-host }+ ?bison" << ::std::endl; + + p = ::bpkg::pkg_build_pkg_options::print_usage (os, ::bpkg::cli::usage_para::text); + + p = ::bpkg::pkg_build_options::print_usage (os, p); + + 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[1mpkg-build\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-pkg-build.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-build\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/pkg-build-options.hxx b/bpkg/pkg-build-options.hxx new file mode 100644 index 0000000..7442120 --- /dev/null +++ b/bpkg/pkg-build-options.hxx @@ -0,0 +1,738 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_BUILD_OPTIONS_HXX +#define BPKG_PKG_BUILD_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class pkg_build_pkg_options + { + public: + pkg_build_pkg_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 pkg_build_pkg_options&); + + // Option accessors and modifiers. + // + const bool& + upgrade () const; + + bool& + upgrade (); + + void + upgrade (const bool&); + + const bool& + patch () const; + + bool& + patch (); + + void + patch (const bool&); + + const bool& + deorphan () const; + + bool& + deorphan (); + + void + deorphan (const bool&); + + const bool& + immediate () const; + + bool& + immediate (); + + void + immediate (const bool&); + + const bool& + recursive () const; + + bool& + recursive (); + + void + recursive (const bool&); + + const bool& + upgrade_immediate () const; + + bool& + upgrade_immediate (); + + void + upgrade_immediate (const bool&); + + const bool& + patch_immediate () const; + + bool& + patch_immediate (); + + void + patch_immediate (const bool&); + + const bool& + deorphan_immediate () const; + + bool& + deorphan_immediate (); + + void + deorphan_immediate (const bool&); + + const bool& + upgrade_recursive () const; + + bool& + upgrade_recursive (); + + void + upgrade_recursive (const bool&); + + const bool& + patch_recursive () const; + + bool& + patch_recursive (); + + void + patch_recursive (const bool&); + + const bool& + deorphan_recursive () const; + + bool& + deorphan_recursive (); + + void + deorphan_recursive (const bool&); + + const bool& + dependency () const; + + bool& + dependency (); + + void + dependency (const bool&); + + const bool& + keep_out () const; + + bool& + keep_out (); + + void + keep_out (const bool&); + + const bool& + disfigure () const; + + bool& + disfigure (); + + void + disfigure (const bool&); + + const dir_path& + checkout_root () const; + + dir_path& + checkout_root (); + + void + checkout_root (const dir_path&); + + bool + checkout_root_specified () const; + + void + checkout_root_specified (bool); + + const bool& + checkout_purge () const; + + bool& + checkout_purge (); + + void + checkout_purge (const bool&); + + const strings& + config_name () const; + + strings& + config_name (); + + void + config_name (const strings&); + + bool + config_name_specified () const; + + void + config_name_specified (bool); + + const vector<uint64_t>& + config_id () const; + + vector<uint64_t>& + config_id (); + + void + config_id (const vector<uint64_t>&); + + bool + config_id_specified () const; + + void + config_id_specified (bool); + + const vector<uuid>& + config_uuid () const; + + vector<uuid>& + config_uuid (); + + void + config_uuid (const vector<uuid>&); + + bool + config_uuid_specified () const; + + void + config_uuid_specified (bool); + + // 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 upgrade_; + bool patch_; + bool deorphan_; + bool immediate_; + bool recursive_; + bool upgrade_immediate_; + bool patch_immediate_; + bool deorphan_immediate_; + bool upgrade_recursive_; + bool patch_recursive_; + bool deorphan_recursive_; + bool dependency_; + bool keep_out_; + bool disfigure_; + dir_path checkout_root_; + bool checkout_root_specified_; + bool checkout_purge_; + strings config_name_; + bool config_name_specified_; + vector<uint64_t> config_id_; + bool config_id_specified_; + vector<uuid> config_uuid_; + bool config_uuid_specified_; + }; + + class pkg_build_options: public ::bpkg::common_options, + public ::bpkg::pkg_build_pkg_options + { + public: + pkg_build_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 pkg_build_options&); + + // Option accessors and modifiers. + // + const bool& + yes () const; + + bool& + yes (); + + void + yes (const bool&); + + const string& + for_ () const; + + string& + for_ (); + + void + for_ (const string&); + + bool + for__specified () const; + + void + for__specified (bool); + + const bool& + keep_unused () const; + + bool& + keep_unused (); + + void + keep_unused (const bool&); + + const bool& + update_dependent () const; + + bool& + update_dependent (); + + void + update_dependent (const bool&); + + const bool& + leave_dependent () const; + + bool& + leave_dependent (); + + void + leave_dependent (const bool&); + + const bool& + configure_only () const; + + bool& + configure_only (); + + void + configure_only (const bool&); + + const bool& + print_only () const; + + bool& + print_only (); + + void + print_only (const bool&); + + const string& + plan () const; + + string& + plan (); + + void + plan (const string&); + + bool + plan_specified () const; + + void + plan_specified (bool); + + const bool& + no_fetch () const; + + bool& + no_fetch (); + + void + no_fetch (const bool&); + + const bool& + fetch_shallow () const; + + bool& + fetch_shallow (); + + void + fetch_shallow (const bool&); + + const strings& + mask_repository () const; + + strings& + mask_repository (); + + void + mask_repository (const strings&); + + bool + mask_repository_specified () const; + + void + mask_repository_specified (bool); + + const strings& + mask_repository_uuid () const; + + strings& + mask_repository_uuid (); + + void + mask_repository_uuid (const strings&); + + bool + mask_repository_uuid_specified () const; + + void + mask_repository_uuid_specified (bool); + + const bool& + no_refinement () const; + + bool& + no_refinement (); + + void + no_refinement (const bool&); + + const bool& + no_move () const; + + bool& + no_move (); + + void + no_move (const bool&); + + const uint16_t& + noop_exit () const; + + uint16_t& + noop_exit (); + + void + noop_exit (const uint16_t&); + + bool + noop_exit_specified () const; + + void + noop_exit_specified (bool); + + const string& + rebuild_checksum () const; + + string& + rebuild_checksum (); + + void + rebuild_checksum (const string&); + + bool + rebuild_checksum_specified () const; + + void + rebuild_checksum_specified (bool); + + const uint16_t& + no_private_config () const; + + uint16_t& + no_private_config (); + + void + no_private_config (const uint16_t&); + + bool + no_private_config_specified () const; + + void + no_private_config_specified (bool); + + const bool& + sys_no_query () const; + + bool& + sys_no_query (); + + void + sys_no_query (const bool&); + + const bool& + sys_install () const; + + bool& + sys_install (); + + void + sys_install (const bool&); + + const bool& + sys_no_fetch () const; + + bool& + sys_no_fetch (); + + void + sys_no_fetch (const bool&); + + const bool& + sys_no_stub () const; + + bool& + sys_no_stub (); + + void + sys_no_stub (const bool&); + + const bool& + sys_yes () const; + + bool& + sys_yes (); + + void + sys_yes (const bool&); + + const string& + sys_sudo () const; + + string& + sys_sudo (); + + void + sys_sudo (const string&); + + bool + sys_sudo_specified () const; + + void + sys_sudo_specified (bool); + + const string& + sys_distribution () const; + + string& + sys_distribution (); + + void + sys_distribution (const string&); + + bool + sys_distribution_specified () const; + + void + sys_distribution_specified (bool); + + const string& + sys_architecture () const; + + string& + sys_architecture (); + + void + sys_architecture (const string&); + + bool + sys_architecture_specified () const; + + void + sys_architecture_specified (bool); + + const dir_paths& + directory () const; + + dir_paths& + directory (); + + void + directory (const dir_paths&); + + bool + directory_specified () const; + + void + directory_specified (bool); + + // 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 yes_; + string for__; + bool for__specified_; + bool keep_unused_; + bool update_dependent_; + bool leave_dependent_; + bool configure_only_; + bool print_only_; + string plan_; + bool plan_specified_; + bool no_fetch_; + bool fetch_shallow_; + strings mask_repository_; + bool mask_repository_specified_; + strings mask_repository_uuid_; + bool mask_repository_uuid_specified_; + bool no_refinement_; + bool no_move_; + uint16_t noop_exit_; + bool noop_exit_specified_; + string rebuild_checksum_; + bool rebuild_checksum_specified_; + uint16_t no_private_config_; + bool no_private_config_specified_; + bool sys_no_query_; + bool sys_install_; + bool sys_no_fetch_; + bool sys_no_stub_; + bool sys_yes_; + string sys_sudo_; + bool sys_sudo_specified_; + string sys_distribution_; + bool sys_distribution_specified_; + string sys_architecture_; + bool sys_architecture_specified_; + dir_paths directory_; + bool directory_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_build_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-build-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_BUILD_OPTIONS_HXX diff --git a/bpkg/pkg-build-options.ixx b/bpkg/pkg-build-options.ixx new file mode 100644 index 0000000..7b0da30 --- /dev/null +++ b/bpkg/pkg-build-options.ixx @@ -0,0 +1,1014 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_build_pkg_options + // + + inline const bool& pkg_build_pkg_options:: + upgrade () const + { + return this->upgrade_; + } + + inline bool& pkg_build_pkg_options:: + upgrade () + { + return this->upgrade_; + } + + inline void pkg_build_pkg_options:: + upgrade (const bool& x) + { + this->upgrade_ = x; + } + + inline const bool& pkg_build_pkg_options:: + patch () const + { + return this->patch_; + } + + inline bool& pkg_build_pkg_options:: + patch () + { + return this->patch_; + } + + inline void pkg_build_pkg_options:: + patch (const bool& x) + { + this->patch_ = x; + } + + inline const bool& pkg_build_pkg_options:: + deorphan () const + { + return this->deorphan_; + } + + inline bool& pkg_build_pkg_options:: + deorphan () + { + return this->deorphan_; + } + + inline void pkg_build_pkg_options:: + deorphan (const bool& x) + { + this->deorphan_ = x; + } + + inline const bool& pkg_build_pkg_options:: + immediate () const + { + return this->immediate_; + } + + inline bool& pkg_build_pkg_options:: + immediate () + { + return this->immediate_; + } + + inline void pkg_build_pkg_options:: + immediate (const bool& x) + { + this->immediate_ = x; + } + + inline const bool& pkg_build_pkg_options:: + recursive () const + { + return this->recursive_; + } + + inline bool& pkg_build_pkg_options:: + recursive () + { + return this->recursive_; + } + + inline void pkg_build_pkg_options:: + recursive (const bool& x) + { + this->recursive_ = x; + } + + inline const bool& pkg_build_pkg_options:: + upgrade_immediate () const + { + return this->upgrade_immediate_; + } + + inline bool& pkg_build_pkg_options:: + upgrade_immediate () + { + return this->upgrade_immediate_; + } + + inline void pkg_build_pkg_options:: + upgrade_immediate (const bool& x) + { + this->upgrade_immediate_ = x; + } + + inline const bool& pkg_build_pkg_options:: + patch_immediate () const + { + return this->patch_immediate_; + } + + inline bool& pkg_build_pkg_options:: + patch_immediate () + { + return this->patch_immediate_; + } + + inline void pkg_build_pkg_options:: + patch_immediate (const bool& x) + { + this->patch_immediate_ = x; + } + + inline const bool& pkg_build_pkg_options:: + deorphan_immediate () const + { + return this->deorphan_immediate_; + } + + inline bool& pkg_build_pkg_options:: + deorphan_immediate () + { + return this->deorphan_immediate_; + } + + inline void pkg_build_pkg_options:: + deorphan_immediate (const bool& x) + { + this->deorphan_immediate_ = x; + } + + inline const bool& pkg_build_pkg_options:: + upgrade_recursive () const + { + return this->upgrade_recursive_; + } + + inline bool& pkg_build_pkg_options:: + upgrade_recursive () + { + return this->upgrade_recursive_; + } + + inline void pkg_build_pkg_options:: + upgrade_recursive (const bool& x) + { + this->upgrade_recursive_ = x; + } + + inline const bool& pkg_build_pkg_options:: + patch_recursive () const + { + return this->patch_recursive_; + } + + inline bool& pkg_build_pkg_options:: + patch_recursive () + { + return this->patch_recursive_; + } + + inline void pkg_build_pkg_options:: + patch_recursive (const bool& x) + { + this->patch_recursive_ = x; + } + + inline const bool& pkg_build_pkg_options:: + deorphan_recursive () const + { + return this->deorphan_recursive_; + } + + inline bool& pkg_build_pkg_options:: + deorphan_recursive () + { + return this->deorphan_recursive_; + } + + inline void pkg_build_pkg_options:: + deorphan_recursive (const bool& x) + { + this->deorphan_recursive_ = x; + } + + inline const bool& pkg_build_pkg_options:: + dependency () const + { + return this->dependency_; + } + + inline bool& pkg_build_pkg_options:: + dependency () + { + return this->dependency_; + } + + inline void pkg_build_pkg_options:: + dependency (const bool& x) + { + this->dependency_ = x; + } + + inline const bool& pkg_build_pkg_options:: + keep_out () const + { + return this->keep_out_; + } + + inline bool& pkg_build_pkg_options:: + keep_out () + { + return this->keep_out_; + } + + inline void pkg_build_pkg_options:: + keep_out (const bool& x) + { + this->keep_out_ = x; + } + + inline const bool& pkg_build_pkg_options:: + disfigure () const + { + return this->disfigure_; + } + + inline bool& pkg_build_pkg_options:: + disfigure () + { + return this->disfigure_; + } + + inline void pkg_build_pkg_options:: + disfigure (const bool& x) + { + this->disfigure_ = x; + } + + inline const dir_path& pkg_build_pkg_options:: + checkout_root () const + { + return this->checkout_root_; + } + + inline dir_path& pkg_build_pkg_options:: + checkout_root () + { + return this->checkout_root_; + } + + inline void pkg_build_pkg_options:: + checkout_root (const dir_path& x) + { + this->checkout_root_ = x; + } + + inline bool pkg_build_pkg_options:: + checkout_root_specified () const + { + return this->checkout_root_specified_; + } + + inline void pkg_build_pkg_options:: + checkout_root_specified (bool x) + { + this->checkout_root_specified_ = x; + } + + inline const bool& pkg_build_pkg_options:: + checkout_purge () const + { + return this->checkout_purge_; + } + + inline bool& pkg_build_pkg_options:: + checkout_purge () + { + return this->checkout_purge_; + } + + inline void pkg_build_pkg_options:: + checkout_purge (const bool& x) + { + this->checkout_purge_ = x; + } + + inline const strings& pkg_build_pkg_options:: + config_name () const + { + return this->config_name_; + } + + inline strings& pkg_build_pkg_options:: + config_name () + { + return this->config_name_; + } + + inline void pkg_build_pkg_options:: + config_name (const strings& x) + { + this->config_name_ = x; + } + + inline bool pkg_build_pkg_options:: + config_name_specified () const + { + return this->config_name_specified_; + } + + inline void pkg_build_pkg_options:: + config_name_specified (bool x) + { + this->config_name_specified_ = x; + } + + inline const vector<uint64_t>& pkg_build_pkg_options:: + config_id () const + { + return this->config_id_; + } + + inline vector<uint64_t>& pkg_build_pkg_options:: + config_id () + { + return this->config_id_; + } + + inline void pkg_build_pkg_options:: + config_id (const vector<uint64_t>& x) + { + this->config_id_ = x; + } + + inline bool pkg_build_pkg_options:: + config_id_specified () const + { + return this->config_id_specified_; + } + + inline void pkg_build_pkg_options:: + config_id_specified (bool x) + { + this->config_id_specified_ = x; + } + + inline const vector<uuid>& pkg_build_pkg_options:: + config_uuid () const + { + return this->config_uuid_; + } + + inline vector<uuid>& pkg_build_pkg_options:: + config_uuid () + { + return this->config_uuid_; + } + + inline void pkg_build_pkg_options:: + config_uuid (const vector<uuid>& x) + { + this->config_uuid_ = x; + } + + inline bool pkg_build_pkg_options:: + config_uuid_specified () const + { + return this->config_uuid_specified_; + } + + inline void pkg_build_pkg_options:: + config_uuid_specified (bool x) + { + this->config_uuid_specified_ = x; + } + + // pkg_build_options + // + + inline const bool& pkg_build_options:: + yes () const + { + return this->yes_; + } + + inline bool& pkg_build_options:: + yes () + { + return this->yes_; + } + + inline void pkg_build_options:: + yes (const bool& x) + { + this->yes_ = x; + } + + inline const string& pkg_build_options:: + for_ () const + { + return this->for__; + } + + inline string& pkg_build_options:: + for_ () + { + return this->for__; + } + + inline void pkg_build_options:: + for_ (const string& x) + { + this->for__ = x; + } + + inline bool pkg_build_options:: + for__specified () const + { + return this->for__specified_; + } + + inline void pkg_build_options:: + for__specified (bool x) + { + this->for__specified_ = x; + } + + inline const bool& pkg_build_options:: + keep_unused () const + { + return this->keep_unused_; + } + + inline bool& pkg_build_options:: + keep_unused () + { + return this->keep_unused_; + } + + inline void pkg_build_options:: + keep_unused (const bool& x) + { + this->keep_unused_ = x; + } + + inline const bool& pkg_build_options:: + update_dependent () const + { + return this->update_dependent_; + } + + inline bool& pkg_build_options:: + update_dependent () + { + return this->update_dependent_; + } + + inline void pkg_build_options:: + update_dependent (const bool& x) + { + this->update_dependent_ = x; + } + + inline const bool& pkg_build_options:: + leave_dependent () const + { + return this->leave_dependent_; + } + + inline bool& pkg_build_options:: + leave_dependent () + { + return this->leave_dependent_; + } + + inline void pkg_build_options:: + leave_dependent (const bool& x) + { + this->leave_dependent_ = x; + } + + inline const bool& pkg_build_options:: + configure_only () const + { + return this->configure_only_; + } + + inline bool& pkg_build_options:: + configure_only () + { + return this->configure_only_; + } + + inline void pkg_build_options:: + configure_only (const bool& x) + { + this->configure_only_ = x; + } + + inline const bool& pkg_build_options:: + print_only () const + { + return this->print_only_; + } + + inline bool& pkg_build_options:: + print_only () + { + return this->print_only_; + } + + inline void pkg_build_options:: + print_only (const bool& x) + { + this->print_only_ = x; + } + + inline const string& pkg_build_options:: + plan () const + { + return this->plan_; + } + + inline string& pkg_build_options:: + plan () + { + return this->plan_; + } + + inline void pkg_build_options:: + plan (const string& x) + { + this->plan_ = x; + } + + inline bool pkg_build_options:: + plan_specified () const + { + return this->plan_specified_; + } + + inline void pkg_build_options:: + plan_specified (bool x) + { + this->plan_specified_ = x; + } + + inline const bool& pkg_build_options:: + no_fetch () const + { + return this->no_fetch_; + } + + inline bool& pkg_build_options:: + no_fetch () + { + return this->no_fetch_; + } + + inline void pkg_build_options:: + no_fetch (const bool& x) + { + this->no_fetch_ = x; + } + + inline const bool& pkg_build_options:: + fetch_shallow () const + { + return this->fetch_shallow_; + } + + inline bool& pkg_build_options:: + fetch_shallow () + { + return this->fetch_shallow_; + } + + inline void pkg_build_options:: + fetch_shallow (const bool& x) + { + this->fetch_shallow_ = x; + } + + inline const strings& pkg_build_options:: + mask_repository () const + { + return this->mask_repository_; + } + + inline strings& pkg_build_options:: + mask_repository () + { + return this->mask_repository_; + } + + inline void pkg_build_options:: + mask_repository (const strings& x) + { + this->mask_repository_ = x; + } + + inline bool pkg_build_options:: + mask_repository_specified () const + { + return this->mask_repository_specified_; + } + + inline void pkg_build_options:: + mask_repository_specified (bool x) + { + this->mask_repository_specified_ = x; + } + + inline const strings& pkg_build_options:: + mask_repository_uuid () const + { + return this->mask_repository_uuid_; + } + + inline strings& pkg_build_options:: + mask_repository_uuid () + { + return this->mask_repository_uuid_; + } + + inline void pkg_build_options:: + mask_repository_uuid (const strings& x) + { + this->mask_repository_uuid_ = x; + } + + inline bool pkg_build_options:: + mask_repository_uuid_specified () const + { + return this->mask_repository_uuid_specified_; + } + + inline void pkg_build_options:: + mask_repository_uuid_specified (bool x) + { + this->mask_repository_uuid_specified_ = x; + } + + inline const bool& pkg_build_options:: + no_refinement () const + { + return this->no_refinement_; + } + + inline bool& pkg_build_options:: + no_refinement () + { + return this->no_refinement_; + } + + inline void pkg_build_options:: + no_refinement (const bool& x) + { + this->no_refinement_ = x; + } + + inline const bool& pkg_build_options:: + no_move () const + { + return this->no_move_; + } + + inline bool& pkg_build_options:: + no_move () + { + return this->no_move_; + } + + inline void pkg_build_options:: + no_move (const bool& x) + { + this->no_move_ = x; + } + + inline const uint16_t& pkg_build_options:: + noop_exit () const + { + return this->noop_exit_; + } + + inline uint16_t& pkg_build_options:: + noop_exit () + { + return this->noop_exit_; + } + + inline void pkg_build_options:: + noop_exit (const uint16_t& x) + { + this->noop_exit_ = x; + } + + inline bool pkg_build_options:: + noop_exit_specified () const + { + return this->noop_exit_specified_; + } + + inline void pkg_build_options:: + noop_exit_specified (bool x) + { + this->noop_exit_specified_ = x; + } + + inline const string& pkg_build_options:: + rebuild_checksum () const + { + return this->rebuild_checksum_; + } + + inline string& pkg_build_options:: + rebuild_checksum () + { + return this->rebuild_checksum_; + } + + inline void pkg_build_options:: + rebuild_checksum (const string& x) + { + this->rebuild_checksum_ = x; + } + + inline bool pkg_build_options:: + rebuild_checksum_specified () const + { + return this->rebuild_checksum_specified_; + } + + inline void pkg_build_options:: + rebuild_checksum_specified (bool x) + { + this->rebuild_checksum_specified_ = x; + } + + inline const uint16_t& pkg_build_options:: + no_private_config () const + { + return this->no_private_config_; + } + + inline uint16_t& pkg_build_options:: + no_private_config () + { + return this->no_private_config_; + } + + inline void pkg_build_options:: + no_private_config (const uint16_t& x) + { + this->no_private_config_ = x; + } + + inline bool pkg_build_options:: + no_private_config_specified () const + { + return this->no_private_config_specified_; + } + + inline void pkg_build_options:: + no_private_config_specified (bool x) + { + this->no_private_config_specified_ = x; + } + + inline const bool& pkg_build_options:: + sys_no_query () const + { + return this->sys_no_query_; + } + + inline bool& pkg_build_options:: + sys_no_query () + { + return this->sys_no_query_; + } + + inline void pkg_build_options:: + sys_no_query (const bool& x) + { + this->sys_no_query_ = x; + } + + inline const bool& pkg_build_options:: + sys_install () const + { + return this->sys_install_; + } + + inline bool& pkg_build_options:: + sys_install () + { + return this->sys_install_; + } + + inline void pkg_build_options:: + sys_install (const bool& x) + { + this->sys_install_ = x; + } + + inline const bool& pkg_build_options:: + sys_no_fetch () const + { + return this->sys_no_fetch_; + } + + inline bool& pkg_build_options:: + sys_no_fetch () + { + return this->sys_no_fetch_; + } + + inline void pkg_build_options:: + sys_no_fetch (const bool& x) + { + this->sys_no_fetch_ = x; + } + + inline const bool& pkg_build_options:: + sys_no_stub () const + { + return this->sys_no_stub_; + } + + inline bool& pkg_build_options:: + sys_no_stub () + { + return this->sys_no_stub_; + } + + inline void pkg_build_options:: + sys_no_stub (const bool& x) + { + this->sys_no_stub_ = x; + } + + inline const bool& pkg_build_options:: + sys_yes () const + { + return this->sys_yes_; + } + + inline bool& pkg_build_options:: + sys_yes () + { + return this->sys_yes_; + } + + inline void pkg_build_options:: + sys_yes (const bool& x) + { + this->sys_yes_ = x; + } + + inline const string& pkg_build_options:: + sys_sudo () const + { + return this->sys_sudo_; + } + + inline string& pkg_build_options:: + sys_sudo () + { + return this->sys_sudo_; + } + + inline void pkg_build_options:: + sys_sudo (const string& x) + { + this->sys_sudo_ = x; + } + + inline bool pkg_build_options:: + sys_sudo_specified () const + { + return this->sys_sudo_specified_; + } + + inline void pkg_build_options:: + sys_sudo_specified (bool x) + { + this->sys_sudo_specified_ = x; + } + + inline const string& pkg_build_options:: + sys_distribution () const + { + return this->sys_distribution_; + } + + inline string& pkg_build_options:: + sys_distribution () + { + return this->sys_distribution_; + } + + inline void pkg_build_options:: + sys_distribution (const string& x) + { + this->sys_distribution_ = x; + } + + inline bool pkg_build_options:: + sys_distribution_specified () const + { + return this->sys_distribution_specified_; + } + + inline void pkg_build_options:: + sys_distribution_specified (bool x) + { + this->sys_distribution_specified_ = x; + } + + inline const string& pkg_build_options:: + sys_architecture () const + { + return this->sys_architecture_; + } + + inline string& pkg_build_options:: + sys_architecture () + { + return this->sys_architecture_; + } + + inline void pkg_build_options:: + sys_architecture (const string& x) + { + this->sys_architecture_ = x; + } + + inline bool pkg_build_options:: + sys_architecture_specified () const + { + return this->sys_architecture_specified_; + } + + inline void pkg_build_options:: + sys_architecture_specified (bool x) + { + this->sys_architecture_specified_ = x; + } + + inline const dir_paths& pkg_build_options:: + directory () const + { + return this->directory_; + } + + inline dir_paths& pkg_build_options:: + directory () + { + return this->directory_; + } + + inline void pkg_build_options:: + directory (const dir_paths& x) + { + this->directory_ = x; + } + + inline bool pkg_build_options:: + directory_specified () const + { + return this->directory_specified_; + } + + inline void pkg_build_options:: + directory_specified (bool x) + { + this->directory_specified_ = x; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-checkout-options.cxx b/bpkg/pkg-checkout-options.cxx new file mode 100644 index 0000000..b8ad0d9 --- /dev/null +++ b/bpkg/pkg-checkout-options.cxx @@ -0,0 +1,728 @@ +// -*- 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/pkg-checkout-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_checkout_options + // + + pkg_checkout_options:: + pkg_checkout_options () + : replace_ (), + output_root_ (), + output_root_specified_ (false), + output_purge_ () + { + } + + bool pkg_checkout_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 pkg_checkout_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 pkg_checkout_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 pkg_checkout_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 pkg_checkout_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 pkg_checkout_options:: + merge (const pkg_checkout_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.replace_) + { + ::bpkg::cli::parser< bool>::merge ( + this->replace_, a.replace_); + } + + if (a.output_root_specified_) + { + ::bpkg::cli::parser< dir_path>::merge ( + this->output_root_, a.output_root_); + this->output_root_specified_ = true; + } + + if (a.output_purge_) + { + ::bpkg::cli::parser< bool>::merge ( + this->output_purge_, a.output_purge_); + } + } + + ::bpkg::cli::usage_para pkg_checkout_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[1mPKG-CHECKOUT OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--replace\033[0m|\033[1m-r\033[0m Replace the source directory if the package is" << ::std::endl + << " already fetched or unpacked." << ::std::endl; + + os << std::endl + << "\033[1m--output-root\033[0m \033[4mdir\033[0m Check out the package into the specified directory" << ::std::endl + << " rather than into the configuration directory. Note" << ::std::endl + << " that the package source is placed into the" << ::std::endl + << " \033[4mpackage\033[0m\033[1m-\033[0m\033[4mversion\033[0m\033[0m subdirectory of this directory." << ::std::endl; + + os << std::endl + << "\033[1m--output-purge\033[0m Remove the checked out package (source) directory" << ::std::endl + << " when the package is purged." << ::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 (*) (pkg_checkout_options&, ::bpkg::cli::scanner&)> + _cli_pkg_checkout_options_map; + + static _cli_pkg_checkout_options_map _cli_pkg_checkout_options_map_; + + struct _cli_pkg_checkout_options_map_init + { + _cli_pkg_checkout_options_map_init () + { + _cli_pkg_checkout_options_map_["--replace"] = + &::bpkg::cli::thunk< pkg_checkout_options, &pkg_checkout_options::replace_ >; + _cli_pkg_checkout_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_checkout_options, &pkg_checkout_options::replace_ >; + _cli_pkg_checkout_options_map_["--output-root"] = + &::bpkg::cli::thunk< pkg_checkout_options, dir_path, &pkg_checkout_options::output_root_, + &pkg_checkout_options::output_root_specified_ >; + _cli_pkg_checkout_options_map_["--output-purge"] = + &::bpkg::cli::thunk< pkg_checkout_options, &pkg_checkout_options::output_purge_ >; + } + }; + + static _cli_pkg_checkout_options_map_init _cli_pkg_checkout_options_map_init_; + + bool pkg_checkout_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_checkout_options_map::const_iterator i (_cli_pkg_checkout_options_map_.find (o)); + + if (i != _cli_pkg_checkout_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_checkout_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_pkg_checkout_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 pkg-checkout\033[0m [\033[4moptions\033[0m] \033[4mpkg\033[0m\033[1m/\033[0m\033[4mver\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-checkout\033[0m command checks out the specified package version from one of" << ::std::endl + << "the version control-based repositories (\033[1mbpkg-rep-add(1)\033[0m). The resulting package" << ::std::endl + << "state is \033[1munpacked\033[0m (\033[1mbpkg-pkg-status(1)\033[0m)." << ::std::endl + << ::std::endl + << "If the \033[1m--output-root\033[0m option is passed, then the package is checked out into the" << ::std::endl + << "specified directory rather than into the configuration directory. In this case," << ::std::endl + << "\033[1mbpkg\033[0m uses the package (source) directory in place, similar to the \033[1mpkg-unpack" << ::std::endl + << "--existing|-e\033[0m mode. Also, unless the \033[1m--output-purge\033[0m option is specified, \033[1mbpkg\033[0m" << ::std::endl + << "will not attempt to remove this directory when the package is later purged with" << ::std::endl + << "the \033[1mbpkg-pkg-purge(1)\033[0m command. Note also that such a package is not \033[4mexternal\033[0m" << ::std::endl + << "(see \033[1mbpkg-pkg-unpack(1)\033[0m for details)." << ::std::endl + << ::std::endl + << "If the \033[1m--replace|-r\033[0m option is specified, then \033[1mpkg-checkout\033[0m will replace the" << ::std::endl + << "archive and/or source directory of a package that is already in the \033[1munpacked\033[0m or" << ::std::endl + << "\033[1mfetched\033[0m state." << ::std::endl; + + p = ::bpkg::pkg_checkout_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[1mpkg-checkout\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-pkg-checkout.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-checkout\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/pkg-checkout-options.hxx b/bpkg/pkg-checkout-options.hxx new file mode 100644 index 0000000..53ddc1e --- /dev/null +++ b/bpkg/pkg-checkout-options.hxx @@ -0,0 +1,125 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_CHECKOUT_OPTIONS_HXX +#define BPKG_PKG_CHECKOUT_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_checkout_options: public ::bpkg::configuration_options + { + public: + pkg_checkout_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 pkg_checkout_options&); + + // Option accessors. + // + const bool& + replace () const; + + const dir_path& + output_root () const; + + bool + output_root_specified () const; + + const bool& + output_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 replace_; + dir_path output_root_; + bool output_root_specified_; + bool output_purge_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_checkout_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-checkout-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_CHECKOUT_OPTIONS_HXX diff --git a/bpkg/pkg-checkout-options.ixx b/bpkg/pkg-checkout-options.ixx new file mode 100644 index 0000000..af1e0c4 --- /dev/null +++ b/bpkg/pkg-checkout-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 +{ + // pkg_checkout_options + // + + inline const bool& pkg_checkout_options:: + replace () const + { + return this->replace_; + } + + inline const dir_path& pkg_checkout_options:: + output_root () const + { + return this->output_root_; + } + + inline bool pkg_checkout_options:: + output_root_specified () const + { + return this->output_root_specified_; + } + + inline const bool& pkg_checkout_options:: + output_purge () const + { + return this->output_purge_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-clean-options.cxx b/bpkg/pkg-clean-options.cxx new file mode 100644 index 0000000..482f279 --- /dev/null +++ b/bpkg/pkg-clean-options.cxx @@ -0,0 +1,742 @@ +// -*- 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/pkg-clean-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_clean_options + // + + pkg_clean_options:: + pkg_clean_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + immediate_ (), + recursive_ () + { + } + + bool pkg_clean_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 pkg_clean_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 pkg_clean_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 pkg_clean_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 pkg_clean_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 pkg_clean_options:: + merge (const pkg_clean_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + } + + ::bpkg::cli::usage_para pkg_clean_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[1mPKG-CLEAN OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Clean all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Clean held packages that match the specified wildcard" << ::std::endl + << " pattern. Repeat this option to match multiple" << ::std::endl + << " patterns. Note that you may need to quote the pattern" << ::std::endl + << " to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also clean immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also clean all dependencies, 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 (*) (pkg_clean_options&, ::bpkg::cli::scanner&)> + _cli_pkg_clean_options_map; + + static _cli_pkg_clean_options_map _cli_pkg_clean_options_map_; + + struct _cli_pkg_clean_options_map_init + { + _cli_pkg_clean_options_map_init () + { + _cli_pkg_clean_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::all_ >; + _cli_pkg_clean_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::all_ >; + _cli_pkg_clean_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_clean_options, strings, &pkg_clean_options::all_pattern_, + &pkg_clean_options::all_pattern_specified_ >; + _cli_pkg_clean_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::immediate_ >; + _cli_pkg_clean_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::immediate_ >; + _cli_pkg_clean_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::recursive_ >; + _cli_pkg_clean_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_clean_options, &pkg_clean_options::recursive_ >; + } + }; + + static _cli_pkg_clean_options_map_init _cli_pkg_clean_options_map_init_; + + bool pkg_clean_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_clean_options_map::const_iterator i (_cli_pkg_clean_options_map_.find (o)); + + if (i != _cli_pkg_clean_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_clean_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_pkg_clean_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 pkg-clean\033[0m|\033[1mclean\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-clean\033[0m|\033[1mclean\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-clean\033[0m|\033[1mclean\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-clean\033[0m command cleans the specified packages (the first form), all the" << ::std::endl + << "held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m), or all the held" << ::std::endl + << "packages that match any of the specified wildcard patterns (the third form)." << ::std::endl + << "Additionally, immediate or all dependencies of these packages can be also" << ::std::endl + << "cleaned by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m options," << ::std::endl + << "respectively. Underneath, this command doesn't do much more than run \033[1mb clean\033[0m." << ::std::endl + << "In the first form the specified packages must have been previously configured" << ::std::endl + << "with \033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m." << ::std::endl + << ::std::endl + << "Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be passed to" << ::std::endl + << "the build system. Such variables apply to all the specified packages but can" << ::std::endl + << "also be specified to only apply to specific packages using the argument" << ::std::endl + << "grouping mechanism (see \033[1mbpkg-argument-grouping(1)\033[0m for details)." << ::std::endl; + + p = ::bpkg::pkg_clean_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[1mpkg-clean\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-pkg-clean.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-clean\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/pkg-clean-options.hxx b/bpkg/pkg-clean-options.hxx new file mode 100644 index 0000000..13a1e73 --- /dev/null +++ b/bpkg/pkg-clean-options.hxx @@ -0,0 +1,129 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_CLEAN_OPTIONS_HXX +#define BPKG_PKG_CLEAN_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_clean_options: public ::bpkg::configuration_options + { + public: + pkg_clean_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 pkg_clean_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + immediate () 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 all_; + strings all_pattern_; + bool all_pattern_specified_; + bool immediate_; + bool recursive_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_clean_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-clean-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_CLEAN_OPTIONS_HXX diff --git a/bpkg/pkg-clean-options.ixx b/bpkg/pkg-clean-options.ixx new file mode 100644 index 0000000..afa49a1 --- /dev/null +++ b/bpkg/pkg-clean-options.ixx @@ -0,0 +1,51 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_clean_options + // + + inline const bool& pkg_clean_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_clean_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_clean_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_clean_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_clean_options:: + recursive () const + { + return this->recursive_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-configure-options.cxx b/bpkg/pkg-configure-options.cxx new file mode 100644 index 0000000..8fb31cb --- /dev/null +++ b/bpkg/pkg-configure-options.cxx @@ -0,0 +1,679 @@ +// -*- 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/pkg-configure-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_configure_options + // + + pkg_configure_options:: + pkg_configure_options () + { + } + + bool pkg_configure_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 pkg_configure_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 pkg_configure_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 pkg_configure_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 pkg_configure_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 pkg_configure_options:: + merge (const pkg_configure_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + } + + ::bpkg::cli::usage_para pkg_configure_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[1mPKG-CONFIGURE OPTIONS\033[0m" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + // configuration_options base + // + p = ::bpkg::configuration_options::print_usage (os, p); + + return p; + } + + typedef + std::map<std::string, void (*) (pkg_configure_options&, ::bpkg::cli::scanner&)> + _cli_pkg_configure_options_map; + + static _cli_pkg_configure_options_map _cli_pkg_configure_options_map_; + + struct _cli_pkg_configure_options_map_init + { + _cli_pkg_configure_options_map_init () + { + } + }; + + static _cli_pkg_configure_options_map_init _cli_pkg_configure_options_map_init_; + + bool pkg_configure_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_configure_options_map::const_iterator i (_cli_pkg_configure_options_map_.find (o)); + + if (i != _cli_pkg_configure_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_configure_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_pkg_configure_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 pkg-configure\033[0m [\033[4moptions\033[0m] [\033[4mcfg-var\033[0m...] \033[4mpkg\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-configure\033[0m command configures either the previously unpacked" << ::std::endl + << "(\033[1mbpkg-pkg-unpack(1)\033[0m, \033[1mbpkg-pkg-checkout(1)\033[0m) source code package or a package" << ::std::endl + << "that is present in the system." << ::std::endl + << ::std::endl + << "A source code package inherits the common \033[1mbuild2\033[0m configuration values that were" << ::std::endl + << "specified when creating the configuration (\033[1mbpkg-cfg-create(1)\033[0m). Additional" << ::std::endl + << "package-specific configuration variables can be passed to \033[1mpkg-configure\033[0m" << ::std::endl + << "(\033[4mcfg-var\033[0m)." << ::std::endl + << ::std::endl + << "A system package is specified using the \033[1msys:\033[0m\033[4mpkg\033[0m[/\033[4mver\033[0m]\033[0m syntax. If the package" << ::std::endl + << "version (\033[4mver\033[0m) is not specified, then it is considered to be unknown but" << ::std::endl + << "satisfying any dependency constraint. Such a version is displayed as \033[1m*\033[0m." << ::std::endl; + + p = ::bpkg::pkg_configure_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[1mpkg-configure\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-pkg-configure.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-configure\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/pkg-configure-options.hxx b/bpkg/pkg-configure-options.hxx new file mode 100644 index 0000000..e990f9c --- /dev/null +++ b/bpkg/pkg-configure-options.hxx @@ -0,0 +1,109 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_CONFIGURE_OPTIONS_HXX +#define BPKG_PKG_CONFIGURE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_configure_options: public ::bpkg::configuration_options + { + public: + pkg_configure_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 pkg_configure_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_pkg_configure_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-configure-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_CONFIGURE_OPTIONS_HXX diff --git a/bpkg/pkg-configure-options.ixx b/bpkg/pkg-configure-options.ixx new file mode 100644 index 0000000..645428c --- /dev/null +++ b/bpkg/pkg-configure-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 +{ + // pkg_configure_options + // +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-disfigure-options.cxx b/bpkg/pkg-disfigure-options.cxx new file mode 100644 index 0000000..4a15052 --- /dev/null +++ b/bpkg/pkg-disfigure-options.cxx @@ -0,0 +1,701 @@ +// -*- 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/pkg-disfigure-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_disfigure_options + // + + pkg_disfigure_options:: + pkg_disfigure_options () + : keep_out_ (), + keep_config_ () + { + } + + bool pkg_disfigure_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 pkg_disfigure_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 pkg_disfigure_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 pkg_disfigure_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 pkg_disfigure_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 pkg_disfigure_options:: + merge (const pkg_disfigure_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.keep_out_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_out_, a.keep_out_); + } + + if (a.keep_config_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_config_, a.keep_config_); + } + } + + ::bpkg::cli::usage_para pkg_disfigure_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[1mPKG-DISFIGURE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--keep-out\033[0m Don't clean the package's output directory." << ::std::endl; + + os << std::endl + << "\033[1m--keep-config\033[0m Don't remove the package's build system configuration" << ::std::endl + << " (\033[1mconfig.build\033[0m)." << ::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 (*) (pkg_disfigure_options&, ::bpkg::cli::scanner&)> + _cli_pkg_disfigure_options_map; + + static _cli_pkg_disfigure_options_map _cli_pkg_disfigure_options_map_; + + struct _cli_pkg_disfigure_options_map_init + { + _cli_pkg_disfigure_options_map_init () + { + _cli_pkg_disfigure_options_map_["--keep-out"] = + &::bpkg::cli::thunk< pkg_disfigure_options, &pkg_disfigure_options::keep_out_ >; + _cli_pkg_disfigure_options_map_["--keep-config"] = + &::bpkg::cli::thunk< pkg_disfigure_options, &pkg_disfigure_options::keep_config_ >; + } + }; + + static _cli_pkg_disfigure_options_map_init _cli_pkg_disfigure_options_map_init_; + + bool pkg_disfigure_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_disfigure_options_map::const_iterator i (_cli_pkg_disfigure_options_map_.find (o)); + + if (i != _cli_pkg_disfigure_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_disfigure_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_pkg_disfigure_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 pkg-disfigure\033[0m [\033[4moptions\033[0m] \033[4mpkg\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-disfigure\033[0m command disfigures the previously configured (via" << ::std::endl + << "\033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m) package. A source code package is" << ::std::endl + << "returned to the \033[1munpacked\033[0m state. A system package is removed from the" << ::std::endl + << "configuration." << ::std::endl + << ::std::endl + << "By default \033[1mpkg-disfigure\033[0m will remove the package's build system configuration" << ::std::endl + << "(\033[1mconfig.build\033[0m) and also clean its output directory. This behavior can be" << ::std::endl + << "suppressed with the \033[1m--keep-config\033[0m and \033[1m--keep-out\033[0m options, respectively, for" << ::std::endl + << "example, if the package is to be reconfigured." << ::std::endl; + + p = ::bpkg::pkg_disfigure_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[1mpkg-disfigure\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-pkg-disfigure.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-disfigure\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/pkg-disfigure-options.hxx b/bpkg/pkg-disfigure-options.hxx new file mode 100644 index 0000000..2ee4a48 --- /dev/null +++ b/bpkg/pkg-disfigure-options.hxx @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_DISFIGURE_OPTIONS_HXX +#define BPKG_PKG_DISFIGURE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_disfigure_options: public ::bpkg::configuration_options + { + public: + pkg_disfigure_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 pkg_disfigure_options&); + + // Option accessors. + // + const bool& + keep_out () const; + + const bool& + keep_config () 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 keep_out_; + bool keep_config_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_disfigure_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-disfigure-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_DISFIGURE_OPTIONS_HXX diff --git a/bpkg/pkg-disfigure-options.ixx b/bpkg/pkg-disfigure-options.ixx new file mode 100644 index 0000000..9868fda --- /dev/null +++ b/bpkg/pkg-disfigure-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 +{ + // pkg_disfigure_options + // + + inline const bool& pkg_disfigure_options:: + keep_out () const + { + return this->keep_out_; + } + + inline const bool& pkg_disfigure_options:: + keep_config () const + { + return this->keep_config_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-drop-options.cxx b/bpkg/pkg-drop-options.cxx new file mode 100644 index 0000000..c9956b2 --- /dev/null +++ b/bpkg/pkg-drop-options.cxx @@ -0,0 +1,845 @@ +// -*- 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/pkg-drop-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_drop_options + // + + pkg_drop_options:: + pkg_drop_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + yes_ (), + no_ (), + keep_unused_ (), + drop_dependent_ (), + keep_dependent_ (), + dependent_exit_ (), + dependent_exit_specified_ (false), + disfigure_only_ (), + print_only_ (), + plan_ (), + plan_specified_ (false) + { + } + + bool pkg_drop_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 pkg_drop_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 pkg_drop_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 pkg_drop_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 pkg_drop_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 pkg_drop_options:: + merge (const pkg_drop_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.yes_) + { + ::bpkg::cli::parser< bool>::merge ( + this->yes_, a.yes_); + } + + if (a.no_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_, a.no_); + } + + if (a.keep_unused_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_unused_, a.keep_unused_); + } + + if (a.drop_dependent_) + { + ::bpkg::cli::parser< bool>::merge ( + this->drop_dependent_, a.drop_dependent_); + } + + if (a.keep_dependent_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_dependent_, a.keep_dependent_); + } + + if (a.dependent_exit_specified_) + { + ::bpkg::cli::parser< uint16_t>::merge ( + this->dependent_exit_, a.dependent_exit_); + this->dependent_exit_specified_ = true; + } + + if (a.disfigure_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->disfigure_only_, a.disfigure_only_); + } + + if (a.print_only_) + { + ::bpkg::cli::parser< bool>::merge ( + this->print_only_, a.print_only_); + } + + if (a.plan_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->plan_, a.plan_); + this->plan_specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_drop_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[1mPKG-DROP OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Drop all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Drop held packages that match the specified wildcard" << ::std::endl + << " pattern. Repeat this option to match multiple" << ::std::endl + << " patterns. Note that you may need to quote the pattern" << ::std::endl + << " to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--yes\033[0m|\033[1m-y\033[0m Assume the answer to all prompts is \033[1myes\033[0m. Note that" << ::std::endl + << " this option does not apply to the dropping of" << ::std::endl + << " dependents; use \033[1m--drop-dependent\033[0m for that." << ::std::endl; + + os << std::endl + << "\033[1m--no\033[0m|\033[1m-n\033[0m Assume the answer to all prompts is \033[1mno\033[0m. Only makes" << ::std::endl + << " sense together with \033[1m--print-only|-p\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--keep-unused\033[0m|\033[1m-K\033[0m Don't drop dependency packages that were" << ::std::endl + << " automatically built but will no longer be used." << ::std::endl; + + os << std::endl + << "\033[1m--drop-dependent\033[0m|\033[1m-D\033[0m Don't warn about or ask for confirmation if dropping" << ::std::endl + << " dependent packages." << ::std::endl; + + os << std::endl + << "\033[1m--keep-dependent\033[0m Issue an error if attempting to drop dependent" << ::std::endl + << " packages." << ::std::endl; + + os << std::endl + << "\033[1m--dependent-exit\033[0m \033[4mcode\033[0m Silently exit with the specified error code if" << ::std::endl + << " attempting to drop dependent packages." << ::std::endl; + + os << std::endl + << "\033[1m--disfigure-only\033[0m Disfigure all the packages but don't purge." << ::std::endl; + + os << std::endl + << "\033[1m--print-only\033[0m|\033[1m-p\033[0m Print to \033[1mstdout\033[0m what would be done without actually" << ::std::endl + << " doing anything." << ::std::endl; + + os << std::endl + << "\033[1m--plan\033[0m \033[4mheader\033[0m Print the plan (even if \033[1m--yes\033[0m is specified) and start" << ::std::endl + << " it with the \033[4mheader\033[0m line (unless it is empty)." << ::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 (*) (pkg_drop_options&, ::bpkg::cli::scanner&)> + _cli_pkg_drop_options_map; + + static _cli_pkg_drop_options_map _cli_pkg_drop_options_map_; + + struct _cli_pkg_drop_options_map_init + { + _cli_pkg_drop_options_map_init () + { + _cli_pkg_drop_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::all_ >; + _cli_pkg_drop_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::all_ >; + _cli_pkg_drop_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_drop_options, strings, &pkg_drop_options::all_pattern_, + &pkg_drop_options::all_pattern_specified_ >; + _cli_pkg_drop_options_map_["--yes"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::yes_ >; + _cli_pkg_drop_options_map_["-y"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::yes_ >; + _cli_pkg_drop_options_map_["--no"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::no_ >; + _cli_pkg_drop_options_map_["-n"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::no_ >; + _cli_pkg_drop_options_map_["--keep-unused"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::keep_unused_ >; + _cli_pkg_drop_options_map_["-K"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::keep_unused_ >; + _cli_pkg_drop_options_map_["--drop-dependent"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::drop_dependent_ >; + _cli_pkg_drop_options_map_["-D"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::drop_dependent_ >; + _cli_pkg_drop_options_map_["--keep-dependent"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::keep_dependent_ >; + _cli_pkg_drop_options_map_["--dependent-exit"] = + &::bpkg::cli::thunk< pkg_drop_options, uint16_t, &pkg_drop_options::dependent_exit_, + &pkg_drop_options::dependent_exit_specified_ >; + _cli_pkg_drop_options_map_["--disfigure-only"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::disfigure_only_ >; + _cli_pkg_drop_options_map_["--print-only"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::print_only_ >; + _cli_pkg_drop_options_map_["-p"] = + &::bpkg::cli::thunk< pkg_drop_options, &pkg_drop_options::print_only_ >; + _cli_pkg_drop_options_map_["--plan"] = + &::bpkg::cli::thunk< pkg_drop_options, string, &pkg_drop_options::plan_, + &pkg_drop_options::plan_specified_ >; + } + }; + + static _cli_pkg_drop_options_map_init _cli_pkg_drop_options_map_init_; + + bool pkg_drop_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_drop_options_map::const_iterator i (_cli_pkg_drop_options_map_.find (o)); + + if (i != _cli_pkg_drop_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_drop_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_pkg_drop_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 pkg-drop\033[0m|\033[1mdrop\033[0m [\033[4moptions\033[0m] <pkg>..." << ::std::endl + << "\033[1mbpkg pkg-drop\033[0m|\033[1mdrop\033[0m [\033[4moptions\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-drop\033[0m|\033[1mdrop\033[0m [\033[4moptions\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-drop\033[0m command drops from the configuration the specified packages (the" << ::std::endl + << "first form), all the held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m)," << ::std::endl + << "or all the held packages that match any of the specified wildcard patterns (the" << ::std::endl + << "third form). If the packages being dropped still have dependent packages, then" << ::std::endl + << "those will have to be dropped as well and you will be prompted to confirm. And" << ::std::endl + << "if the packages being dropped have dependency packages that would otherwise no" << ::std::endl + << "longer be used, then they will be dropped as well unless the \033[1m--keep-unused\033[0m|\033[1m-K\033[0m\033[0m" << ::std::endl + << "option is specified." << ::std::endl + << ::std::endl + << "The \033[1mpkg-drop\033[0m command also supports several options (described below) that allow" << ::std::endl + << "you to control the amount of work that will be done." << ::std::endl; + + p = ::bpkg::pkg_drop_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[1mpkg-drop\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-pkg-drop.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-drop\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/pkg-drop-options.hxx b/bpkg/pkg-drop-options.hxx new file mode 100644 index 0000000..e72e9fb --- /dev/null +++ b/bpkg/pkg-drop-options.hxx @@ -0,0 +1,165 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_DROP_OPTIONS_HXX +#define BPKG_PKG_DROP_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_drop_options: public ::bpkg::configuration_options + { + public: + pkg_drop_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 pkg_drop_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + yes () const; + + const bool& + no () const; + + const bool& + keep_unused () const; + + const bool& + drop_dependent () const; + + const bool& + keep_dependent () const; + + const uint16_t& + dependent_exit () const; + + bool + dependent_exit_specified () const; + + const bool& + disfigure_only () const; + + const bool& + print_only () const; + + const string& + plan () const; + + bool + plan_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: + bool all_; + strings all_pattern_; + bool all_pattern_specified_; + bool yes_; + bool no_; + bool keep_unused_; + bool drop_dependent_; + bool keep_dependent_; + uint16_t dependent_exit_; + bool dependent_exit_specified_; + bool disfigure_only_; + bool print_only_; + string plan_; + bool plan_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_drop_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-drop-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_DROP_OPTIONS_HXX diff --git a/bpkg/pkg-drop-options.ixx b/bpkg/pkg-drop-options.ixx new file mode 100644 index 0000000..b32cb95 --- /dev/null +++ b/bpkg/pkg-drop-options.ixx @@ -0,0 +1,105 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_drop_options + // + + inline const bool& pkg_drop_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_drop_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_drop_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_drop_options:: + yes () const + { + return this->yes_; + } + + inline const bool& pkg_drop_options:: + no () const + { + return this->no_; + } + + inline const bool& pkg_drop_options:: + keep_unused () const + { + return this->keep_unused_; + } + + inline const bool& pkg_drop_options:: + drop_dependent () const + { + return this->drop_dependent_; + } + + inline const bool& pkg_drop_options:: + keep_dependent () const + { + return this->keep_dependent_; + } + + inline const uint16_t& pkg_drop_options:: + dependent_exit () const + { + return this->dependent_exit_; + } + + inline bool pkg_drop_options:: + dependent_exit_specified () const + { + return this->dependent_exit_specified_; + } + + inline const bool& pkg_drop_options:: + disfigure_only () const + { + return this->disfigure_only_; + } + + inline const bool& pkg_drop_options:: + print_only () const + { + return this->print_only_; + } + + inline const string& pkg_drop_options:: + plan () const + { + return this->plan_; + } + + inline bool pkg_drop_options:: + plan_specified () const + { + return this->plan_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-fetch-options.cxx b/bpkg/pkg-fetch-options.cxx new file mode 100644 index 0000000..ae911d2 --- /dev/null +++ b/bpkg/pkg-fetch-options.cxx @@ -0,0 +1,727 @@ +// -*- 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/pkg-fetch-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_fetch_options + // + + pkg_fetch_options:: + pkg_fetch_options () + : replace_ (), + existing_ (), + purge_ () + { + } + + bool pkg_fetch_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 pkg_fetch_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 pkg_fetch_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 pkg_fetch_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 pkg_fetch_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 pkg_fetch_options:: + merge (const pkg_fetch_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.replace_) + { + ::bpkg::cli::parser< bool>::merge ( + this->replace_, a.replace_); + } + + if (a.existing_) + { + ::bpkg::cli::parser< bool>::merge ( + this->existing_, a.existing_); + } + + if (a.purge_) + { + ::bpkg::cli::parser< bool>::merge ( + this->purge_, a.purge_); + } + } + + ::bpkg::cli::usage_para pkg_fetch_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[1mPKG-FETCH OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--replace\033[0m|\033[1m-r\033[0m Replace the archive if the package is already fetched" << ::std::endl + << " or unpacked." << ::std::endl; + + os << std::endl + << "\033[1m--existing\033[0m|\033[1m-e\033[0m Treat the argument as an existing package archive" << ::std::endl + << " path rather than the package name/version to fetch." << ::std::endl; + + os << std::endl + << "\033[1m--purge\033[0m|\033[1m-p\033[0m Remove the existing package archive when the package" << ::std::endl + << " is purged." << ::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 (*) (pkg_fetch_options&, ::bpkg::cli::scanner&)> + _cli_pkg_fetch_options_map; + + static _cli_pkg_fetch_options_map _cli_pkg_fetch_options_map_; + + struct _cli_pkg_fetch_options_map_init + { + _cli_pkg_fetch_options_map_init () + { + _cli_pkg_fetch_options_map_["--replace"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::replace_ >; + _cli_pkg_fetch_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::replace_ >; + _cli_pkg_fetch_options_map_["--existing"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::existing_ >; + _cli_pkg_fetch_options_map_["-e"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::existing_ >; + _cli_pkg_fetch_options_map_["--purge"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::purge_ >; + _cli_pkg_fetch_options_map_["-p"] = + &::bpkg::cli::thunk< pkg_fetch_options, &pkg_fetch_options::purge_ >; + } + }; + + static _cli_pkg_fetch_options_map_init _cli_pkg_fetch_options_map_init_; + + bool pkg_fetch_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_fetch_options_map::const_iterator i (_cli_pkg_fetch_options_map_.find (o)); + + if (i != _cli_pkg_fetch_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_fetch_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_pkg_fetch_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 pkg-fetch\033[0m [\033[4moptions\033[0m] (\033[4mpkg\033[0m\033[1m/\033[0m\033[4mver\033[0m | \033[1m--existing|-e\033[0m \033[4mfile\033[0m)\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-fetch\033[0m command fetches the archive for the specified package name and" << ::std::endl + << "version from one of the archive-based repositories (\033[1mbpkg-rep-add(1)\033[0m). The" << ::std::endl + << "resulting package state is \033[1mfetched\033[0m (\033[1mbpkg-pkg-status(1)\033[0m)." << ::std::endl + << ::std::endl + << "If the \033[1m--replace|-r\033[0m option is specified, then \033[1mpkg-fetch\033[0m will replace the" << ::std::endl + << "archive of a package that is already in the \033[1mfetched\033[0m or \033[1munpacked\033[0m state." << ::std::endl + << "Otherwise, \033[1mpkg-fetch\033[0m expects the package to not exist in the configuration." << ::std::endl + << ::std::endl + << "If the \033[1m--existing|-e\033[0m option is used, then instead of the name and version" << ::std::endl + << "arguments, \033[1mpkg-fetch\033[0m expects a local path to an existing package archive. In" << ::std::endl + << "this case, \033[1mbpkg\033[0m will use the archive in place, without copying it into the" << ::std::endl + << "configuration directory. Also, unless the \033[1m--purge|-p\033[0m option is specified, \033[1mbpkg\033[0m" << ::std::endl + << "will not attempt to remove this archive when the package is later purged with" << ::std::endl + << "the \033[1mbpkg-pkg-purge(1)\033[0m command." << ::std::endl; + + p = ::bpkg::pkg_fetch_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[1mpkg-fetch\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-pkg-fetch.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-fetch\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl + << "--purge|-p" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/pkg-fetch-options.hxx b/bpkg/pkg-fetch-options.hxx new file mode 100644 index 0000000..99c834c --- /dev/null +++ b/bpkg/pkg-fetch-options.hxx @@ -0,0 +1,121 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_FETCH_OPTIONS_HXX +#define BPKG_PKG_FETCH_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_fetch_options: public ::bpkg::configuration_options + { + public: + pkg_fetch_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 pkg_fetch_options&); + + // Option accessors. + // + const bool& + replace () const; + + const bool& + existing () const; + + const bool& + 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 replace_; + bool existing_; + bool purge_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_fetch_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-fetch-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_FETCH_OPTIONS_HXX diff --git a/bpkg/pkg-fetch-options.ixx b/bpkg/pkg-fetch-options.ixx new file mode 100644 index 0000000..e57a26f --- /dev/null +++ b/bpkg/pkg-fetch-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 +{ + // pkg_fetch_options + // + + inline const bool& pkg_fetch_options:: + replace () const + { + return this->replace_; + } + + inline const bool& pkg_fetch_options:: + existing () const + { + return this->existing_; + } + + inline const bool& pkg_fetch_options:: + purge () const + { + return this->purge_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-install-options.cxx b/bpkg/pkg-install-options.cxx new file mode 100644 index 0000000..dcd0147 --- /dev/null +++ b/bpkg/pkg-install-options.cxx @@ -0,0 +1,750 @@ +// -*- 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/pkg-install-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_install_options + // + + pkg_install_options:: + pkg_install_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + immediate_ (), + recursive_ () + { + } + + bool pkg_install_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 pkg_install_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 pkg_install_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 pkg_install_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 pkg_install_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 pkg_install_options:: + merge (const pkg_install_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + } + + ::bpkg::cli::usage_para pkg_install_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[1mPKG-INSTALL OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Install all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Install held packages that match the specified" << ::std::endl + << " wildcard pattern. Repeat this option to match" << ::std::endl + << " multiple patterns. Note that you may need to quote" << ::std::endl + << " the pattern to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also install immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also install all dependencies, 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 (*) (pkg_install_options&, ::bpkg::cli::scanner&)> + _cli_pkg_install_options_map; + + static _cli_pkg_install_options_map _cli_pkg_install_options_map_; + + struct _cli_pkg_install_options_map_init + { + _cli_pkg_install_options_map_init () + { + _cli_pkg_install_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::all_ >; + _cli_pkg_install_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::all_ >; + _cli_pkg_install_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_install_options, strings, &pkg_install_options::all_pattern_, + &pkg_install_options::all_pattern_specified_ >; + _cli_pkg_install_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::immediate_ >; + _cli_pkg_install_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::immediate_ >; + _cli_pkg_install_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::recursive_ >; + _cli_pkg_install_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_install_options, &pkg_install_options::recursive_ >; + } + }; + + static _cli_pkg_install_options_map_init _cli_pkg_install_options_map_init_; + + bool pkg_install_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_install_options_map::const_iterator i (_cli_pkg_install_options_map_.find (o)); + + if (i != _cli_pkg_install_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_install_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_pkg_install_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 pkg-install\033[0m|\033[1minstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-install\033[0m|\033[1minstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-install\033[0m|\033[1minstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-install\033[0m command installs the specified packages (the first form), all" << ::std::endl + << "the held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m), or all the held" << ::std::endl + << "packages that match any of the specified wildcard patterns (the third form)." << ::std::endl + << "Additionally, immediate or all dependencies of these packages can be also" << ::std::endl + << "installed by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m options," << ::std::endl + << "respectively. Underneath, this command doesn't do much more than run \033[1mb install\033[0m." << ::std::endl + << "In the first form the specified packages must have been previously configured" << ::std::endl + << "with \033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m." << ::std::endl + << ::std::endl + << "Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be passed to" << ::std::endl + << "the build system. Such variables apply to all the specified packages but can" << ::std::endl + << "also be specified to only apply to specific packages using the argument" << ::std::endl + << "grouping mechanism (see \033[1mbpkg-argument-grouping(1)\033[0m for details). In particular," << ::std::endl + << "this mechanism can be used to specify the installation directory, for example:" << ::std::endl + << ::std::endl + << "bpkg install config.install.root=/usr/local \\" << ::std::endl + << " config.install.sudo=sudo \\" << ::std::endl + << " libfoo libbar" << ::std::endl + << ::std::endl + << "Alternatively, the installation directory can be specified once when creating" << ::std::endl + << "the configuration (\033[1mbpkg-cfg-create(1)\033[0m)." << ::std::endl; + + p = ::bpkg::pkg_install_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[1mpkg-install\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-pkg-install.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-install\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/pkg-install-options.hxx b/bpkg/pkg-install-options.hxx new file mode 100644 index 0000000..6beff63 --- /dev/null +++ b/bpkg/pkg-install-options.hxx @@ -0,0 +1,129 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_INSTALL_OPTIONS_HXX +#define BPKG_PKG_INSTALL_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_install_options: public ::bpkg::configuration_options + { + public: + pkg_install_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 pkg_install_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + immediate () 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 all_; + strings all_pattern_; + bool all_pattern_specified_; + bool immediate_; + bool recursive_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_install_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-install-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_INSTALL_OPTIONS_HXX diff --git a/bpkg/pkg-install-options.ixx b/bpkg/pkg-install-options.ixx new file mode 100644 index 0000000..575b4b4 --- /dev/null +++ b/bpkg/pkg-install-options.ixx @@ -0,0 +1,51 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_install_options + // + + inline const bool& pkg_install_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_install_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_install_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_install_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_install_options:: + recursive () const + { + return this->recursive_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-purge-options.cxx b/bpkg/pkg-purge-options.cxx new file mode 100644 index 0000000..65b59a4 --- /dev/null +++ b/bpkg/pkg-purge-options.cxx @@ -0,0 +1,707 @@ +// -*- 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/pkg-purge-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_purge_options + // + + pkg_purge_options:: + pkg_purge_options () + : keep_ (), + force_ () + { + } + + bool pkg_purge_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 pkg_purge_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 pkg_purge_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 pkg_purge_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 pkg_purge_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 pkg_purge_options:: + merge (const pkg_purge_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.keep_) + { + ::bpkg::cli::parser< bool>::merge ( + this->keep_, a.keep_); + } + + if (a.force_) + { + ::bpkg::cli::parser< bool>::merge ( + this->force_, a.force_); + } + } + + ::bpkg::cli::usage_para pkg_purge_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[1mPKG-PURGE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--keep\033[0m|\033[1m-k\033[0m Keep the package archive. Note that in this mode the" << ::std::endl + << " package is still retained in the configuration's" << ::std::endl + << " database in the \033[1mfetched\033[0m state." << ::std::endl; + + os << std::endl + << "\033[1m--force\033[0m|\033[1m-f\033[0m Purge a broken package. In this mode \033[1mbpkg\033[0m will verify" << ::std::endl + << " that the package directory and archive no longer" << ::std::endl + << " exist and then remove the package from the" << ::std::endl + << " configuration." << ::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 (*) (pkg_purge_options&, ::bpkg::cli::scanner&)> + _cli_pkg_purge_options_map; + + static _cli_pkg_purge_options_map _cli_pkg_purge_options_map_; + + struct _cli_pkg_purge_options_map_init + { + _cli_pkg_purge_options_map_init () + { + _cli_pkg_purge_options_map_["--keep"] = + &::bpkg::cli::thunk< pkg_purge_options, &pkg_purge_options::keep_ >; + _cli_pkg_purge_options_map_["-k"] = + &::bpkg::cli::thunk< pkg_purge_options, &pkg_purge_options::keep_ >; + _cli_pkg_purge_options_map_["--force"] = + &::bpkg::cli::thunk< pkg_purge_options, &pkg_purge_options::force_ >; + _cli_pkg_purge_options_map_["-f"] = + &::bpkg::cli::thunk< pkg_purge_options, &pkg_purge_options::force_ >; + } + }; + + static _cli_pkg_purge_options_map_init _cli_pkg_purge_options_map_init_; + + bool pkg_purge_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_purge_options_map::const_iterator i (_cli_pkg_purge_options_map_.find (o)); + + if (i != _cli_pkg_purge_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_purge_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_pkg_purge_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 pkg-purge\033[0m [\033[4moptions\033[0m] \033[4mpkg\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-purge\033[0m command removes the package directory and archive from the" << ::std::endl + << "filesystem and removes the package from the configuration. Only packages in" << ::std::endl + << "the \033[1mfetched\033[0m and \033[1munpacked\033[0m state (\033[1mbpkg-pkg-status(1)\033[0m) can be purged plus \033[1mbroken\033[0m" << ::std::endl + << "packages if the \033[1m--force|-f\033[0m option is specified (see the option's description" << ::std::endl + << "for details on purging broken packages). If the \033[1m--keep|-k\033[0m option is specified," << ::std::endl + << "then the package archive is not removed (see the option's description for" << ::std::endl + << "details on this mode)." << ::std::endl; + + p = ::bpkg::pkg_purge_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[1mpkg-purge\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-pkg-purge.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-purge\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/pkg-purge-options.hxx b/bpkg/pkg-purge-options.hxx new file mode 100644 index 0000000..2649a4a --- /dev/null +++ b/bpkg/pkg-purge-options.hxx @@ -0,0 +1,117 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_PURGE_OPTIONS_HXX +#define BPKG_PKG_PURGE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_purge_options: public ::bpkg::configuration_options + { + public: + pkg_purge_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 pkg_purge_options&); + + // Option accessors. + // + const bool& + keep () const; + + const bool& + force () 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 keep_; + bool force_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_purge_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-purge-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_PURGE_OPTIONS_HXX diff --git a/bpkg/pkg-purge-options.ixx b/bpkg/pkg-purge-options.ixx new file mode 100644 index 0000000..85b3e75 --- /dev/null +++ b/bpkg/pkg-purge-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 +{ + // pkg_purge_options + // + + inline const bool& pkg_purge_options:: + keep () const + { + return this->keep_; + } + + inline const bool& pkg_purge_options:: + force () const + { + return this->force_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-status-options.cxx b/bpkg/pkg-status-options.cxx new file mode 100644 index 0000000..46ca79e --- /dev/null +++ b/bpkg/pkg-status-options.cxx @@ -0,0 +1,973 @@ +// -*- 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/pkg-status-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_status_options + // + + pkg_status_options:: + pkg_status_options () + : all_ (), + link_ (), + immediate_ (), + recursive_ (), + old_available_ (), + constraint_ (), + system_ (), + no_hold_ (), + no_hold_package_ (), + no_hold_version_ () + { + } + + bool pkg_status_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 pkg_status_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 pkg_status_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 pkg_status_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 pkg_status_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 pkg_status_options:: + merge (const pkg_status_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.link_) + { + ::bpkg::cli::parser< bool>::merge ( + this->link_, a.link_); + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + + if (a.old_available_) + { + ::bpkg::cli::parser< bool>::merge ( + this->old_available_, a.old_available_); + } + + if (a.constraint_) + { + ::bpkg::cli::parser< bool>::merge ( + this->constraint_, a.constraint_); + } + + if (a.system_) + { + ::bpkg::cli::parser< bool>::merge ( + this->system_, a.system_); + } + + if (a.no_hold_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_hold_, a.no_hold_); + } + + if (a.no_hold_package_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_hold_package_, a.no_hold_package_); + } + + if (a.no_hold_version_) + { + ::bpkg::cli::parser< bool>::merge ( + this->no_hold_version_, a.no_hold_version_); + } + } + + ::bpkg::cli::usage_para pkg_status_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[1mPKG-STATUS OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Print the status of all the packages, not just held." << ::std::endl; + + os << std::endl + << "\033[1m--link\033[0m Also print the status of held/all packages from" << ::std::endl + << " linked configurations." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also print the status of immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also print the status of all dependencies," << ::std::endl + << " recursively." << ::std::endl; + + os << std::endl + << "\033[1m--old-available\033[0m|\033[1m-o\033[0m Print old available versions." << ::std::endl; + + os << std::endl + << "\033[1m--constraint\033[0m Print version constraints for dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--system\033[0m Check the availability of packages from the system." << ::std::endl; + + os << std::endl + << "\033[1m--no-hold\033[0m Don't print the package or version hold status." << ::std::endl; + + os << std::endl + << "\033[1m--no-hold-package\033[0m Don't print the package hold status." << ::std::endl; + + os << std::endl + << "\033[1m--no-hold-version\033[0m Don't print the version hold status." << ::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 (*) (pkg_status_options&, ::bpkg::cli::scanner&)> + _cli_pkg_status_options_map; + + static _cli_pkg_status_options_map _cli_pkg_status_options_map_; + + struct _cli_pkg_status_options_map_init + { + _cli_pkg_status_options_map_init () + { + _cli_pkg_status_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::all_ >; + _cli_pkg_status_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::all_ >; + _cli_pkg_status_options_map_["--link"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::link_ >; + _cli_pkg_status_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::immediate_ >; + _cli_pkg_status_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::immediate_ >; + _cli_pkg_status_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::recursive_ >; + _cli_pkg_status_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::recursive_ >; + _cli_pkg_status_options_map_["--old-available"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::old_available_ >; + _cli_pkg_status_options_map_["-o"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::old_available_ >; + _cli_pkg_status_options_map_["--constraint"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::constraint_ >; + _cli_pkg_status_options_map_["--system"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::system_ >; + _cli_pkg_status_options_map_["--no-hold"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::no_hold_ >; + _cli_pkg_status_options_map_["--no-hold-package"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::no_hold_package_ >; + _cli_pkg_status_options_map_["--no-hold-version"] = + &::bpkg::cli::thunk< pkg_status_options, &pkg_status_options::no_hold_version_ >; + } + }; + + static _cli_pkg_status_options_map_init _cli_pkg_status_options_map_init_; + + bool pkg_status_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_status_options_map::const_iterator i (_cli_pkg_status_options_map_.find (o)); + + if (i != _cli_pkg_status_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_status_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_pkg_status_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 pkg-status\033[0m|\033[1mstatus\033[0m [\033[4moptions\033[0m] [\033[4mpkg\033[0m[\033[1m/\033[0m\033[4mver\033[0m]...]\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-status\033[0m command prints the status of the specified packages or, if \033[4mver\033[0m" << ::std::endl + << "is specified, package versions. If no packages were specified, then \033[1mpkg-status\033[0m" << ::std::endl + << "prints the status of all the held packages (which are the packages that were" << ::std::endl + << "explicitly built; see \033[1mbpkg-pkg-build(1)\033[0m). The latter mode can be modified to" << ::std::endl + << "print the status of all the packages by specifying the \033[1m--all\033[0m|\033[1m-a\033[0m\033[0m option." << ::std::endl + << "Additionally, the status of immediate or all dependencies of the above packages" << ::std::endl + << "can be printed by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m options," << ::std::endl + << "respectively. Note that the status is written to \033[1mstdout\033[0m, not \033[1mstderr\033[0m." << ::std::endl + << ::std::endl + << "The default output format (see the \033[1m--stdout-format\033[0m common option) is regular" << ::std::endl + << "with components separated with spaces. Each line starts with the package name" << ::std::endl + << "followed by one of the status words listed below. Some of them can be" << ::std::endl + << "optionally followed by '\033[1m,\033[0m' (no spaces) and a sub-status word. Lines" << ::std::endl + << "corresponding to dependencies from linked configurations will additionally" << ::std::endl + << "mention the configuration directory in square brackets after the package name." << ::std::endl + << ::std::endl + << "\033[1munknown\033[0m" << ::std::endl + << " Package is not part of the configuration nor available from any of the" << ::std::endl + << " repositories." << ::std::endl + << "\033[1mavailable\033[0m" << ::std::endl + << " Package is not part of the configuration but is available from one of the" << ::std::endl + << " repositories." << ::std::endl + << "\033[1mfetched\033[0m" << ::std::endl + << " Package is part of the configuration and is fetched." << ::std::endl + << "\033[1munpacked\033[0m" << ::std::endl + << " Package is part of the configuration and is unpacked." << ::std::endl + << "\033[1mconfigured\033[0m" << ::std::endl + << " Package is part of the configuration and is configured. May be followed by" << ::std::endl + << " the \033[1msystem\033[0m sub-status indicating a package coming from the system. The" << ::std::endl + << " version of such a system package (described below) may be the special '\033[1m*\033[0m'" << ::std::endl + << " value indicating a wildcard version." << ::std::endl + << "\033[1mbroken\033[0m" << ::std::endl + << " Package is part of the configuration and is broken (broken packages can" << ::std::endl + << " only be purged; see \033[1mbpkg-pkg-purge(1)\033[0m)." << ::std::endl + << ::std::endl + << "If only the package name was specified without the package version, then the" << ::std::endl + << "\033[1mavailable\033[0m status word is followed by the list of available versions. Versions" << ::std::endl + << "that are only available for up/down-grading are printed in '\033[1m[]\033[0m' (such version" << ::std::endl + << "are only available as dependencies from prerequisite repositories of other" << ::std::endl + << "repositories). If the \033[1m--system\033[0m option is specified, then the last version in" << ::std::endl + << "this list may have the \033[1msys:\033[0m prefix indicating an available system version. Such" << ::std::endl + << "a system version may be the special '\033[1m?\033[0m' value indicating that a package may or" << ::std::endl + << "may not be available from the system and that its version is unknown." << ::std::endl + << ::std::endl + << "The \033[1mfetched\033[0m, \033[1munpacked\033[0m, \033[1mconfigured\033[0m, and \033[1mbroken\033[0m status words are followed by the" << ::std::endl + << "version of the package. If the package version was specified, then the \033[1munknown\033[0m" << ::std::endl + << "status word is also followed by the version." << ::std::endl + << ::std::endl + << "If the status is \033[1mfetched\033[0m, \033[1munpacked\033[0m, \033[1mconfigured\033[0m, or \033[1mbroken\033[0m and newer versions" << ::std::endl + << "are available, then the package version is followed by the \033[1mavailable\033[0m status" << ::std::endl + << "word and the list of newer versions. To instead see a list of all versions," << ::std::endl + << "including the older ones, specify the \033[1m--old-available\033[0m|\033[1m-o\033[0m\033[0m option. In this case" << ::std::endl + << "the currently selected version is printed in '\033[1m()\033[0m'." << ::std::endl + << ::std::endl + << "If the package name was specified with the version, then only the status (such" << ::std::endl + << "as, \033[1mconfigured\033[0m, \033[1mavailable\033[0m, etc.) of this version is considered." << ::std::endl + << ::std::endl + << "If a package is being held, then its name is printed prefixed with '\033[1m!\033[0m'." << ::std::endl + << "Similarly, if a package version is being held, then the version is printed" << ::std::endl + << "prefixed with '\033[1m!\033[0m'. Held packages and held versions were selected by the user" << ::std::endl + << "and are not automatically dropped and upgraded, respectively." << ::std::endl + << ::std::endl + << "Below are some examples, assuming the configuration has \033[1mlibfoo\033[0m \033[1m1.0.0\033[0m configured" << ::std::endl + << "and held (both package and version) as well as \033[1mlibfoo\033[0m \033[1m1.1.0\033[0m and \033[1m1.1.1\033[0m available" << ::std::endl + << "from source and \033[1m1.1.0\033[0m from the system." << ::std::endl + << ::std::endl + << "bpkg status libbar" << ::std::endl + << "libbar unknown" << ::std::endl + << ::std::endl + << "bpkg status libbar/1.0.0" << ::std::endl + << "libbar unknown 1.0.0" << ::std::endl + << ::std::endl + << "bpkg status libfoo/1.0.0" << ::std::endl + << "!libfoo configured !1.0.0" << ::std::endl + << ::std::endl + << "bpkg status libfoo/1.1.0" << ::std::endl + << "libfoo available 1.1.0" << ::std::endl + << ::std::endl + << "bpkg status --system libfoo/1.1.0" << ::std::endl + << "libfoo available 1.1.0 sys:1.1.0" << ::std::endl + << ::std::endl + << "bpkg status libfoo" << ::std::endl + << "!libfoo configured !1.0.0 available 1.1.0 1.1.1" << ::std::endl + << ::std::endl + << "bpkg status libfoo/1.1.1 libbar" << ::std::endl + << "libfoo available 1.1.1" << ::std::endl + << "libbar unknown" << ::std::endl + << ::std::endl + << "Assuming now that we dropped \033[1mlibfoo\033[0m from the configuration:" << ::std::endl + << ::std::endl + << "bpkg status libfoo/1.0.0" << ::std::endl + << "libfoo unknown 1.0.0" << ::std::endl + << ::std::endl + << "bpkg status libfoo" << ::std::endl + << "libfoo available 1.1.0 1.1.1" << ::std::endl + << ::std::endl + << "And assuming now that we built \033[1mlibfoo\033[0m as a system package with the wildcard" << ::std::endl + << "version:" << ::std::endl + << ::std::endl + << "bpkg status libfoo" << ::std::endl + << "!libfoo configured,system !* available 1.1.0 1.1.1" << ::std::endl + << ::std::endl + << "Another example of the status output this time including dependencies:" << ::std::endl + << ::std::endl + << "bpkg status -r libbaz" << ::std::endl + << "!libbaz configured 1.0.0" << ::std::endl + << " libfoo configured 1.0.0" << ::std::endl + << " bison [.bpkg/host/] configured 1.0.0" << ::std::endl + << " libbar configured 2.0.0" << ::std::endl + << ::std::endl + << "If the output format is \033[1mjson\033[0m, then the output is a JSON array of objects which" << ::std::endl + << "are the serialized representation of the following C++ \033[1mstruct\033[0m \033[1mpackage_status\033[0m:" << ::std::endl + << ::std::endl + << "struct available_version" << ::std::endl + << "{" << ::std::endl + << " string version;" << ::std::endl + << " bool system;" << ::std::endl + << " bool dependency;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "struct package_status" << ::std::endl + << "{" << ::std::endl + << " string name;" << ::std::endl + << " optional<string> configuration;" << ::std::endl + << " optional<string> constraint;" << ::std::endl + << " string status;" << ::std::endl + << " optional<string> sub_status;" << ::std::endl + << " optional<string> version;" << ::std::endl + << " bool hold_package;" << ::std::endl + << " bool hold_version;" << ::std::endl + << " vector<available_version> available_versions;" << ::std::endl + << " vector<package_status> dependencies;" << ::std::endl + << "};" << ::std::endl + << ::std::endl + << "For example:" << ::std::endl + << ::std::endl + << "[" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"hello\"," << ::std::endl + << " \"status\": \"configured\"," << ::std::endl + << " \"version\": \"1.0.0\"," << ::std::endl + << " \"hold_package\": true," << ::std::endl + << " \"available_versions\": [" << ::std::endl + << " {" << ::std::endl + << " \"version\": \"1.0.1\"" << ::std::endl + << " }," << ::std::endl + << " {" << ::std::endl + << " \"version\": \"2.0.0\"" << ::std::endl + << " }" << ::std::endl + << " ]," << ::std::endl + << " \"dependencies\": [" << ::std::endl + << " {" << ::std::endl + << " \"name\": \"libhello\"," << ::std::endl + << " \"status\": \"configured\"," << ::std::endl + << " \"version\": \"1.0.2\"," << ::std::endl + << " }" << ::std::endl + << " ]" << ::std::endl + << " }" << ::std::endl + << "]" << ::std::endl + << ::std::endl + << "See the JSON OUTPUT section in \033[1mbpkg-common-options(1)\033[0m for details on the" << ::std::endl + << "overall properties of this format and the semantics of the \033[1mstruct\033[0m" << ::std::endl + << "serialization." << ::std::endl + << ::std::endl + << "In \033[1mpackage_status\033[0m, the \033[1mconfiguration\033[0m member contains the absolute directory of" << ::std::endl + << "a linked configuration if this package resides in a linked configuration. The" << ::std::endl + << "\033[1mconstraint\033[0m member is present only if the \033[1m--constraint\033[0m option is specified. The" << ::std::endl + << "\033[1mversion\033[0m member is absent if the \033[1mstatus\033[0m member is \033[1munknown\033[0m or \033[1mavailable\033[0m and no" << ::std::endl + << "package version is specified on the command line. If the \033[1msub_status\033[0m member is" << ::std::endl + << "\033[1msystem\033[0m, then the \033[1mversion\033[0m member can be special \033[1m*\033[0m. The \033[1mdependencies\033[0m member is" << ::std::endl + << "present only if the \033[1m--immediate|-i\033[0m or \033[1m--recursive|-r\033[0m options are specified." << ::std::endl + << ::std::endl + << "In \033[1mavailable_version\033[0m, if the \033[1msystem\033[0m member is \033[1mtrue\033[0m, then this version is" << ::std::endl + << "available from the system, in which case the \033[1mversion\033[0m member can be special \033[1m?\033[0m or" << ::std::endl + << "\033[1m*\033[0m. If the \033[1mdependency\033[0m member is \033[1mtrue\033[0m, then this version is only available as a" << ::std::endl + << "dependency from prerequisite repositories of other repositories." << ::std::endl; + + p = ::bpkg::pkg_status_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[1mpkg-status\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-pkg-status.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-status\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/pkg-status-options.hxx b/bpkg/pkg-status-options.hxx new file mode 100644 index 0000000..9271c1e --- /dev/null +++ b/bpkg/pkg-status-options.hxx @@ -0,0 +1,149 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_STATUS_OPTIONS_HXX +#define BPKG_PKG_STATUS_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_status_options: public ::bpkg::configuration_options + { + public: + pkg_status_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 pkg_status_options&); + + // Option accessors. + // + const bool& + all () const; + + const bool& + link () const; + + const bool& + immediate () const; + + const bool& + recursive () const; + + const bool& + old_available () const; + + const bool& + constraint () const; + + const bool& + system () const; + + const bool& + no_hold () const; + + const bool& + no_hold_package () const; + + const bool& + no_hold_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 all_; + bool link_; + bool immediate_; + bool recursive_; + bool old_available_; + bool constraint_; + bool system_; + bool no_hold_; + bool no_hold_package_; + bool no_hold_version_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_status_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-status-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_STATUS_OPTIONS_HXX diff --git a/bpkg/pkg-status-options.ixx b/bpkg/pkg-status-options.ixx new file mode 100644 index 0000000..bf0c13c --- /dev/null +++ b/bpkg/pkg-status-options.ixx @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_status_options + // + + inline const bool& pkg_status_options:: + all () const + { + return this->all_; + } + + inline const bool& pkg_status_options:: + link () const + { + return this->link_; + } + + inline const bool& pkg_status_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_status_options:: + recursive () const + { + return this->recursive_; + } + + inline const bool& pkg_status_options:: + old_available () const + { + return this->old_available_; + } + + inline const bool& pkg_status_options:: + constraint () const + { + return this->constraint_; + } + + inline const bool& pkg_status_options:: + system () const + { + return this->system_; + } + + inline const bool& pkg_status_options:: + no_hold () const + { + return this->no_hold_; + } + + inline const bool& pkg_status_options:: + no_hold_package () const + { + return this->no_hold_package_; + } + + inline const bool& pkg_status_options:: + no_hold_version () const + { + return this->no_hold_version_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-test-options.cxx b/bpkg/pkg-test-options.cxx new file mode 100644 index 0000000..f5fdcf7 --- /dev/null +++ b/bpkg/pkg-test-options.cxx @@ -0,0 +1,758 @@ +// -*- 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/pkg-test-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_test_options + // + + pkg_test_options:: + pkg_test_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + immediate_ (), + recursive_ (), + package_cwd_ () + { + } + + bool pkg_test_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 pkg_test_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 pkg_test_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 pkg_test_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 pkg_test_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 pkg_test_options:: + merge (const pkg_test_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + + if (a.package_cwd_) + { + ::bpkg::cli::parser< bool>::merge ( + this->package_cwd_, a.package_cwd_); + } + } + + ::bpkg::cli::usage_para pkg_test_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[1mPKG-TEST OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Test all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Test held packages that match the specified wildcard" << ::std::endl + << " pattern. Repeat this option to match multiple" << ::std::endl + << " patterns. Note that you may need to quote the pattern" << ::std::endl + << " to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also test immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also test all dependencies, recursively." << ::std::endl; + + os << std::endl + << "\033[1m--package-cwd\033[0m Change the current working directory to the package" << ::std::endl + << " directory prior to running tests. This may help" << ::std::endl + << " ported third-party packages since its not uncommon" << ::std::endl + << " for tests to expect they are running form the project" << ::std::endl + << " root 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 (*) (pkg_test_options&, ::bpkg::cli::scanner&)> + _cli_pkg_test_options_map; + + static _cli_pkg_test_options_map _cli_pkg_test_options_map_; + + struct _cli_pkg_test_options_map_init + { + _cli_pkg_test_options_map_init () + { + _cli_pkg_test_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::all_ >; + _cli_pkg_test_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::all_ >; + _cli_pkg_test_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_test_options, strings, &pkg_test_options::all_pattern_, + &pkg_test_options::all_pattern_specified_ >; + _cli_pkg_test_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::immediate_ >; + _cli_pkg_test_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::immediate_ >; + _cli_pkg_test_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::recursive_ >; + _cli_pkg_test_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::recursive_ >; + _cli_pkg_test_options_map_["--package-cwd"] = + &::bpkg::cli::thunk< pkg_test_options, &pkg_test_options::package_cwd_ >; + } + }; + + static _cli_pkg_test_options_map_init _cli_pkg_test_options_map_init_; + + bool pkg_test_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_test_options_map::const_iterator i (_cli_pkg_test_options_map_.find (o)); + + if (i != _cli_pkg_test_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_test_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_pkg_test_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 pkg-test\033[0m|\033[1mtest\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-test\033[0m|\033[1mtest\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-test\033[0m|\033[1mtest\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-test\033[0m command tests the specified packages (the first form), all the" << ::std::endl + << "held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m), or all the held" << ::std::endl + << "packages that match any of the specified wildcard patterns (the third form)." << ::std::endl + << "Additionally, immediate or all dependencies of these packages can also be" << ::std::endl + << "tested by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m options," << ::std::endl + << "respectively. Underneath, this command doesn't do much more than run \033[1mb test\033[0m. In" << ::std::endl + << "the first form the specified packages must have been previously configured with" << ::std::endl + << "\033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m." << ::std::endl + << ::std::endl + << "Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be passed to" << ::std::endl + << "the build system. Such variables apply to all the specified packages but can" << ::std::endl + << "also be specified to only apply to specific packages using the argument" << ::std::endl + << "grouping mechanism (see \033[1mbpkg-argument-grouping(1)\033[0m for details)." << ::std::endl; + + p = ::bpkg::pkg_test_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[1mpkg-test\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-pkg-test.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-test\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/pkg-test-options.hxx b/bpkg/pkg-test-options.hxx new file mode 100644 index 0000000..b2c1096 --- /dev/null +++ b/bpkg/pkg-test-options.hxx @@ -0,0 +1,133 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_TEST_OPTIONS_HXX +#define BPKG_PKG_TEST_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_test_options: public ::bpkg::configuration_options + { + public: + pkg_test_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 pkg_test_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + immediate () const; + + const bool& + recursive () const; + + const bool& + package_cwd () 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 all_; + strings all_pattern_; + bool all_pattern_specified_; + bool immediate_; + bool recursive_; + bool package_cwd_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_test_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-test-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_TEST_OPTIONS_HXX diff --git a/bpkg/pkg-test-options.ixx b/bpkg/pkg-test-options.ixx new file mode 100644 index 0000000..5c75c56 --- /dev/null +++ b/bpkg/pkg-test-options.ixx @@ -0,0 +1,57 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_test_options + // + + inline const bool& pkg_test_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_test_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_test_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_test_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_test_options:: + recursive () const + { + return this->recursive_; + } + + inline const bool& pkg_test_options:: + package_cwd () const + { + return this->package_cwd_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-uninstall-options.cxx b/bpkg/pkg-uninstall-options.cxx new file mode 100644 index 0000000..611b19d --- /dev/null +++ b/bpkg/pkg-uninstall-options.cxx @@ -0,0 +1,743 @@ +// -*- 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/pkg-uninstall-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_uninstall_options + // + + pkg_uninstall_options:: + pkg_uninstall_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + immediate_ (), + recursive_ () + { + } + + bool pkg_uninstall_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 pkg_uninstall_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 pkg_uninstall_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 pkg_uninstall_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 pkg_uninstall_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 pkg_uninstall_options:: + merge (const pkg_uninstall_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + } + + ::bpkg::cli::usage_para pkg_uninstall_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[1mPKG-UNINSTALL OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Uninstall all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Uninstall held packages that match the specified" << ::std::endl + << " wildcard pattern. Repeat this option to match" << ::std::endl + << " multiple patterns. Note that you may need to quote" << ::std::endl + << " the pattern to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also uninstall immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also uninstall all dependencies, 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 (*) (pkg_uninstall_options&, ::bpkg::cli::scanner&)> + _cli_pkg_uninstall_options_map; + + static _cli_pkg_uninstall_options_map _cli_pkg_uninstall_options_map_; + + struct _cli_pkg_uninstall_options_map_init + { + _cli_pkg_uninstall_options_map_init () + { + _cli_pkg_uninstall_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::all_ >; + _cli_pkg_uninstall_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::all_ >; + _cli_pkg_uninstall_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_uninstall_options, strings, &pkg_uninstall_options::all_pattern_, + &pkg_uninstall_options::all_pattern_specified_ >; + _cli_pkg_uninstall_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::immediate_ >; + _cli_pkg_uninstall_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::immediate_ >; + _cli_pkg_uninstall_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::recursive_ >; + _cli_pkg_uninstall_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_uninstall_options, &pkg_uninstall_options::recursive_ >; + } + }; + + static _cli_pkg_uninstall_options_map_init _cli_pkg_uninstall_options_map_init_; + + bool pkg_uninstall_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_uninstall_options_map::const_iterator i (_cli_pkg_uninstall_options_map_.find (o)); + + if (i != _cli_pkg_uninstall_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_uninstall_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_pkg_uninstall_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 pkg-uninstall\033[0m|\033[1muninstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-uninstall\033[0m|\033[1muninstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-uninstall\033[0m|\033[1muninstall\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-uninstall\033[0m command uninstalls the specified packages (the first form)," << ::std::endl + << "all the held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m), or all the" << ::std::endl + << "held packages that match any of the specified wildcard patterns (the third" << ::std::endl + << "form). Additionally, immediate or all dependencies of these specified packages" << ::std::endl + << "can be also uninstalled by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m" << ::std::endl + << "options, respectively. Underneath, this command doesn't do much more than run \033[1mb" << ::std::endl + << "uninstall\033[0m. In the first form the specified packages must have been previously" << ::std::endl + << "configured with \033[1mbpkg-pkg-build(1)\033[0m or \033[1mbpkg-pkg-configure(1)\033[0m." << ::std::endl + << ::std::endl + << "Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be passed to" << ::std::endl + << "the build system. Such variables apply to all the specified packages but can" << ::std::endl + << "also be specified to only apply to specific packages using the argument" << ::std::endl + << "grouping mechanism (see \033[1mbpkg-argument-grouping(1)\033[0m for details). See" << ::std::endl + << "\033[1mbpkg-pkg-install(1)\033[0m for some examples." << ::std::endl; + + p = ::bpkg::pkg_uninstall_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[1mpkg-uninstall\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-pkg-uninstall.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-uninstall\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/pkg-uninstall-options.hxx b/bpkg/pkg-uninstall-options.hxx new file mode 100644 index 0000000..1feb443 --- /dev/null +++ b/bpkg/pkg-uninstall-options.hxx @@ -0,0 +1,129 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_UNINSTALL_OPTIONS_HXX +#define BPKG_PKG_UNINSTALL_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_uninstall_options: public ::bpkg::configuration_options + { + public: + pkg_uninstall_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 pkg_uninstall_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + immediate () 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 all_; + strings all_pattern_; + bool all_pattern_specified_; + bool immediate_; + bool recursive_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_uninstall_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-uninstall-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_UNINSTALL_OPTIONS_HXX diff --git a/bpkg/pkg-uninstall-options.ixx b/bpkg/pkg-uninstall-options.ixx new file mode 100644 index 0000000..ef15f14 --- /dev/null +++ b/bpkg/pkg-uninstall-options.ixx @@ -0,0 +1,51 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // pkg_uninstall_options + // + + inline const bool& pkg_uninstall_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_uninstall_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_uninstall_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_uninstall_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_uninstall_options:: + recursive () const + { + return this->recursive_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-unpack-options.cxx b/bpkg/pkg-unpack-options.cxx new file mode 100644 index 0000000..9654924 --- /dev/null +++ b/bpkg/pkg-unpack-options.cxx @@ -0,0 +1,741 @@ +// -*- 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/pkg-unpack-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_unpack_options + // + + pkg_unpack_options:: + pkg_unpack_options () + : existing_ (), + purge_ (), + replace_ () + { + } + + bool pkg_unpack_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 pkg_unpack_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 pkg_unpack_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 pkg_unpack_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 pkg_unpack_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 pkg_unpack_options:: + merge (const pkg_unpack_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.existing_) + { + ::bpkg::cli::parser< bool>::merge ( + this->existing_, a.existing_); + } + + if (a.purge_) + { + ::bpkg::cli::parser< bool>::merge ( + this->purge_, a.purge_); + } + + if (a.replace_) + { + ::bpkg::cli::parser< bool>::merge ( + this->replace_, a.replace_); + } + } + + ::bpkg::cli::usage_para pkg_unpack_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[1mPKG-UNPACK OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--existing\033[0m|\033[1m-e\033[0m Treat the argument as an existing package directory" << ::std::endl + << " path rather than the package name to unpack." << ::std::endl; + + os << std::endl + << "\033[1m--purge\033[0m|\033[1m-p\033[0m Remove the existing package directory when the" << ::std::endl + << " package is purged." << ::std::endl; + + os << std::endl + << "\033[1m--replace\033[0m|\033[1m-r\033[0m Replace the source directory if the package is" << ::std::endl + << " already unpacked or fetched. Can only be specified" << ::std::endl + << " with an external package." << ::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 (*) (pkg_unpack_options&, ::bpkg::cli::scanner&)> + _cli_pkg_unpack_options_map; + + static _cli_pkg_unpack_options_map _cli_pkg_unpack_options_map_; + + struct _cli_pkg_unpack_options_map_init + { + _cli_pkg_unpack_options_map_init () + { + _cli_pkg_unpack_options_map_["--existing"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::existing_ >; + _cli_pkg_unpack_options_map_["-e"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::existing_ >; + _cli_pkg_unpack_options_map_["--purge"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::purge_ >; + _cli_pkg_unpack_options_map_["-p"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::purge_ >; + _cli_pkg_unpack_options_map_["--replace"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::replace_ >; + _cli_pkg_unpack_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_unpack_options, &pkg_unpack_options::replace_ >; + } + }; + + static _cli_pkg_unpack_options_map_init _cli_pkg_unpack_options_map_init_; + + bool pkg_unpack_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_unpack_options_map::const_iterator i (_cli_pkg_unpack_options_map_.find (o)); + + if (i != _cli_pkg_unpack_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_unpack_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_pkg_unpack_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 pkg-unpack\033[0m [\033[4moptions\033[0m] (\033[4mpkg\033[0m[\033[1m/\033[0m\033[4mver\033[0m] | \033[1m--existing|-e\033[0m \033[4mdir\033[0m)\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "If only the package name is specified, then the \033[1mpkg-unpack\033[0m command unpacks the" << ::std::endl + << "archive for the previously fetched (\033[1mbpkg-pkg-fetch(1)\033[0m) package. The resulting" << ::std::endl + << "package state is \033[1munpacked\033[0m (\033[1mbpkg-pkg-status(1)\033[0m)." << ::std::endl + << ::std::endl + << "If the package version is also specified, then the (source) directory from one" << ::std::endl + << "of the directory-based repositories (\033[1mbpkg-rep-add(1)\033[0m) is used in place, without" << ::std::endl + << "copying it into the configuration directory. Such a package is called \033[4mexternal\033[0m." << ::std::endl + << ::std::endl + << "If the \033[1m--existing|-e\033[0m option is used, then instead of the package name," << ::std::endl + << "\033[1mpkg-unpack\033[0m expects a local path to an existing package directory. In this case," << ::std::endl + << "\033[1mbpkg\033[0m will use the (source) directory in place, the same as for packages from" << ::std::endl + << "directory-based repositories. Also, unless the \033[1m--purge|-p\033[0m option is specified," << ::std::endl + << "\033[1mbpkg\033[0m will not attempt to remove this directory when the package is later purged" << ::std::endl + << "with the \033[1mbpkg-pkg-purge(1)\033[0m command. Such a package is also \033[4mexternal\033[0m." << ::std::endl + << ::std::endl + << "If \033[1m--existing|-e\033[0m is specified together with the \033[1m--replace|-r\033[0m option, then" << ::std::endl + << "\033[1mpkg-unpack\033[0m will replace the archive and/or source directory of a package that" << ::std::endl + << "is already in the \033[1munpacked\033[0m or \033[1mfetched\033[0m state." << ::std::endl + << ::std::endl + << "An external package triggers several changes in semantics compared to a normal" << ::std::endl + << "package: The package (output) directory inside the configuration is called just" << ::std::endl + << "\033[4mpkg\033[0m rather than \033[4mpkg\033[0m\033[1m-\033[0m\033[4mver\033[0m. It is also assumed that the packaging information" << ::std::endl + << "(package manifest and lockfile) for such packages may change without" << ::std::endl + << "incrementing the package version (for example, during development). To support" << ::std::endl + << "this, \033[1mbpkg\033[0m implements the \033[4mpackage iteration\033[0m mechanism which may result in" << ::std::endl + << "iteration numbers to be shown as part of the package version, for example," << ::std::endl + << "\033[1m1.2.3#1\033[0m (see Package Version (bpkg#package-version))." << ::std::endl; + + p = ::bpkg::pkg_unpack_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[1mpkg-unpack\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-pkg-unpack.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-unpack\033[0m command options cannot be specified in the default" << ::std::endl + << "options files:" << ::std::endl + << ::std::endl + << "--directory|-d" << ::std::endl + << "--purge|-p" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/pkg-unpack-options.hxx b/bpkg/pkg-unpack-options.hxx new file mode 100644 index 0000000..752e17b --- /dev/null +++ b/bpkg/pkg-unpack-options.hxx @@ -0,0 +1,121 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_UNPACK_OPTIONS_HXX +#define BPKG_PKG_UNPACK_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_unpack_options: public ::bpkg::configuration_options + { + public: + pkg_unpack_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 pkg_unpack_options&); + + // Option accessors. + // + const bool& + existing () const; + + const bool& + purge () const; + + const bool& + replace () 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 existing_; + bool purge_; + bool replace_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_unpack_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-unpack-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_UNPACK_OPTIONS_HXX diff --git a/bpkg/pkg-unpack-options.ixx b/bpkg/pkg-unpack-options.ixx new file mode 100644 index 0000000..68abf8a --- /dev/null +++ b/bpkg/pkg-unpack-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 +{ + // pkg_unpack_options + // + + inline const bool& pkg_unpack_options:: + existing () const + { + return this->existing_; + } + + inline const bool& pkg_unpack_options:: + purge () const + { + return this->purge_; + } + + inline const bool& pkg_unpack_options:: + replace () const + { + return this->replace_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-update-options.cxx b/bpkg/pkg-update-options.cxx new file mode 100644 index 0000000..0dc6187 --- /dev/null +++ b/bpkg/pkg-update-options.cxx @@ -0,0 +1,763 @@ +// -*- 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/pkg-update-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_update_options + // + + pkg_update_options:: + pkg_update_options () + : all_ (), + all_pattern_ (), + all_pattern_specified_ (false), + immediate_ (), + recursive_ (), + for__ (), + for__specified_ (false) + { + } + + bool pkg_update_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 pkg_update_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 pkg_update_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 pkg_update_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 pkg_update_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 pkg_update_options:: + merge (const pkg_update_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.all_pattern_specified_) + { + ::bpkg::cli::parser< strings>::merge ( + this->all_pattern_, a.all_pattern_); + this->all_pattern_specified_ = true; + } + + if (a.immediate_) + { + ::bpkg::cli::parser< bool>::merge ( + this->immediate_, a.immediate_); + } + + if (a.recursive_) + { + ::bpkg::cli::parser< bool>::merge ( + this->recursive_, a.recursive_); + } + + if (a.for__specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->for__, a.for__); + this->for__specified_ = true; + } + } + + ::bpkg::cli::usage_para pkg_update_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[1mPKG-UPDATE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Update all held packages." << ::std::endl; + + os << std::endl + << "\033[1m--all-pattern\033[0m \033[4mpattern\033[0m Update held packages that match the specified" << ::std::endl + << " wildcard pattern. Repeat this option to match" << ::std::endl + << " multiple patterns. Note that you may need to quote" << ::std::endl + << " the pattern to prevent expansion by your shell." << ::std::endl; + + os << std::endl + << "\033[1m--immediate\033[0m|\033[1m-i\033[0m Also update immediate dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--recursive\033[0m|\033[1m-r\033[0m Also update all dependencies, recursively." << ::std::endl; + + os << std::endl + << "\033[1m--for\033[0m|\033[1m-f\033[0m \033[4moperation\033[0m Instead of the default \033[1mupdate\033[0m build system operation," << ::std::endl + << " perform the \033[1mupdate-for-\033[0m\033[4moperation\033[0m variant where" << ::std::endl + << " \033[4moperation\033[0m is normally \033[1minstall\033[0m or \033[1mtest\033[0m." << ::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 (*) (pkg_update_options&, ::bpkg::cli::scanner&)> + _cli_pkg_update_options_map; + + static _cli_pkg_update_options_map _cli_pkg_update_options_map_; + + struct _cli_pkg_update_options_map_init + { + _cli_pkg_update_options_map_init () + { + _cli_pkg_update_options_map_["--all"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::all_ >; + _cli_pkg_update_options_map_["-a"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::all_ >; + _cli_pkg_update_options_map_["--all-pattern"] = + &::bpkg::cli::thunk< pkg_update_options, strings, &pkg_update_options::all_pattern_, + &pkg_update_options::all_pattern_specified_ >; + _cli_pkg_update_options_map_["--immediate"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::immediate_ >; + _cli_pkg_update_options_map_["-i"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::immediate_ >; + _cli_pkg_update_options_map_["--recursive"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::recursive_ >; + _cli_pkg_update_options_map_["-r"] = + &::bpkg::cli::thunk< pkg_update_options, &pkg_update_options::recursive_ >; + _cli_pkg_update_options_map_["--for"] = + &::bpkg::cli::thunk< pkg_update_options, string, &pkg_update_options::for__, + &pkg_update_options::for__specified_ >; + _cli_pkg_update_options_map_["-f"] = + &::bpkg::cli::thunk< pkg_update_options, string, &pkg_update_options::for__, + &pkg_update_options::for__specified_ >; + } + }; + + static _cli_pkg_update_options_map_init _cli_pkg_update_options_map_init_; + + bool pkg_update_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_update_options_map::const_iterator i (_cli_pkg_update_options_map_.find (o)); + + if (i != _cli_pkg_update_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_update_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_pkg_update_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 pkg-update\033[0m|\033[1mupdate\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[4mpkg\033[0m..." << ::std::endl + << "\033[1mbpkg pkg-update\033[0m|\033[1mupdate\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg pkg-update\033[0m|\033[1mupdate\033[0m [\033[4moptions\033[0m] [\033[4mvars\033[0m] (\033[1m--all-pattern\033[0m <pattern>)...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-update\033[0m command updates the specified packages (the first form), all the" << ::std::endl + << "held packages (the second form, see \033[1mbpkg-pkg-status(1)\033[0m), or all the held" << ::std::endl + << "packages that match any of the specified wildcard patterns (the third form)." << ::std::endl + << "Additionally, immediate or all dependencies of these packages can be also" << ::std::endl + << "updated by specifying the \033[1m--immediate\033[0m|\033[1m-i\033[0m\033[0m or \033[1m--recursive\033[0m|\033[1m-r\033[0m\033[0m options," << ::std::endl + << "respectively. Underneath, this command doesn't do much more than run \033[1mb update\033[0m" << ::std::endl + << "(or one of its update-for-*\033[0m variants; see \033[1m--for|-f\033[0m). In the first form the" << ::std::endl + << "specified packages must have been previously configured with \033[1mbpkg-pkg-build(1)\033[0m" << ::std::endl + << "or \033[1mbpkg-pkg-configure(1)\033[0m." << ::std::endl + << ::std::endl + << "Additional command line variables (\033[4mvars\033[0m, normally \033[1mconfig.*\033[0m) can be passed to" << ::std::endl + << "the build system. Such variables apply to all the specified packages but can" << ::std::endl + << "also be specified to only apply to specific packages using the argument" << ::std::endl + << "grouping mechanism (see \033[1mbpkg-argument-grouping(1)\033[0m for details)." << ::std::endl; + + p = ::bpkg::pkg_update_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[1mpkg-update\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-pkg-update.options" << ::std::endl + << ::std::endl + << "The following \033[1mpkg-update\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/pkg-update-options.hxx b/bpkg/pkg-update-options.hxx new file mode 100644 index 0000000..291af69 --- /dev/null +++ b/bpkg/pkg-update-options.hxx @@ -0,0 +1,137 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_UPDATE_OPTIONS_HXX +#define BPKG_PKG_UPDATE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class pkg_update_options: public ::bpkg::configuration_options + { + public: + pkg_update_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 pkg_update_options&); + + // Option accessors. + // + const bool& + all () const; + + const strings& + all_pattern () const; + + bool + all_pattern_specified () const; + + const bool& + immediate () const; + + const bool& + recursive () const; + + const string& + for_ () const; + + bool + for__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: + bool all_; + strings all_pattern_; + bool all_pattern_specified_; + bool immediate_; + bool recursive_; + string for__; + bool for__specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_update_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-update-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_UPDATE_OPTIONS_HXX diff --git a/bpkg/pkg-update-options.ixx b/bpkg/pkg-update-options.ixx new file mode 100644 index 0000000..d90eb44 --- /dev/null +++ b/bpkg/pkg-update-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 +{ + // pkg_update_options + // + + inline const bool& pkg_update_options:: + all () const + { + return this->all_; + } + + inline const strings& pkg_update_options:: + all_pattern () const + { + return this->all_pattern_; + } + + inline bool pkg_update_options:: + all_pattern_specified () const + { + return this->all_pattern_specified_; + } + + inline const bool& pkg_update_options:: + immediate () const + { + return this->immediate_; + } + + inline const bool& pkg_update_options:: + recursive () const + { + return this->recursive_; + } + + inline const string& pkg_update_options:: + for_ () const + { + return this->for__; + } + + inline bool pkg_update_options:: + for__specified () const + { + return this->for__specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/pkg-verify-options.cxx b/bpkg/pkg-verify-options.cxx new file mode 100644 index 0000000..8d5bc18 --- /dev/null +++ b/bpkg/pkg-verify-options.cxx @@ -0,0 +1,731 @@ +// -*- 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/pkg-verify-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // pkg_verify_options + // + + pkg_verify_options:: + pkg_verify_options () + : silent_ (), + deep_ (), + ignore_unknown_ (), + manifest_ () + { + } + + bool pkg_verify_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 pkg_verify_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 pkg_verify_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 pkg_verify_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 pkg_verify_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 pkg_verify_options:: + merge (const pkg_verify_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.silent_) + { + ::bpkg::cli::parser< bool>::merge ( + this->silent_, a.silent_); + } + + if (a.deep_) + { + ::bpkg::cli::parser< bool>::merge ( + this->deep_, a.deep_); + } + + if (a.ignore_unknown_) + { + ::bpkg::cli::parser< bool>::merge ( + this->ignore_unknown_, a.ignore_unknown_); + } + + if (a.manifest_) + { + ::bpkg::cli::parser< bool>::merge ( + this->manifest_, a.manifest_); + } + } + + ::bpkg::cli::usage_para pkg_verify_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[1mPKG-VERIFY OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--silent\033[0m Suppress the error messages about the reason why the" << ::std::endl + << " package is invalid. Just return the error status." << ::std::endl; + + os << std::endl + << "\033[1m--deep\033[0m Verify the presence of the required *-build\033[0m" << ::std::endl + << " values/files and the validity of files referenced by" << ::std::endl + << " the \033[1m*-file\033[0m manifest values." << ::std::endl; + + os << std::endl + << "\033[1m--ignore-unknown\033[0m Ignore unknown manifest entries. By default, \033[1mbpkg\033[0m" << ::std::endl + << " will refuse to declare such a package valid since it" << ::std::endl + << " cannot be sure the unknown entries are valid. Note" << ::std::endl + << " that this option also ignores the version constraints" << ::std::endl + << " in the special toolchain build-time dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--manifest\033[0m Instead of printing the successful verification" << ::std::endl + << " result in the human-readable form, dump the package" << ::std::endl + << " manifest to \033[1mstdout\033[0m. If the \033[1m--deep\033[0m option is" << ::std::endl + << " specified, then in the resulting manifest the \033[1m*-file\033[0m" << ::std::endl + << " values are replaced with the contents of the" << ::std::endl + << " referenced files, the *-build\033[0m values are" << ::std::endl + << " automatically added (unless the corresponding files" << ::std::endl + << " are absent), and the package dependency constraints" << ::std::endl + << " are completed." << ::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 (*) (pkg_verify_options&, ::bpkg::cli::scanner&)> + _cli_pkg_verify_options_map; + + static _cli_pkg_verify_options_map _cli_pkg_verify_options_map_; + + struct _cli_pkg_verify_options_map_init + { + _cli_pkg_verify_options_map_init () + { + _cli_pkg_verify_options_map_["--silent"] = + &::bpkg::cli::thunk< pkg_verify_options, &pkg_verify_options::silent_ >; + _cli_pkg_verify_options_map_["--deep"] = + &::bpkg::cli::thunk< pkg_verify_options, &pkg_verify_options::deep_ >; + _cli_pkg_verify_options_map_["--ignore-unknown"] = + &::bpkg::cli::thunk< pkg_verify_options, &pkg_verify_options::ignore_unknown_ >; + _cli_pkg_verify_options_map_["--manifest"] = + &::bpkg::cli::thunk< pkg_verify_options, &pkg_verify_options::manifest_ >; + } + }; + + static _cli_pkg_verify_options_map_init _cli_pkg_verify_options_map_init_; + + bool pkg_verify_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_pkg_verify_options_map::const_iterator i (_cli_pkg_verify_options_map_.find (o)); + + if (i != _cli_pkg_verify_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool pkg_verify_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_pkg_verify_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 pkg-verify\033[0m [\033[4moptions\033[0m] \033[4mfile\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mpkg-verify\033[0m command verifies that the specified archive file is a valid" << ::std::endl + << "\033[1mbpkg\033[0m package. Specifically, it checks that the file's name and the top-level" << ::std::endl + << "directory inside the archive match the canonical \033[4mname\033[0m\033[1m-\033[0m\033[4mversion\033[0m\033[0m form and that" << ::std::endl + << "there is a valid manifest file in that top-level directory. Additionally, if" << ::std::endl + << "the \033[1m--deep\033[0m option is specified, it also checks that the required *-build\033[0m" << ::std::endl + << "values/files are present in the manifest/archive and the files referenced by" << ::std::endl + << "the \033[1m*-file\033[0m manifest values are present in the archive and are not empty." << ::std::endl; + + p = ::bpkg::pkg_verify_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[1mpkg-verify\033[0m command the following options files are searched for in the" << ::std::endl + << "predefined directories (system, etc) and, if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-pkg-verify.options" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/pkg-verify-options.hxx b/bpkg/pkg-verify-options.hxx new file mode 100644 index 0000000..d4b1415 --- /dev/null +++ b/bpkg/pkg-verify-options.hxx @@ -0,0 +1,125 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_PKG_VERIFY_OPTIONS_HXX +#define BPKG_PKG_VERIFY_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class pkg_verify_options: public ::bpkg::common_options + { + public: + pkg_verify_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 pkg_verify_options&); + + // Option accessors. + // + const bool& + silent () const; + + const bool& + deep () const; + + const bool& + ignore_unknown () const; + + const bool& + manifest () 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 silent_; + bool deep_; + bool ignore_unknown_; + bool manifest_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_pkg_verify_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/pkg-verify-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_PKG_VERIFY_OPTIONS_HXX diff --git a/bpkg/pkg-verify-options.ixx b/bpkg/pkg-verify-options.ixx new file mode 100644 index 0000000..4e66b5a --- /dev/null +++ b/bpkg/pkg-verify-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 +{ + // pkg_verify_options + // + + inline const bool& pkg_verify_options:: + silent () const + { + return this->silent_; + } + + inline const bool& pkg_verify_options:: + deep () const + { + return this->deep_; + } + + inline const bool& pkg_verify_options:: + ignore_unknown () const + { + return this->ignore_unknown_; + } + + inline const bool& pkg_verify_options:: + manifest () const + { + return this->manifest_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-add-options.cxx b/bpkg/rep-add-options.cxx new file mode 100644 index 0000000..194a5d7 --- /dev/null +++ b/bpkg/rep-add-options.cxx @@ -0,0 +1,703 @@ +// -*- 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/rep-add-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_add_options + // + + rep_add_options:: + rep_add_options () + : type_ (), + type_specified_ (false) + { + } + + bool rep_add_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 rep_add_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 rep_add_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 rep_add_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 rep_add_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 rep_add_options:: + merge (const rep_add_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.type_specified_) + { + ::bpkg::cli::parser< repository_type>::merge ( + this->type_, a.type_); + this->type_specified_ = true; + } + } + + ::bpkg::cli::usage_para rep_add_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[1mREP-ADD OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--type\033[0m \033[4mtype\033[0m Specify the repository type with valid values being" << ::std::endl + << " \033[1mpkg\033[0m, \033[1mdir\033[0m, and \033[1mgit\033[0m." << ::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 (*) (rep_add_options&, ::bpkg::cli::scanner&)> + _cli_rep_add_options_map; + + static _cli_rep_add_options_map _cli_rep_add_options_map_; + + struct _cli_rep_add_options_map_init + { + _cli_rep_add_options_map_init () + { + _cli_rep_add_options_map_["--type"] = + &::bpkg::cli::thunk< rep_add_options, repository_type, &rep_add_options::type_, + &rep_add_options::type_specified_ >; + } + }; + + static _cli_rep_add_options_map_init _cli_rep_add_options_map_init_; + + bool rep_add_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_add_options_map::const_iterator i (_cli_rep_add_options_map_.find (o)); + + if (i != _cli_rep_add_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool rep_add_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_rep_add_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 rep-add\033[0m|\033[1madd\033[0m [\033[4moptions\033[0m] \033[4mrep-loc\033[0m...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mrep-add\033[0m command adds the specified package repositories to the" << ::std::endl + << "configuration. The repository location \033[4mrep-loc\033[0m is a URL or a directory path. If" << ::std::endl + << "a repository with the same canonical name already exists in the configuration," << ::std::endl + << "then its location is replaced with the specified." << ::std::endl + << ::std::endl + << "Note that this command doesn't fetch the list of available packages for the" << ::std::endl + << "newly added repository. For that, use the \033[1mbpkg-rep-fetch(1)\033[0m command, normally," << ::std::endl + << "after adding all the repositories you wish to use." << ::std::endl + << ::std::endl + << "Currently three types of repositories are supported: archive-based \033[1mpkg\033[0m," << ::std::endl + << "directory-based \033[1mdir\033[0m, and version control-based \033[1mgit\033[0m. See" << ::std::endl + << "\033[1mbpkg-repository-types(1)\033[0m for details on their structure and URL format." << ::std::endl + << ::std::endl + << "Normally the repository type can be automatically guessed by examining its URL" << ::std::endl + << "(for example, the presence of the \033[1m.git\033[0m extension) or, in case of a local" << ::std::endl + << "repository, its content (for example, the presence of the \033[1m.git/\033[0m subdirectory)." << ::std::endl + << "Without any identifying information the \033[1mpkg\033[0m type is assumed unless explicitly" << ::std::endl + << "specified with the \033[1m--type\033[0m option or in the URL scheme. Note, however, that the" << ::std::endl + << "\033[1mdir\033[0m repository type is never guessed since it is not easily distinguishable" << ::std::endl + << "from local \033[1mpkg\033[0m and \033[1mgit\033[0m repositories." << ::std::endl; + + p = ::bpkg::rep_add_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[1mrep-add\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-rep-add.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-add\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/rep-add-options.hxx b/bpkg/rep-add-options.hxx new file mode 100644 index 0000000..9e257c6 --- /dev/null +++ b/bpkg/rep-add-options.hxx @@ -0,0 +1,119 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_ADD_OPTIONS_HXX +#define BPKG_REP_ADD_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <libbpkg/manifest.hxx> + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class rep_add_options: public ::bpkg::configuration_options + { + public: + rep_add_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 rep_add_options&); + + // Option accessors. + // + const repository_type& + type () const; + + bool + type_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: + repository_type type_; + bool type_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_add_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-add-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_ADD_OPTIONS_HXX diff --git a/bpkg/rep-add-options.ixx b/bpkg/rep-add-options.ixx new file mode 100644 index 0000000..bfaa70f --- /dev/null +++ b/bpkg/rep-add-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 +{ + // rep_add_options + // + + inline const repository_type& rep_add_options:: + type () const + { + return this->type_; + } + + inline bool rep_add_options:: + type_specified () const + { + return this->type_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-create-options.cxx b/bpkg/rep-create-options.cxx new file mode 100644 index 0000000..3c8c1d1 --- /dev/null +++ b/bpkg/rep-create-options.cxx @@ -0,0 +1,727 @@ +// -*- 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/rep-create-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_create_options + // + + rep_create_options:: + rep_create_options () + : ignore_unknown_ (), + min_bpkg_version_ (), + min_bpkg_version_specified_ (false), + key_ (), + key_specified_ (false) + { + } + + bool rep_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 rep_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 rep_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 rep_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 rep_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 rep_create_options:: + merge (const rep_create_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.ignore_unknown_) + { + ::bpkg::cli::parser< bool>::merge ( + this->ignore_unknown_, a.ignore_unknown_); + } + + if (a.min_bpkg_version_specified_) + { + ::bpkg::cli::parser< butl::standard_version>::merge ( + this->min_bpkg_version_, a.min_bpkg_version_); + this->min_bpkg_version_specified_ = true; + } + + if (a.key_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->key_, a.key_); + this->key_specified_ = true; + } + } + + ::bpkg::cli::usage_para rep_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[1mREP-CREATE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--ignore-unknown\033[0m Ignore unknown manifest entries. Note that this" << ::std::endl + << " option also ignores the version constraints in the" << ::std::endl + << " special toolchain build-time dependencies." << ::std::endl; + + os << std::endl + << "\033[1m--min-bpkg-version\033[0m \033[4mver\033[0m Apply backward compatibility workarounds to the" << ::std::endl + << " generated \033[1mpackages.manifest\033[0m file so that it can be" << ::std::endl + << " consumed by \033[1mbpkg\033[0m versions greater or equal to the" << ::std::endl + << " specified version. If unspecified, then the" << ::std::endl + << " \033[1mmin-bpkg-version\033[0m value from the" << ::std::endl + << " \033[1mrepositories.manifest\033[0m file is used, if present. If" << ::std::endl + << " the manifest value is not specified either, then no" << ::std::endl + << " backward compatibility workarounds are applied." << ::std::endl; + + os << std::endl + << "\033[1m--key\033[0m \033[4mname\033[0m Private key to use to sign the repository. In most" << ::std::endl + << " cases \033[4mname\033[0m will be a path to the key file but it can" << ::std::endl + << " also be a key id when a custom \033[1mopenssl\033[0m cryptographic" << ::std::endl + << " engine is used." << ::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 (*) (rep_create_options&, ::bpkg::cli::scanner&)> + _cli_rep_create_options_map; + + static _cli_rep_create_options_map _cli_rep_create_options_map_; + + struct _cli_rep_create_options_map_init + { + _cli_rep_create_options_map_init () + { + _cli_rep_create_options_map_["--ignore-unknown"] = + &::bpkg::cli::thunk< rep_create_options, &rep_create_options::ignore_unknown_ >; + _cli_rep_create_options_map_["--min-bpkg-version"] = + &::bpkg::cli::thunk< rep_create_options, butl::standard_version, &rep_create_options::min_bpkg_version_, + &rep_create_options::min_bpkg_version_specified_ >; + _cli_rep_create_options_map_["--key"] = + &::bpkg::cli::thunk< rep_create_options, string, &rep_create_options::key_, + &rep_create_options::key_specified_ >; + } + }; + + static _cli_rep_create_options_map_init _cli_rep_create_options_map_init_; + + bool rep_create_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_create_options_map::const_iterator i (_cli_rep_create_options_map_.find (o)); + + if (i != _cli_rep_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 rep_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_rep_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 rep-create\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[1mrep-create\033[0m command regenerates the \033[1mpackages.manifest\033[0m file based on the" << ::std::endl + << "files present in the repository directory. If the \033[1mrepositories.manifest\033[0m file" << ::std::endl + << "contains a certificate, then the \033[1msignature.manifest\033[0m file is regenerated as" << ::std::endl + << "well. In this case the \033[1m--key\033[0m option must be used to specify the certificate's" << ::std::endl + << "private key. If \033[4mdir\033[0m is not specified, then the current working directory is" << ::std::endl + << "used as the repository root." << ::std::endl; + + p = ::bpkg::rep_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[1mrep-create\033[0m command the search start directory is the repository" << ::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-rep-create.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-create\033[0m command options cannot be specified in the remote" << ::std::endl + << "default options files:" << ::std::endl + << ::std::endl + << "--key" << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/rep-create-options.hxx b/bpkg/rep-create-options.hxx new file mode 100644 index 0000000..9afb227 --- /dev/null +++ b/bpkg/rep-create-options.hxx @@ -0,0 +1,129 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_CREATE_OPTIONS_HXX +#define BPKG_REP_CREATE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class rep_create_options: public ::bpkg::common_options + { + public: + rep_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 rep_create_options&); + + // Option accessors. + // + const bool& + ignore_unknown () const; + + const butl::standard_version& + min_bpkg_version () const; + + bool + min_bpkg_version_specified () const; + + const string& + key () const; + + bool + key_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: + bool ignore_unknown_; + butl::standard_version min_bpkg_version_; + bool min_bpkg_version_specified_; + string key_; + bool key_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_create_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-create-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_CREATE_OPTIONS_HXX diff --git a/bpkg/rep-create-options.ixx b/bpkg/rep-create-options.ixx new file mode 100644 index 0000000..cf0a734 --- /dev/null +++ b/bpkg/rep-create-options.ixx @@ -0,0 +1,51 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // rep_create_options + // + + inline const bool& rep_create_options:: + ignore_unknown () const + { + return this->ignore_unknown_; + } + + inline const butl::standard_version& rep_create_options:: + min_bpkg_version () const + { + return this->min_bpkg_version_; + } + + inline bool rep_create_options:: + min_bpkg_version_specified () const + { + return this->min_bpkg_version_specified_; + } + + inline const string& rep_create_options:: + key () const + { + return this->key_; + } + + inline bool rep_create_options:: + key_specified () const + { + return this->key_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-fetch-options.cxx b/bpkg/rep-fetch-options.cxx new file mode 100644 index 0000000..a9f336d --- /dev/null +++ b/bpkg/rep-fetch-options.cxx @@ -0,0 +1,694 @@ +// -*- 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/rep-fetch-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_fetch_options + // + + rep_fetch_options:: + rep_fetch_options () + : shallow_ () + { + } + + bool rep_fetch_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 rep_fetch_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 rep_fetch_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 rep_fetch_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 rep_fetch_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 rep_fetch_options:: + merge (const rep_fetch_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.shallow_) + { + ::bpkg::cli::parser< bool>::merge ( + this->shallow_, a.shallow_); + } + } + + ::bpkg::cli::usage_para rep_fetch_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[1mREP-FETCH OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--shallow\033[0m Do not re-fetch complement and prerequisite" << ::std::endl + << " repositories of the specified repositories unless the" << ::std::endl + << " set of complements and/or prerequisites has changed." << ::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 (*) (rep_fetch_options&, ::bpkg::cli::scanner&)> + _cli_rep_fetch_options_map; + + static _cli_rep_fetch_options_map _cli_rep_fetch_options_map_; + + struct _cli_rep_fetch_options_map_init + { + _cli_rep_fetch_options_map_init () + { + _cli_rep_fetch_options_map_["--shallow"] = + &::bpkg::cli::thunk< rep_fetch_options, &rep_fetch_options::shallow_ >; + } + }; + + static _cli_rep_fetch_options_map_init _cli_rep_fetch_options_map_init_; + + bool rep_fetch_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_fetch_options_map::const_iterator i (_cli_rep_fetch_options_map_.find (o)); + + if (i != _cli_rep_fetch_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool rep_fetch_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_rep_fetch_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 rep-fetch\033[0m|\033[1mfetch\033[0m [\033[4moptions\033[0m] [(\033[4mrep-name\033[0m | \033[4mrep-loc\033[0m)...]\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mrep-fetch\033[0m command fetches the list of available packages for the specified" << ::std::endl + << "repositories as well as all their complement and prerequisite repositories," << ::std::endl + << "recursively. If no repositories were specified, then all the repositories" << ::std::endl + << "previously added (\033[1mbpkg-rep-add(1)\033[0m) to the configuration are fetched." << ::std::endl + << ::std::endl + << "The repository to fetch can be specified either as a repository name or as a" << ::std::endl + << "repository location (URL or a directory path; see \033[1mbpkg-rep-add(1)\033[0m for details)." << ::std::endl + << "In the latter case, the repository location is added/replaced as if by first" << ::std::endl + << "executing the \033[1mrep-add\033[0m command." << ::std::endl + << ::std::endl + << "Note that fetching only a specific repository that happens to be a prerequisite" << ::std::endl + << "or complete of another repository not being fetched may result in an" << ::std::endl + << "inconsistent repository state." << ::std::endl; + + p = ::bpkg::rep_fetch_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[1mrep-fetch\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-rep-fetch.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-fetch\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/rep-fetch-options.hxx b/bpkg/rep-fetch-options.hxx new file mode 100644 index 0000000..01ed16e --- /dev/null +++ b/bpkg/rep-fetch-options.hxx @@ -0,0 +1,113 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_FETCH_OPTIONS_HXX +#define BPKG_REP_FETCH_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class rep_fetch_options: public ::bpkg::configuration_options + { + public: + rep_fetch_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 rep_fetch_options&); + + // Option accessors. + // + const bool& + shallow () 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 shallow_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_fetch_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-fetch-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_FETCH_OPTIONS_HXX diff --git a/bpkg/rep-fetch-options.ixx b/bpkg/rep-fetch-options.ixx new file mode 100644 index 0000000..283f304 --- /dev/null +++ b/bpkg/rep-fetch-options.ixx @@ -0,0 +1,27 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // rep_fetch_options + // + + inline const bool& rep_fetch_options:: + shallow () const + { + return this->shallow_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-info-options.cxx b/bpkg/rep-info-options.cxx new file mode 100644 index 0000000..e714f2e --- /dev/null +++ b/bpkg/rep-info-options.cxx @@ -0,0 +1,902 @@ +// -*- 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/rep-info-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_info_options + // + + rep_info_options:: + rep_info_options () + : name_ (), + cert_fingerprint_ (), + cert_name_ (), + cert_organization_ (), + cert_email_ (), + repositories_ (), + packages_ (), + manifest_ (), + ignore_unknown_ (), + deep_ (), + repositories_file_ (), + repositories_file_specified_ (false), + packages_file_ (), + packages_file_specified_ (false), + type_ (), + type_specified_ (false), + directory_ (), + directory_specified_ (false) + { + } + + bool rep_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 rep_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 rep_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 rep_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 rep_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 rep_info_options:: + merge (const rep_info_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // common_options base + // + ::bpkg::common_options::merge (a); + + if (a.name_) + { + ::bpkg::cli::parser< bool>::merge ( + this->name_, a.name_); + } + + if (a.cert_fingerprint_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cert_fingerprint_, a.cert_fingerprint_); + } + + if (a.cert_name_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cert_name_, a.cert_name_); + } + + if (a.cert_organization_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cert_organization_, a.cert_organization_); + } + + if (a.cert_email_) + { + ::bpkg::cli::parser< bool>::merge ( + this->cert_email_, a.cert_email_); + } + + if (a.repositories_) + { + ::bpkg::cli::parser< bool>::merge ( + this->repositories_, a.repositories_); + } + + if (a.packages_) + { + ::bpkg::cli::parser< bool>::merge ( + this->packages_, a.packages_); + } + + if (a.manifest_) + { + ::bpkg::cli::parser< bool>::merge ( + this->manifest_, a.manifest_); + } + + if (a.ignore_unknown_) + { + ::bpkg::cli::parser< bool>::merge ( + this->ignore_unknown_, a.ignore_unknown_); + } + + if (a.deep_) + { + ::bpkg::cli::parser< bool>::merge ( + this->deep_, a.deep_); + } + + if (a.repositories_file_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->repositories_file_, a.repositories_file_); + this->repositories_file_specified_ = true; + } + + if (a.packages_file_specified_) + { + ::bpkg::cli::parser< path>::merge ( + this->packages_file_, a.packages_file_); + this->packages_file_specified_ = true; + } + + if (a.type_specified_) + { + ::bpkg::cli::parser< repository_type>::merge ( + this->type_, a.type_); + this->type_specified_ = true; + } + + if (a.directory_specified_) + { + ::bpkg::cli::parser< string>::merge ( + this->directory_, a.directory_); + this->directory_specified_ = true; + } + } + + ::bpkg::cli::usage_para rep_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[1mREP-INFO OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--name\033[0m|\033[1m-n\033[0m Print the repository's name and location." << ::std::endl; + + os << std::endl + << "\033[1m--cert-fingerprint\033[0m Print the repository's certificate fingerprint or" << ::std::endl + << " empty line if the repository is unsigned." << ::std::endl; + + os << std::endl + << "\033[1m--cert-name\033[0m Print the repository's certificate common name (CN)" << ::std::endl + << " or empty line if the repository is unsigned." << ::std::endl; + + os << std::endl + << "\033[1m--cert-organization\033[0m Print the repository's certificate organization name" << ::std::endl + << " (O) or empty line if the repository is unsigned." << ::std::endl; + + os << std::endl + << "\033[1m--cert-email\033[0m Print the repository's certificate email or empty" << ::std::endl + << " line if the repository is unsigned." << ::std::endl; + + os << std::endl + << "\033[1m--repositories\033[0m|\033[1m-r\033[0m Print the list of complement and prerequisite" << ::std::endl + << " repositories." << ::std::endl; + + os << std::endl + << "\033[1m--packages\033[0m|\033[1m-p\033[0m Print the list of available packages." << ::std::endl; + + os << std::endl + << "\033[1m--manifest\033[0m Instead of printing the information in the" << ::std::endl + << " human-readable form, dump it (to \033[1mstdout\033[0m) as" << ::std::endl + << " manifest(s). Normally you would use this option in" << ::std::endl + << " combination with \033[1m--packages|-p\033[0m or \033[1m--repositories|-r\033[0m" << ::std::endl + << " to only dump one of the manifests. If the \033[1m--deep\033[0m" << ::std::endl + << " option is specified, then in the resulting packages" << ::std::endl + << " manifest the \033[1m*-file\033[0m values are replaced with the" << ::std::endl + << " contents of the referenced files and the *-build\033[0m" << ::std::endl + << " values are automatically added (unless the" << ::std::endl + << " corresponding files are absent). See also" << ::std::endl + << " \033[1m--ignore-unknown\033[0m, \033[1m--repositories-file\033[0m, and" << ::std::endl + << " \033[1m--packages-file\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--ignore-unknown\033[0m Ignore unknown manifest entries. Note that this" << ::std::endl + << " option also ignores the version constraints in the" << ::std::endl + << " special toolchain build-time dependencies. This" << ::std::endl + << " option is implied if \033[1m--manifest\033[0m is not specified." << ::std::endl; + + os << std::endl + << "\033[1m--deep\033[0m Verify the presence of the required *-build\033[0m" << ::std::endl + << " values/files and the validity of files referenced by" << ::std::endl + << " the \033[1m*-file\033[0m manifest values." << ::std::endl; + + os << std::endl + << "\033[1m--repositories-file\033[0m \033[4mpath\033[0m If \033[1m--manifest\033[0m is specified, then save the" << ::std::endl + << " repositories manifest to the specified file instead" << ::std::endl + << " of dumping it to \033[1mstdout\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--packages-file\033[0m \033[4mpath\033[0m If \033[1m--manifest\033[0m is specified, then save the packages" << ::std::endl + << " manifest to the specified file instead of dumping it" << ::std::endl + << " to \033[1mstdout\033[0m." << ::std::endl; + + os << std::endl + << "\033[1m--type\033[0m \033[4mtype\033[0m Specify the repository type with valid values being" << ::std::endl + << " \033[1mpkg\033[0m, \033[1mdir\033[0m, and \033[1mgit\033[0m. Refer to \033[1mbpkg-rep-add(1)\033[0m for" << ::std::endl + << " details." << ::std::endl; + + os << std::endl + << "\033[1m--directory\033[0m|\033[1m-d\033[0m \033[4mdir\033[0m Use configuration in \033[4mdir\033[0m for the trusted certificate" << ::std::endl + << " database." << ::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 (*) (rep_info_options&, ::bpkg::cli::scanner&)> + _cli_rep_info_options_map; + + static _cli_rep_info_options_map _cli_rep_info_options_map_; + + struct _cli_rep_info_options_map_init + { + _cli_rep_info_options_map_init () + { + _cli_rep_info_options_map_["--name"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::name_ >; + _cli_rep_info_options_map_["-n"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::name_ >; + _cli_rep_info_options_map_["--cert-fingerprint"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::cert_fingerprint_ >; + _cli_rep_info_options_map_["--cert-name"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::cert_name_ >; + _cli_rep_info_options_map_["--cert-organization"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::cert_organization_ >; + _cli_rep_info_options_map_["--cert-email"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::cert_email_ >; + _cli_rep_info_options_map_["--repositories"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::repositories_ >; + _cli_rep_info_options_map_["-r"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::repositories_ >; + _cli_rep_info_options_map_["--packages"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::packages_ >; + _cli_rep_info_options_map_["-p"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::packages_ >; + _cli_rep_info_options_map_["--manifest"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::manifest_ >; + _cli_rep_info_options_map_["--ignore-unknown"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::ignore_unknown_ >; + _cli_rep_info_options_map_["--deep"] = + &::bpkg::cli::thunk< rep_info_options, &rep_info_options::deep_ >; + _cli_rep_info_options_map_["--repositories-file"] = + &::bpkg::cli::thunk< rep_info_options, path, &rep_info_options::repositories_file_, + &rep_info_options::repositories_file_specified_ >; + _cli_rep_info_options_map_["--packages-file"] = + &::bpkg::cli::thunk< rep_info_options, path, &rep_info_options::packages_file_, + &rep_info_options::packages_file_specified_ >; + _cli_rep_info_options_map_["--type"] = + &::bpkg::cli::thunk< rep_info_options, repository_type, &rep_info_options::type_, + &rep_info_options::type_specified_ >; + _cli_rep_info_options_map_["--directory"] = + &::bpkg::cli::thunk< rep_info_options, string, &rep_info_options::directory_, + &rep_info_options::directory_specified_ >; + _cli_rep_info_options_map_["-d"] = + &::bpkg::cli::thunk< rep_info_options, string, &rep_info_options::directory_, + &rep_info_options::directory_specified_ >; + } + }; + + static _cli_rep_info_options_map_init _cli_rep_info_options_map_init_; + + bool rep_info_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_info_options_map::const_iterator i (_cli_rep_info_options_map_.find (o)); + + if (i != _cli_rep_info_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // common_options base + // + if (::bpkg::common_options::_parse (o, s)) + return true; + + return false; + } + + bool rep_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_rep_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 rep-info\033[0m [\033[4moptions\033[0m] \033[4mrep-loc\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mrep-info\033[0m command prints various information about the specified repository." << ::std::endl + << "By default it print the repository's name and location as the first line. If" << ::std::endl + << "the repository is signed, the certificate information (name/organization/email)" << ::std::endl + << "is printed as the next line followed by the certificate fingerprint. Then comes" << ::std::endl + << "the list of complement and prerequisite repositories followed by the list of" << ::std::endl + << "available packages." << ::std::endl + << ::std::endl + << "This default format can be altered in various ways using options listed below." << ::std::endl + << "Note also that the information is written to \033[1mstdout\033[0m, not \033[1mstderr\033[0m." << ::std::endl + << ::std::endl + << "If the current working directory contains a \033[1mbpkg\033[0m configuration, then \033[1mrep-info\033[0m" << ::std::endl + << "will use its certificate database for the repository authentication. That is," << ::std::endl + << "it will trust the repository's certificate if it is already trusted by the" << ::std::endl + << "configuration. Otherwise it will add the certificate to the configuration if" << ::std::endl + << "you confirm it is trusted. You can specify an alternative configuration" << ::std::endl + << "directory with the \033[1m--directory|-d\033[0m option. To disable using the configuration in" << ::std::endl + << "the current working directory pass this option with an empty path." << ::std::endl; + + p = ::bpkg::rep_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 + << "If the \033[1mrep-info\033[0m command uses an existing bpkg\033[0m configuration, then the start" << ::std::endl + << "directory is the configuration directory. Otherwise, only the predefined" << ::std::endl + << "directories (home, system, etc) are searched. The following options files are" << ::std::endl + << "searched for in each directory and, if found, loaded in the order listed:" << ::std::endl + << ::std::endl + << "bpkg.options" << ::std::endl + << "bpkg-rep-info.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-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/rep-info-options.hxx b/bpkg/rep-info-options.hxx new file mode 100644 index 0000000..8e040da --- /dev/null +++ b/bpkg/rep-info-options.hxx @@ -0,0 +1,183 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_INFO_OPTIONS_HXX +#define BPKG_REP_INFO_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <libbpkg/manifest.hxx> + +#include <bpkg/common-options.hxx> + +namespace bpkg +{ + class rep_info_options: public ::bpkg::common_options + { + public: + rep_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 rep_info_options&); + + // Option accessors. + // + const bool& + name () const; + + const bool& + cert_fingerprint () const; + + const bool& + cert_name () const; + + const bool& + cert_organization () const; + + const bool& + cert_email () const; + + const bool& + repositories () const; + + const bool& + packages () const; + + const bool& + manifest () const; + + const bool& + ignore_unknown () const; + + const bool& + deep () const; + + const path& + repositories_file () const; + + bool + repositories_file_specified () const; + + const path& + packages_file () const; + + bool + packages_file_specified () const; + + const repository_type& + type () const; + + bool + type_specified () const; + + const string& + 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: + bool name_; + bool cert_fingerprint_; + bool cert_name_; + bool cert_organization_; + bool cert_email_; + bool repositories_; + bool packages_; + bool manifest_; + bool ignore_unknown_; + bool deep_; + path repositories_file_; + bool repositories_file_specified_; + path packages_file_; + bool packages_file_specified_; + repository_type type_; + bool type_specified_; + string directory_; + bool directory_specified_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_info_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-info-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_INFO_OPTIONS_HXX diff --git a/bpkg/rep-info-options.ixx b/bpkg/rep-info-options.ixx new file mode 100644 index 0000000..7aa219f --- /dev/null +++ b/bpkg/rep-info-options.ixx @@ -0,0 +1,129 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +// Begin prologue. +// +// +// End prologue. + +namespace bpkg +{ + // rep_info_options + // + + inline const bool& rep_info_options:: + name () const + { + return this->name_; + } + + inline const bool& rep_info_options:: + cert_fingerprint () const + { + return this->cert_fingerprint_; + } + + inline const bool& rep_info_options:: + cert_name () const + { + return this->cert_name_; + } + + inline const bool& rep_info_options:: + cert_organization () const + { + return this->cert_organization_; + } + + inline const bool& rep_info_options:: + cert_email () const + { + return this->cert_email_; + } + + inline const bool& rep_info_options:: + repositories () const + { + return this->repositories_; + } + + inline const bool& rep_info_options:: + packages () const + { + return this->packages_; + } + + inline const bool& rep_info_options:: + manifest () const + { + return this->manifest_; + } + + inline const bool& rep_info_options:: + ignore_unknown () const + { + return this->ignore_unknown_; + } + + inline const bool& rep_info_options:: + deep () const + { + return this->deep_; + } + + inline const path& rep_info_options:: + repositories_file () const + { + return this->repositories_file_; + } + + inline bool rep_info_options:: + repositories_file_specified () const + { + return this->repositories_file_specified_; + } + + inline const path& rep_info_options:: + packages_file () const + { + return this->packages_file_; + } + + inline bool rep_info_options:: + packages_file_specified () const + { + return this->packages_file_specified_; + } + + inline const repository_type& rep_info_options:: + type () const + { + return this->type_; + } + + inline bool rep_info_options:: + type_specified () const + { + return this->type_specified_; + } + + inline const string& rep_info_options:: + directory () const + { + return this->directory_; + } + + inline bool rep_info_options:: + directory_specified () const + { + return this->directory_specified_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-list-options.cxx b/bpkg/rep-list-options.cxx new file mode 100644 index 0000000..c1f456c --- /dev/null +++ b/bpkg/rep-list-options.cxx @@ -0,0 +1,701 @@ +// -*- 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/rep-list-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_list_options + // + + rep_list_options:: + rep_list_options () + : complements_ (), + prerequisites_ () + { + } + + bool rep_list_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 rep_list_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 rep_list_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 rep_list_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 rep_list_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 rep_list_options:: + merge (const rep_list_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.complements_) + { + ::bpkg::cli::parser< bool>::merge ( + this->complements_, a.complements_); + } + + if (a.prerequisites_) + { + ::bpkg::cli::parser< bool>::merge ( + this->prerequisites_, a.prerequisites_); + } + } + + ::bpkg::cli::usage_para rep_list_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[1mREP-LIST OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--complements\033[0m|\033[1m-c\033[0m List complement repositories." << ::std::endl; + + os << std::endl + << "\033[1m--prerequisites\033[0m|\033[1m-p\033[0m List prerequisite repositories." << ::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 (*) (rep_list_options&, ::bpkg::cli::scanner&)> + _cli_rep_list_options_map; + + static _cli_rep_list_options_map _cli_rep_list_options_map_; + + struct _cli_rep_list_options_map_init + { + _cli_rep_list_options_map_init () + { + _cli_rep_list_options_map_["--complements"] = + &::bpkg::cli::thunk< rep_list_options, &rep_list_options::complements_ >; + _cli_rep_list_options_map_["-c"] = + &::bpkg::cli::thunk< rep_list_options, &rep_list_options::complements_ >; + _cli_rep_list_options_map_["--prerequisites"] = + &::bpkg::cli::thunk< rep_list_options, &rep_list_options::prerequisites_ >; + _cli_rep_list_options_map_["-p"] = + &::bpkg::cli::thunk< rep_list_options, &rep_list_options::prerequisites_ >; + } + }; + + static _cli_rep_list_options_map_init _cli_rep_list_options_map_init_; + + bool rep_list_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_list_options_map::const_iterator i (_cli_rep_list_options_map_.find (o)); + + if (i != _cli_rep_list_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool rep_list_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_rep_list_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 rep-list\033[0m|\033[1mlist\033[0m [\033[4moptions\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mrep-list\033[0m command lists the repositories in the configuration." << ::std::endl + << ::std::endl + << "For each repository a line containing the repository name and location is" << ::std::endl + << "printed to \033[1mstdout\033[0m. If the \033[1m--complements|-c\033[0m and/or \033[1m--prerequisites|-p\033[0m options" << ::std::endl + << "are specified, then it is followed by the list of complement and/or" << ::std::endl + << "prerequisite repositories, recursively." << ::std::endl; + + p = ::bpkg::rep_list_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[1mrep-list\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-rep-list.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-list\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/rep-list-options.hxx b/bpkg/rep-list-options.hxx new file mode 100644 index 0000000..a736975 --- /dev/null +++ b/bpkg/rep-list-options.hxx @@ -0,0 +1,119 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_LIST_OPTIONS_HXX +#define BPKG_REP_LIST_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <libbpkg/manifest.hxx> + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class rep_list_options: public ::bpkg::configuration_options + { + public: + rep_list_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 rep_list_options&); + + // Option accessors. + // + const bool& + complements () const; + + const bool& + prerequisites () 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 complements_; + bool prerequisites_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_list_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-list-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_LIST_OPTIONS_HXX diff --git a/bpkg/rep-list-options.ixx b/bpkg/rep-list-options.ixx new file mode 100644 index 0000000..babc7a0 --- /dev/null +++ b/bpkg/rep-list-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 +{ + // rep_list_options + // + + inline const bool& rep_list_options:: + complements () const + { + return this->complements_; + } + + inline const bool& rep_list_options:: + prerequisites () const + { + return this->prerequisites_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/rep-remove-options.cxx b/bpkg/rep-remove-options.cxx new file mode 100644 index 0000000..ffe44be --- /dev/null +++ b/bpkg/rep-remove-options.cxx @@ -0,0 +1,704 @@ +// -*- 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/rep-remove-options.hxx> + +#include <map> +#include <set> +#include <string> +#include <vector> +#include <utility> +#include <ostream> +#include <sstream> +#include <cstring> + +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, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (s.more ()) + { + const char* v (s.next ()); + + if (std::strcmp (v, "1") == 0 || + std::strcmp (v, "true") == 0 || + std::strcmp (v, "TRUE") == 0 || + std::strcmp (v, "True") == 0) + x = true; + else if (std::strcmp (v, "0") == 0 || + std::strcmp (v, "false") == 0 || + std::strcmp (v, "FALSE") == 0 || + std::strcmp (v, "False") == 0) + x = false; + else + throw invalid_value (o, v); + } + else + throw missing_value (o); + + xs = 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 K, typename V, typename C> + struct parser<std::multimap<K, V, C> > + { + static void + parse (std::multimap<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.insert (typename std::multimap<K, V, C>::value_type (k, v)); + } + else + throw missing_value (o); + + xs = true; + } + + static void + merge (std::multimap<K, V, C>& b, const std::multimap<K, V, C>& a) + { + for (typename std::multimap<K, V, C>::const_iterator i (a.begin ()); + i != a.end (); + ++i) + b.insert (typename std::multimap<K, V, C>::value_type (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, bool X::*M> + void + thunk (X& x, scanner& s) + { + s.next (); + x.*M = true; + } + + 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> + +namespace bpkg +{ + // rep_remove_options + // + + rep_remove_options:: + rep_remove_options () + : all_ (), + clean_ () + { + } + + bool rep_remove_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 rep_remove_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 rep_remove_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 rep_remove_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 rep_remove_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 rep_remove_options:: + merge (const rep_remove_options& a) + { + CLI_POTENTIALLY_UNUSED (a); + + // configuration_options base + // + ::bpkg::configuration_options::merge (a); + + if (a.all_) + { + ::bpkg::cli::parser< bool>::merge ( + this->all_, a.all_); + } + + if (a.clean_) + { + ::bpkg::cli::parser< bool>::merge ( + this->clean_, a.clean_); + } + } + + ::bpkg::cli::usage_para rep_remove_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[1mREP-REMOVE OPTIONS\033[0m" << ::std::endl; + + os << std::endl + << "\033[1m--all\033[0m|\033[1m-a\033[0m Remove all the repositories." << ::std::endl; + + os << std::endl + << "\033[1m--clean\033[0m Clean the repository state." << ::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 (*) (rep_remove_options&, ::bpkg::cli::scanner&)> + _cli_rep_remove_options_map; + + static _cli_rep_remove_options_map _cli_rep_remove_options_map_; + + struct _cli_rep_remove_options_map_init + { + _cli_rep_remove_options_map_init () + { + _cli_rep_remove_options_map_["--all"] = + &::bpkg::cli::thunk< rep_remove_options, &rep_remove_options::all_ >; + _cli_rep_remove_options_map_["-a"] = + &::bpkg::cli::thunk< rep_remove_options, &rep_remove_options::all_ >; + _cli_rep_remove_options_map_["--clean"] = + &::bpkg::cli::thunk< rep_remove_options, &rep_remove_options::clean_ >; + } + }; + + static _cli_rep_remove_options_map_init _cli_rep_remove_options_map_init_; + + bool rep_remove_options:: + _parse (const char* o, ::bpkg::cli::scanner& s) + { + _cli_rep_remove_options_map::const_iterator i (_cli_rep_remove_options_map_.find (o)); + + if (i != _cli_rep_remove_options_map_.end ()) + { + (*(i->second)) (*this, s); + return true; + } + + // configuration_options base + // + if (::bpkg::configuration_options::_parse (o, s)) + return true; + + return false; + } + + bool rep_remove_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_rep_remove_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 rep-remove\033[0m|\033[1mremove\033[0m [\033[4moptions\033[0m] (\033[4mrep-name\033[0m|\033[4mrep-loc\033[0m)..." << ::std::endl + << "\033[1mbpkg rep-remove\033[0m|\033[1mremove\033[0m [\033[4moptions\033[0m] \033[1m--all\033[0m|\033[1m-a\033[0m" << ::std::endl + << "\033[1mbpkg rep-remove\033[0m|\033[1mremove\033[0m [\033[4moptions\033[0m] \033[1m--clean\033[0m\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The \033[1mrep-remove\033[0m command removes the specified package repositories from the" << ::std::endl + << "configuration. The repository to remove can be specified either as a repository" << ::std::endl + << "name or as a repository location (URL or a directory path)." << ::std::endl + << ::std::endl + << "Alternatively, the \033[1m--all|-a\033[0m option can be used to remove all the repositories" << ::std::endl + << "that were previously added (\033[1mbpkg-rep-add(1)\033[0m) to the configuration." << ::std::endl + << ::std::endl + << "Finally, the \033[1m--clean\033[0m option can be used to revert the repositories to the clean" << ::std::endl + << "state, as if they were added but never fetched." << ::std::endl; + + p = ::bpkg::rep_remove_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[1mpkg-rep-remove\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-rep-remove.options" << ::std::endl + << ::std::endl + << "The following \033[1mrep-remove\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/rep-remove-options.hxx b/bpkg/rep-remove-options.hxx new file mode 100644 index 0000000..eedbe27 --- /dev/null +++ b/bpkg/rep-remove-options.hxx @@ -0,0 +1,119 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REP_REMOVE_OPTIONS_HXX +#define BPKG_REP_REMOVE_OPTIONS_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <libbpkg/manifest.hxx> + +#include <bpkg/configuration-options.hxx> + +namespace bpkg +{ + class rep_remove_options: public ::bpkg::configuration_options + { + public: + rep_remove_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 rep_remove_options&); + + // Option accessors. + // + const bool& + all () const; + + const bool& + clean () 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 all_; + bool clean_; + }; +} + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_rep_remove_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +#include <bpkg/rep-remove-options.ixx> + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REP_REMOVE_OPTIONS_HXX diff --git a/bpkg/rep-remove-options.ixx b/bpkg/rep-remove-options.ixx new file mode 100644 index 0000000..b8ec8ba --- /dev/null +++ b/bpkg/rep-remove-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 +{ + // rep_remove_options + // + + inline const bool& rep_remove_options:: + all () const + { + return this->all_; + } + + inline const bool& rep_remove_options:: + clean () const + { + return this->clean_; + } +} + +// Begin epilogue. +// +// +// End epilogue. diff --git a/bpkg/repository-signing.cxx b/bpkg/repository-signing.cxx new file mode 100644 index 0000000..66366cb --- /dev/null +++ b/bpkg/repository-signing.cxx @@ -0,0 +1,205 @@ +// -*- 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/repository-signing.hxx> + +#include <map> + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_repository_signing_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 rep-create --key\033[0m ...\033[0m" << ::std::endl + << ::std::endl + << "\033[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "The purpose of signing a repository is to prevent tampering with packages" << ::std::endl + << "either during transmission or on the repository \033[4mhost machine\033[0m. Ideally, you" << ::std::endl + << "would generate and sign the repository manifests on a separate \033[4mbuild machine\033[0m" << ::std::endl + << "that is behind a firewall. This way, if (or, really, when) your host machine is" << ::std::endl + << "compromised, it will be difficult for an attacker to compromise the repository" << ::std::endl + << "packages without being noticed. Since the repository key is kept on the build" << ::std::endl + << "machine (or, better yet, on a \033[4mone-way\033[0m PIV/PKCS#11 device; see below) they will" << ::std::endl + << "not be able to re-sign the modified repository." << ::std::endl + << ::std::endl + << "\033[1mbpkg\033[0m uses X.509 public key cryptography for repository signing. Currently, only" << ::std::endl + << "the explicit \033[4mfirst use\033[0m certificate authentication is implemented. That is, for" << ::std::endl + << "an unknown (to this \033[1mbpkg\033[0m configuration) repository certificate its subject" << ::std::endl + << "information and fingerprint are presented to the user. If the user confirms the" << ::std::endl + << "authenticity of the certificate, then it is added to the configuration and any" << ::std::endl + << "repository that in the future presents this certificate is trusted without" << ::std::endl + << "further confirmations, provided its name matches the certificate's subject (see" << ::std::endl + << "below). In the future a certificate authority (CA)-based model may be added." << ::std::endl + << ::std::endl + << "The rest of this guide shows how to create a key/certificate pair for \033[1mpkg\033[0m" << ::std::endl + << "repository signing and use it to sign a repository. At the end it also briefly" << ::std::endl + << "explains how to store the private key on a PIV/PKCS#11 device using Yubikey 4" << ::std::endl + << "as an example." << ::std::endl + << ::std::endl + << "1. Generate Private Key" << ::std::endl + << ::std::endl + << " The first step is to generate the private key:" << ::std::endl + << ::std::endl + << " $ openssl genrsa -aes256 2048 >key.pem" << ::std::endl + << ::std::endl + << " If you would like to generate a key without password protection (not a good" << ::std::endl + << " idea except for testing), leave the \033[1m-aes256\033[0m option out. You may also need" << ::std::endl + << " to add \033[1m-nodes\033[0m depending on your \033[1mopenssl(1)\033[0m configuration." << ::std::endl + << ::std::endl + << "2. Generate Certificate" << ::std::endl + << ::std::endl + << " Next create the certificate configuration file by saving the following into" << ::std::endl + << " \033[1mcert.conf\033[0m. You may want to keep it around in case you need to renew an" << ::std::endl + << " expired certificate, etc." << ::std::endl + << ::std::endl + << " name = example.com" << ::std::endl + << " org = Example, Inc" << ::std::endl + << " email = admin@example.com" << ::std::endl + << ::std::endl + << " [req]" << ::std::endl + << " distinguished_name = req_distinguished_name" << ::std::endl + << " x509_extensions = v3_req" << ::std::endl + << " prompt = no" << ::std::endl + << " utf8 = yes" << ::std::endl + << ::std::endl + << " [req_distinguished_name]" << ::std::endl + << " O = $org" << ::std::endl + << " CN = name:$name" << ::std::endl + << ::std::endl + << " [v3_req]" << ::std::endl + << " keyUsage = critical,digitalSignature" << ::std::endl + << " extendedKeyUsage = critical,codeSigning" << ::std::endl + << " subjectAltName = email:$email" << ::std::endl + << ::std::endl + << " Adjust the first three lines to match your details. If the repository is" << ::std::endl + << " hosted by an organization, use the organization's name for \033[1morg\033[0m. If you host" << ::std::endl + << " it as an individual, put your full, real name there. Using any kind of" << ::std::endl + << " aliases or nicknames is a bad idea (except, again, for testing). Remember," << ::std::endl + << " users of your repository will be presented with this information and if" << ::std::endl + << " they see it was signed by someone named SmellySnook, they will unlikely" << ::std::endl + << " trust it. Also use a working email address in case users need to contact" << ::std::endl + << " you about issues with your certificate. Note that the \033[1mname:\033[0m prefix in the" << ::std::endl + << " \033[1mCN\033[0m value is not a typo." << ::std::endl + << ::std::endl + << " The \033[1mname\033[0m field is a canonical repository name prefix with the \033[1mpkg:\033[0m type" << ::std::endl + << " part stripped. Any repository with a canonical name that starts with this" << ::std::endl + << " prefix can be authenticated by this certificate (see the repository" << ::std::endl + << " manifest documentation for more information on canonical names). For" << ::std::endl + << " example, name \033[1mexample.com\033[0m will match any repository hosted on" << ::std::endl + << " \033[1m{,www.,pkg.,bpkg.}example.com\033[0m. While name \033[1mexample.com/math\033[0m will match" << ::std::endl + << " \033[1m{...}example.com/pkg/1/math\033[0m but not \033[1m{...}example.com/pkg/1/misc\033[0m." << ::std::endl + << ::std::endl + << " A certificate name can also contain a subdomain wildcard. A wildcard name" << ::std::endl + << " in the \033[1m*.example.com\033[0m form matches any single-level subdomain, for example" << ::std::endl + << " \033[1mfoo.example.com\033[0m but not \033[1mfoo.bar.example.com\033[0m while a wildcard name in the" << ::std::endl + << " \033[1m**.example.com\033[0m form matches any subdomain, including multi-level. The above" << ::std::endl + << " two forms do not match the domain itself (\033[1mexample.com\033[0m in the above" << ::std::endl + << " example). If this is desired, the \033[1m*example.com\033[0m and \033[1m**example.com\033[0m forms" << ::std::endl + << " should be used instead. Note that these forms still only match subdomains." << ::std::endl + << " In other words, they won't match \033[1mfooexample.com\033[0m. Wildcard names are less" << ::std::endl + << " secure and therefore are normally only used for testing and/or internal" << ::std::endl + << " repositories." << ::std::endl + << ::std::endl + << " Once the configuration file is ready, generate the certificate:" << ::std::endl + << ::std::endl + << " openssl req -x509 -new -sha256 -key key.pem \\" << ::std::endl + << " -config cert.conf -days 730 >cert.pem" << ::std::endl + << ::std::endl + << " To verify the certificate information, run:" << ::std::endl + << ::std::endl + << " openssl x509 -noout -nameopt RFC2253,sep_multiline \\" << ::std::endl + << " -subject -dates -email <cert.pem" << ::std::endl + << ::std::endl + << "3. Add Certificate to Repository" << ::std::endl + << ::std::endl + << " Add the \033[1mcertificate:\033[0m field for the base repository (\033[1mrole: base\033[0m) in the" << ::std::endl + << " \033[1mrepositories\033[0m manifest file(s):" << ::std::endl + << ::std::endl + << " certificate:" << ::std::endl + << " \\" << ::std::endl + << " <cert>" << ::std::endl + << " \\" << ::std::endl + << ::std::endl + << " Replace \033[4mcert\033[0m with the entire contents of \033[1mcert.pem\033[0m (including the BEGIN" << ::std::endl + << " CERTIFICATE\033[0m and END CERTIFICATE\033[0m lines). So you will have an entry like" << ::std::endl + << " this:" << ::std::endl + << ::std::endl + << " certificate:" << ::std::endl + << " \\" << ::std::endl + << " -----BEGIN CERTIFICATE-----" << ::std::endl + << " MIIDQjCCAiqgAwIBAgIJAIUgsIqSnesGMA0GCSqGSIb3DQEBCwUAMDkxFzAVBgNV" << ::std::endl + << " ." << ::std::endl + << " ." << ::std::endl + << " ." << ::std::endl + << " +NOVBamEvjn58ZcLfWh2oKee7ulIZg==" << ::std::endl + << " -----END CERTIFICATE-----" << ::std::endl + << " \\" << ::std::endl + << ::std::endl + << "4. Sign Repository" << ::std::endl + << ::std::endl + << " When generating the repository manifests with the \033[1mbpkg-rep-create(1)\033[0m" << ::std::endl + << " command, specify the path to \033[1mkey.pem\033[0m with the \033[1m--key\033[0m option:" << ::std::endl + << ::std::endl + << " bpkg rep-create --key /path/to/key.pem /path/to/repository" << ::std::endl + << ::std::endl + << " You will be prompted for a password to unlock the private key." << ::std::endl + << ::std::endl + << "5. Using PIV/PKCS#11 Device" << ::std::endl + << ::std::endl + << " This optional step shows how to load the private key into Yubikey 4 and" << ::std::endl + << " then use it instead of the private key itself for signing the repository." << ::std::endl + << " Note that you will need OpenSSL 1.0.2 or later for the signing part to" << ::std::endl + << " work." << ::std::endl + << ::std::endl + << " First change the Yubikey MKEY, PUK, and PIN if necessary. You should" << ::std::endl + << " definitely do this if it still has the factory defaults. Then import the" << ::std::endl + << " private key and the certificate into Yubikey (replace \033[4mmkey\033[0m with the" << ::std::endl + << " management key):" << ::std::endl + << ::std::endl + << " yubico-piv-tool --key=<mkey> -a import-key -s 9c <key.pem" << ::std::endl + << " yubico-piv-tool --key=<mkey> -a import-certificate -s 9c <cert.pem" << ::std::endl + << ::std::endl + << " After this you will normally save the certificate/private key onto backup" << ::std::endl + << " media, store it in a secure, offline location, and remove the key from the" << ::std::endl + << " build machine." << ::std::endl + << ::std::endl + << " To sign the repository with Yubikey specify the following options instead" << ::std::endl + << " of just \033[1m--key\033[0m as at step 4 (\"SIGN key\"\033[0m is the label for the slot 9c\033[0m private" << ::std::endl + << " key):" << ::std::endl + << ::std::endl + << " bpkg rep-create \\" << ::std::endl + << " --openssl-option pkeyutl:-engine --openssl-option pkeyutl:pkcs11 \\" << ::std::endl + << " --openssl-option pkeyutl:-keyform --openssl-option pkeyutl:engine \\" << ::std::endl + << " --key \"pkcs11:object=SIGN%20key\" /path/to/repository" << ::std::endl + << ::std::endl + << " Note that for \033[1mopenssl\033[0m versions prior to \033[1m3.0.0\033[0m \033[1mbpkg\033[0m uses the \033[1mrsautl\033[0m command" << ::std::endl + << " instead of \033[1mpkeyutl\033[0m for the data signing operation." << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/repository-signing.hxx b/bpkg/repository-signing.hxx new file mode 100644 index 0000000..d5338e1 --- /dev/null +++ b/bpkg/repository-signing.hxx @@ -0,0 +1,31 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REPOSITORY_SIGNING_HXX +#define BPKG_REPOSITORY_SIGNING_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_repository_signing_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REPOSITORY_SIGNING_HXX diff --git a/bpkg/repository-types.cxx b/bpkg/repository-types.cxx new file mode 100644 index 0000000..90efcdd --- /dev/null +++ b/bpkg/repository-types.cxx @@ -0,0 +1,206 @@ +// -*- 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/repository-types.hxx> + +#include <map> + +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_repository_types_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[1mDESCRIPTION\033[0m" << ::std::endl + << ::std::endl + << "This help topic describes the repository types recognized by \033[1mbpkg\033[0m, their" << ::std::endl + << "structure, and the format of their URLs. Currently three types of repositories" << ::std::endl + << "are supported: archive-based \033[1mpkg\033[0m, directory-based \033[1mdir\033[0m, and version" << ::std::endl + << "control-based \033[1mgit\033[0m." << ::std::endl + << ::std::endl + << "The repository location may specify the repository type as part of the URL" << ::std::endl + << "scheme component in the \033[4mtype\033[0m\033[1m+\033[0m\033[4mprotocol\033[0m\033[0m form. For example:" << ::std::endl + << ::std::endl + << "git+https://example.com/foo" << ::std::endl + << "dir+file:///tmp/repo" << ::std::endl + << ::std::endl + << "Note that the explicit specification is only needed when the correct type" << ::std::endl + << "cannot be guessed from the URL. See \033[1mbpkg-rep-add(1)\033[0m for details." << ::std::endl + << ::std::endl + << "\033[1mPKG REPOSITORIES\033[0m" << ::std::endl + << ::std::endl + << "A \033[1mpkg\033[0m repository is \033[4marchive\033[0m-based. That is, it contains a collection of various" << ::std::endl + << "packages/versions as archive files. For more information on the structure of" << ::std::endl + << "\033[1mpkg\033[0m repositories refer to The \033[1mbuild2\033[0m Package Manager Manual (bpkg). The \033[1mpkg\033[0m" << ::std::endl + << "repository location can be a local directory path or an \033[1mhttp(s)://\033[0m URL." << ::std::endl + << ::std::endl + << "\033[1mDIR REPOSITORIES\033[0m" << ::std::endl + << ::std::endl + << "A \033[1mdir\033[0m repository is \033[4mdirectory\033[0m-based. That is, it contains a collection of" << ::std::endl + << "various packages as directories but only a single version per package can be" << ::std::endl + << "present in such a repository. The \033[1mdir\033[0m repository location can be a local" << ::std::endl + << "directory path or a \033[1mfile://\033[0m URL." << ::std::endl + << ::std::endl + << "A \033[1mdir\033[0m repository is expected to contain either the \033[1mmanifest\033[0m or" << ::std::endl + << "\033[1mpackages.manifest\033[0m file in the root directory of the repository. If it only" << ::std::endl + << "contains \033[1mmanifest\033[0m, then it is assumed to be a simple, single-package repository" << ::std::endl + << "with the \033[1mmanifest\033[0m file being its package manifest. Otherwise, the" << ::std::endl + << "\033[1mpackages.manifest\033[0m file should list the locations of available packages as" << ::std::endl + << "described in Package List Manifest for \033[1mdir\033[0m Repositories" << ::std::endl + << "(bpkg#manifest-package-list-dir)." << ::std::endl + << ::std::endl + << "A \033[1mdir\033[0m repository may also contain the \033[1mrepositories.manifest\033[0m file in the root" << ::std::endl + << "directory of the repository. This file can be used to describe the repository" << ::std::endl + << "itself as well as specify its prerequisite and complement repositories. See" << ::std::endl + << "Repository List Manifest (bpkg#manifest-repository-list) for details on the" << ::std::endl + << "format and semantics of this file." << ::std::endl + << ::std::endl + << "\033[1mGIT REPOSITORIES\033[0m" << ::std::endl + << ::std::endl + << "A \033[1mgit\033[0m repository is \033[4mversion control\033[0m-based. That is, it normally contains" << ::std::endl + << "multiple versions of the same package (but can also contain several, usually" << ::std::endl + << "related, packages in the same repository)." << ::std::endl + << ::std::endl + << "A \033[1mgit\033[0m repository has the same structure and manifest files as the \033[1mdir\033[0m" << ::std::endl + << "repository. See Package List Manifest for \033[1mdir\033[0m Repositories" << ::std::endl + << "(bpkg#manifest-package-list-dir) and Repository List Manifest" << ::std::endl + << "(bpkg#manifest-repository-list) for details on their format and semantics." << ::std::endl + << ::std::endl + << "Theoretically, a \033[1mgit\033[0m repository may contain as many package versions as there" << ::std::endl + << "are commits. Practically, however, we are normally only interested in a small" << ::std::endl + << "subset of them while fetching and processing the necessary information for all" << ::std::endl + << "of them could be prohibitively expensive. As a result, by default, only" << ::std::endl + << "advertised tags in the \033[1mrefs/tags/v*\033[0m form where the part after \033[1mv\033[0m is also a valid" << ::std::endl + << "standard version (b#module-version) are considered to be sources of useful" << ::std::endl + << "package versions. These commits normally correspond to released versions and" << ::std::endl + << "are called the \033[4mdefault set\033[0m. Note that only the latest revision of each such" << ::std::endl + << "version is considered." << ::std::endl + << ::std::endl + << "Instead of the default set, it is possible to provide a custom set of available" << ::std::endl + << "versions by specifying one or more commit ids and/or references and/or" << ::std::endl + << "reference patterns in the repository URL fragment (see \033[1mgit-ls-remote(1)\033[0m for" << ::std::endl + << "details on advertised references). For example:" << ::std::endl + << ::std::endl + << "https://example.com/foo.git#v1.2.3" << ::std::endl + << "https://example.com/foo.git#master" << ::std::endl + << "https://example.com/foo.git#af234f56" << ::std::endl + << "https://example.com/foo.git#tags/releases/*" << ::std::endl + << "https://example.com/foo.git#HEAD,tags/v1.*.*,heads/feature-*" << ::std::endl + << ::std::endl + << "Furthermore, it is possible to expand (or narrow down) the default set using" << ::std::endl + << "the special \033[1m##\033[0m fragment notation. For example:" << ::std::endl + << ::std::endl + << "https://example.com/foo.git##HEAD - default set plus HEAD" << ::std::endl + << "https://example.com/foo.git##heads/* - default set plus branches" << ::std::endl + << "https://example.com/foo.git##-v1.* - default set minus v1.*" << ::std::endl + << ::std::endl + << "A \033[1mgit\033[0m repository URL fragment is a comma-separated list of reference filters in" << ::std::endl + << "the following form:" << ::std::endl + << ::std::endl + << "[\033[4mrefname\033[0m][\033[1m@\033[0m\033[4mcommit\033[0m]\033[0m" << ::std::endl + << ::std::endl + << "Either \033[4mrefname\033[0m, \033[4mcommit\033[0m, or both must be specified. If both are specified then" << ::std::endl + << "\033[4mrefname\033[0m is only used to minimize the amount of data fetched and \033[4mcommit\033[0m is" << ::std::endl + << "expected to belong to its history. For example:" << ::std::endl + << ::std::endl + << ".../foo.git#master@48fba3625d65941bb85a39061bcf795d4949c778" << ::std::endl + << ::std::endl + << "The \033[4mrefname\033[0m part can be an abbreviated commit id or an advertised reference or" << ::std::endl + << "reference pattern under \033[1mrefs/\033[0m. While \033[4mcommit\033[0m must be the complete, 40-characters" << ::std::endl + << "SHA1 that need not be advertised. For convenience, a 40-characters filter that" << ::std::endl + << "consists of only hexadecimal digits is assumed to be \033[4mcommit\033[0m even if not" << ::std::endl + << "prefixed with \033[1m@\033[0m. In an unlikely event this produces an incorrect result, the" << ::std::endl + << "\033[1m@\033[0m-form with omitted \033[4mcommit\033[0m can be used. For example:" << ::std::endl + << ::std::endl + << ".../foo.git#48fba3625d65941bb85a39061bcf795d4949c778 (commit id)" << ::std::endl + << ".../foo.git#deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@ (reference)" << ::std::endl + << ::std::endl + << "The \033[4mrefname\033[0m part can use the \033[1m*\033[0m and \033[1m?\033[0m wildcard pattern characters with the" << ::std::endl + << "standard semantics as well as the \033[1m**\033[0m character sequence which matches in" << ::std::endl + << "subdirectories, recursively. For example:" << ::std::endl + << ::std::endl + << ".../foo.git#tags/v* - tags/v1.2.3 but not tags/old/v0.1.0" << ::std::endl + << ".../foo.git#tags/v** - tags/v1.2.3 and tags/old/v0.1.0" << ::std::endl + << ::std::endl + << "A relative \033[4mrefname\033[0m is searched for in \033[1mrefs/\033[0m, \033[1mrefs/tags/\033[0m, and \033[1mrefs/heads/\033[0m as" << ::std::endl + << "well as among symbolic references like \033[1mHEAD\033[0m. To anchor it to \033[1mrefs/\033[0m make it" << ::std::endl + << "absolute, for example:" << ::std::endl + << ::std::endl + << ".../foo.git#tags/v* - refs/tags/v1.2.3 but also refs/heads/tags/voo" << ::std::endl + << ".../foo.git#/tags/v* - refs/tags/v1.2.3 only" << ::std::endl + << ::std::endl + << "While a \033[4mrefname\033[0m pattern is allowed not match any references, a non-pattern that" << ::std::endl + << "doesn't resolve to a reference is invalid." << ::std::endl + << ::std::endl + << "If a \033[4mrefname\033[0m starts with minus (\033[1m-\033[0m) then it is treated as an exclusion filter --" << ::std::endl + << "any references that it matches are excluded from the set included by the" << ::std::endl + << "preceding filters (or the default set). For example:" << ::std::endl + << ::std::endl + << ".../foo.git#v*,-v1.* - exclude v1.* from v*" << ::std::endl + << ".../foo.git##-v1.* - exclude v1.* from default set" << ::std::endl + << ::std::endl + << "To support specifying literal leading minus, a \033[4mrefname\033[0m that starts with plus" << ::std::endl + << "(\033[1m+\033[0m) is treated as an inclusion filter. For example:" << ::std::endl + << ::std::endl + << ".../foo.git#+x - include x" << ::std::endl + << ".../foo.git#+-x - include -x" << ::std::endl + << ".../foo.git#++x - include +x" << ::std::endl + << ::std::endl + << "Currently supported \033[1mgit\033[0m protocols are \033[1mgit://\033[0m, \033[1mssh://\033[0m (but not scp\033[0m pseudo-URL" << ::std::endl + << "syntax), \033[1mhttp://\033[0m, and \033[1mhttps://\033[0m for remote repositories and \033[1mfile://\033[0m for local" << ::std::endl + << "repositories. While \033[1mbpkg\033[0m tries to minimize the amount of information (history)" << ::std::endl + << "fetched, it is not always possible for some protocols and/or server" << ::std::endl + << "configurations, as discussed next." << ::std::endl + << ::std::endl + << "A \033[1mgit\033[0m repository accessible via \033[1mhttp(s)://\033[0m can use either \033[4mdumb\033[0m or \033[4msmart\033[0m" << ::std::endl + << "protocol (refer to the \033[1mgit\033[0m documentation for details). The dumb protocol" << ::std::endl + << "provides only limited support for fetch minimization and if this protocol is" << ::std::endl + << "used, then \033[1mbpkg\033[0m has no choice but to download a substantial amount of history." << ::std::endl + << ::std::endl + << "The smart protocol allows fetching of minimal history for tags and branches." << ::std::endl + << "Whether this is also possible for (all) commit ids depends on whether the" << ::std::endl + << "server is configured to allow fetching unadvertised commits. For details, refer" << ::std::endl + << "to the \033[1muploadpack.allowReachableSHA1InWant\033[0m and \033[1muploadpack.allowAnySHA1InWant\033[0m" << ::std::endl + << "\033[1mgit\033[0m configuration values." << ::std::endl + << ::std::endl + << "The \033[1mgit://\033[0m and \033[1mssh://\033[0m protocols are similar to smart \033[1mhttp://\033[0m in that they" << ::std::endl + << "support fetching minimal history for tags and branches and may or may not" << ::std::endl + << "support this for commit ids depending on the server configuration. Note," << ::std::endl + << "however, that unlike for \033[1mhttp(s)://\033[0m, for these protocols \033[1mbpkg\033[0m does not try to" << ::std::endl + << "sense if fetching unadvertised commits is allowed and always assumes that it is" << ::std::endl + << "not. Also note that the sensed or assumed protocol capabilities can be" << ::std::endl + << "overridden for a \033[1mgit\033[0m repository URL prefix using the \033[1m--git-capabilities\033[0m option" << ::std::endl + << "(\033[1mbpkg-common-options(1)\033[0m)." << ::std::endl + << ::std::endl + << "Based on this information, to achieve optimal results the recommended protocol" << ::std::endl + << "for remote repositories is smart \033[1mhttps://\033[0m. Additionally, if you are planning to" << ::std::endl + << "refer to unadvertised commit ids, then also consider configuring the server to" << ::std::endl + << "allow fetching unadvertised commits." << ::std::endl + << ::std::endl + << "The \033[1mfile://\033[0m protocol has the same fetch minimization support as \033[1mgit://\033[0m and is" << ::std::endl + << "therefore treated the same." << ::std::endl; + + p = ::bpkg::cli::usage_para::text; + + return p; + } +} + +// Begin epilogue. +// +// +// End epilogue. + diff --git a/bpkg/repository-types.hxx b/bpkg/repository-types.hxx new file mode 100644 index 0000000..b62deed --- /dev/null +++ b/bpkg/repository-types.hxx @@ -0,0 +1,31 @@ +// -*- C++ -*- +// +// This file was generated by CLI, a command line interface +// compiler for C++. +// + +#ifndef BPKG_REPOSITORY_TYPES_HXX +#define BPKG_REPOSITORY_TYPES_HXX + +// Begin prologue. +// +// +// End prologue. + +#include <bpkg/common-options.hxx> + +// Print page usage information. +// +namespace bpkg +{ + ::bpkg::cli::usage_para + print_bpkg_repository_types_usage (::std::ostream&, + ::bpkg::cli::usage_para = ::bpkg::cli::usage_para::none); +} + +// Begin epilogue. +// +// +// End epilogue. + +#endif // BPKG_REPOSITORY_TYPES_HXX diff --git a/bpkg/system-package-manager-fedora.cxx b/bpkg/system-package-manager-fedora.cxx index 61ded1a..b4e9e10 100644 --- a/bpkg/system-package-manager-fedora.cxx +++ b/bpkg/system-package-manager-fedora.cxx @@ -191,6 +191,104 @@ namespace bpkg static process_path dnf_path; static process_path sudo_path; + // Note that dnf5 introduces quite a lot of changes to the command line + // interface. See the full list of changes between dnf and dnf5 at + // https://dnf5.readthedocs.io/en/latest/changes_from_dnf4.7.html. + // + + // Run `dnf --version`, parse the output, and return true for dnf of the + // version 5 and above. Cache the value returned on the first call. + // + static optional<bool> dnf_version_5; + + static bool + dnf5 () + { + // Note that `dnf --version` output looks as follows for dnf5: + // + // dnf5 version 5.2.6.2 + // dnf5 plugin API version 2.0 + // libdnf5 version 5.2.6.2 + // libdnf5 plugin API version 2.0 + // + // Loaded dnf5 plugins: + // ... + // + // and as follows for the earlier versions: + // + // 4.19.2 + // Installed: dnf-0:4.19.2-1.fc39.noarch at Sat 15 Jun 2024 07:37:35 PM GMT + // Built : Fedora Project at Fri 29 Mar 2024 06:55:12 PM GMT + // + // Installed: rpm-0:4.19.1.1-1.fc39.x86_64 at Sat 15 Jun 2024 07:37:18 PM GMT + // Built : Fedora Project at Wed 07 Feb 2024 04:05:57 PM GMT + // + // We will return true if the first line of the output starts with "dnf", + // assuming (perhaps a bit optimistically) that the first line format will + // not change in the future. + // + if (!dnf_version_5) + { + cstrings args {"dnf", "--version", nullptr}; + const char* evars[] = {"LC_ALL=C", nullptr}; + + try + { + process_path pp (process::path_search (args[0])); + process_env pe (pp, evars); + + if (verb >= 3) + print_process (pe, args); + + process pr (pp, args, -2 /* stdin */, -1 /* stdout */, 2); + + string l; + try + { + ifdstream is (move (pr.in_ofd), fdstream_mode::skip); + getline (is, l); + is.close (); + } + catch (const io_error& e) + { + if (pr.wait ()) + fail << "unable to read " << args[0] << " --version output: " << e; + + // Fall through. + } + + if (!pr.wait ()) + { + diag_record dr (fail); + dr << args[0] << " exited with non-zero code"; + + if (verb < 3) + { + dr << info << "command line: "; + print_process (dr, pe, args); + } + } + + if (l.empty ()) + fail << "unable to retrieve dnf version from " << args[0] + << " --version output"; + + dnf_version_5 = (l.compare (0, 3, "dnf") == 0); + } + catch (const process_error& e) + { + error << "unable to execute " << args[0] << ": " << e; + + if (e.child) + exit (1); + + throw failed (); + } + } + + return *dnf_version_5; + } + // Obtain the installed and candidate versions for the specified list of // Fedora packages by executing `dnf list`. // @@ -204,13 +302,14 @@ namespace bpkg assert (n != 0 && n <= pis.size ()); + // Lists all packages: installed, available, or both. + // // The --quiet option makes sure we don't get 'Last metadata expiration // check: <timestamp>' printed to stderr. It does not appear to affect // error diagnostics (try specifying a single unknown package). // cstrings args { "dnf", "list", - "--all", // Look for both installed and available. "--cacheonly", // Don't automatically update the metadata. "--quiet"}; @@ -262,6 +361,7 @@ namespace bpkg // process pr; if (!simulate_) + { pr = process (dnf_path, args, -2 /* stdin */, @@ -269,6 +369,7 @@ namespace bpkg 2 /* stderr */, nullptr /* cwd */, evars); + } else { strings k; @@ -314,10 +415,11 @@ namespace bpkg // The output of `dnf list <pkg1> <pkg2> ...` is the 2 groups of lines // in the following form: // - // Installed Packages + // Installed packages // <pkg1>.<arch1> 13.0.0-3.fc35 @<repo1> // <pkg2>.<arch2> 69.1-6.fc35 @<repo2> - // Available Packages + // + // Available packages // <pkg1>.<arch1> 13.0.1-1.fc35 <repo1> // <pkg3>.<arch3> 1.2.11-32.fc35 <repo3> // @@ -325,8 +427,8 @@ namespace bpkg // necessarily match the order of the packages on the command line. // It looks like there should be not blank lines but who really knows. // - // Note also that if a package appears in the 'Installed Packages' - // group, then it only appears in the 'Available Packages' if the + // Note also that if a package appears in the 'Installed packages' + // group, then it only appears in the 'Available packages' if the // candidate version is better. Only the single (best) available // version is listed, which we call the candidate version. // @@ -338,14 +440,22 @@ namespace bpkg print_process (dr, pe, args); }); - // Keep track of whether we are inside of the 'Installed Packages' - // or 'Available Packages' sections. + // Keep track of whether we are inside of the 'Installed packages' + // or 'Available packages' sections. + // + // Note that dnf prior to dnf5 prints "Installed Packages" and + // "Available Packages". // optional<bool> installed; for (string l; !eof (getline (is, l)); ) { - if (l == "Installed Packages") + // Skip empty lines. + // + if (l.empty ()) + continue; + + if (icasecmp (l, "Installed packages") == 0) { if (installed) fail << "unexpected line '" << l << "'"; @@ -354,7 +464,7 @@ namespace bpkg continue; } - if (l == "Available Packages") + if (icasecmp (l, "Available packages") == 0) { if (installed && !*installed) fail << "duplicate line '" << l << "'"; @@ -506,7 +616,7 @@ namespace bpkg // Note that if a Fedora package is installed but the repository doesn't // contain a better version, then this package won't appear in the - // 'Available Packages' section of the `dnf list` output and thus the + // 'Available packages' section of the `dnf list` output and thus the // candidate_version will stay empty. Let's set it to the installed // version in this case to be consistent with the Debian's semantics and // keep the Fedora and Debian system package manager implementations @@ -524,7 +634,8 @@ namespace bpkg } } - // Execute `dnf repoquery --requires` for the specified + // Execute `dnf repoquery --providers-of=requires` (`dnf repoquery + // --requires` for dnf prior to dnf5) for the specified // package/version/architecture and return its dependencies as a list of the // name/version pairs. // @@ -567,11 +678,39 @@ namespace bpkg // error diagnostics (try specifying an unknown option). // cstrings args { - "dnf", "repoquery", "--requires", + "dnf", "repoquery", "--quiet", - "--cacheonly", // Don't automatically update the metadata. - "--resolve", // Resolve requirements to packages/versions. - "--qf", "%{name} %{arch} %{epoch}:%{version}-%{release}"}; + "--cacheonly"}; // Don't automatically update the metadata. + + // Resolve requirements to packages/versions. + // + // Note that dnf5 has dropped the --resolve option, but the semantics of + // the --requires --resolve options combination can now be achieved with + // the --providers-of=requires option. + // + // Also note that for dnf5 the newline character needs to be specified + // explicitly in the --queryformat option value. + // + // As a side note, the full list of macros that can be used in the + // --queryformat value can be retrieved by the `dnf repoquery --querytags` + // command. + // + if (simulate_ || dnf5 ()) + { + args.push_back ("--providers-of"); + args.push_back ("requires"); + + args.push_back ("--queryformat"); + args.push_back ("%{name} %{arch} %{epoch}:%{version}-%{release}\\n"); + } + else + { + args.push_back ("--requires"); + args.push_back ("--resolve"); + + args.push_back ("--queryformat"); + args.push_back ("%{name} %{arch} %{epoch}:%{version}-%{release}"); + } // Note that installed packages which are not available from configured // repositories (e.g. packages installed from local rpm files or temporary @@ -591,7 +730,19 @@ namespace bpkg // --install to make sure that all installed packages will be listed and // no configuration file may influence the result. // - args.push_back ("--disableexcludes=all"); + // Note that dnf5 has dropped the --disableexcludes command line option + // but has invented the disable_excludes configuration option instead. + // + if (simulate_ || dnf5 ()) + { + args.push_back ("--setopt"); + args.push_back ("disable_excludes=*"); + } + else + { + args.push_back ("--disableexcludes"); + args.push_back ("all"); + } } args.push_back (spec.c_str ()); @@ -661,9 +812,9 @@ namespace bpkg ifdstream is (move (pr.in_ofd), fdstream_mode::skip, ifdstream::badbit); // The output of the command will be the sequence of the package lines - // in the `<name> <arc> <version>` form (per the -qf option above). So - // for example for the libicu-devel-69.1-6.fc35.x86_64 package it is - // as follows: + // in the `<name> <arc> <version>` form (per the --queryformat option + // above). So for example for the libicu-devel-69.1-6.fc35.x86_64 + // package it is as follows: // // bash i686 0:5.1.8-3.fc35 // bash x86_64 0:5.1.8-3.fc35 @@ -731,8 +882,9 @@ namespace bpkg catch (const io_error& e) { if (pr.wait ()) - fail << "unable to read " << args[0] << " repoquery --requires " - << "output: " << e; + fail << "unable to read " << args[0] << " repoquery " + << (dnf5 () ? "--providers-of=requires" : "--requires") + << " output: " << e; // Fall through. } @@ -766,6 +918,7 @@ namespace bpkg // pair<cstrings, const process_path&> system_package_manager_fedora:: dnf_common (const char* command, + const char* subcommand, optional<size_t> fetch_timeout, strings& args_storage) { @@ -782,6 +935,9 @@ namespace bpkg args.push_back ("dnf"); args.push_back (command); + if (subcommand != nullptr) + args.push_back (subcommand); + // Map our verbosity/progress to dnf --quiet and --verbose options. // // Note that all the diagnostics, including the progress indication and @@ -817,11 +973,12 @@ namespace bpkg // if (fetch_timeout) { - args_storage.push_back ( - "--setopt=timeout=" + to_string (*fetch_timeout)); - + args.push_back ("--setopt"); + args_storage.push_back ("timeout=" + to_string (*fetch_timeout)); args.push_back (args_storage.back ().c_str ()); - args.push_back ("--setopt=minrate=0"); + + args.push_back ("--setopt"); + args.push_back ("minrate=0"); } try @@ -851,6 +1008,17 @@ namespace bpkg } } + pair<cstrings, const process_path&> system_package_manager_fedora:: + dnf_common (const char* command, + optional<size_t> fetch_timeout, + strings& args_storage) + { + return dnf_common (command, + nullptr /* subcommand */, + fetch_timeout, + args_storage); + } + // Execute `dnf makecache` to download and cache the repositories metadata. // void system_package_manager_fedora:: @@ -954,7 +1122,8 @@ namespace bpkg // save us from attempting to download no longer existing packages). // #if 0 - args.push_back ("--setopt=metadata_expire=never"); + args.push_back ("--setopt"); + args.push_back ("metadata_expire=never"); #endif for (const string& p: pkgs) @@ -1011,18 +1180,19 @@ namespace bpkg } } - // Execute `dnf mark install` to mark the installed packages as installed by - // the user (see dnf_install() for details on the package specs). + // Execute `dnf mark user` (`dnf mark install` for dnf prior to dnf5) to + // mark the installed packages as installed by the user (see dnf_install() + // for details on the package specs). // // Note that an installed package may be marked as installed by the user // rather than as a dependency. In particular, such a package will never be // automatically removed as an unused dependency. This mark can be added and - // removed by the `dnf mark install` and `dnf mark remove` commands, - // respectively. Besides that, this mark is automatically added by `dnf - // install` for a package specified on the command line, but only if it is - // not yet installed. Note that this mark will not be added automatically - // for an already installed package even if it is upgraded explicitly. For - // example: + // removed by the `dnf mark user` and `dnf mark dependency` (`dnf mark + // remove` for dnf prior to dnf5) commands, respectively. Besides that, this + // mark is automatically added by `dnf install` for a package specified on + // the command line, but only if it is not yet installed. Note that this + // mark will not be added automatically for an already installed package + // even if it is upgraded explicitly. For example: // // $ sudo dnf install libsigc++30-devel-3.0.2-2.fc32 --repofrompath test,./repo --setopt=gpgcheck=0 --assumeyes // Installed: libsigc++30-3.0.2-2.fc32.x86_64 libsigc++30-devel-3.0.2-2.fc32.x86_64 @@ -1040,12 +1210,14 @@ namespace bpkg strings args_storage; pair<cstrings, const process_path&> args_pp ( - dnf_common ("mark", nullopt /* fetch_timeout */, args_storage)); + dnf_common ("mark", + (simulate_ || dnf5 () ? "user" : "install"), + nullopt /* fetch_timeout */, + args_storage)); cstrings& args (args_pp.first); const process_path& pp (args_pp.second); - args.push_back ("install"); args.push_back ("--cacheonly"); for (const string& p: pkgs) @@ -1061,9 +1233,14 @@ namespace bpkg process pr; if (!simulate_) { - // Redirect stdout to stderr. + // Redirect stdout to /dev/null for dnf5 (which prints some useless + // information) and to stderr for the earlier versions (which issue + // diagnostics to stdout rather than to stderr). // - pr = process (pp, args, 0 /* stdin */, 2 /* stdout */); + pr = process (pp, args, + 0 /* stdin */, + (dnf5 () ? -2 : 2) /* stdout */, + 2 /* stderr */); } else { @@ -1737,18 +1914,18 @@ namespace bpkg // packages, including the fully installed ones. But we must be careful // not to force their upgrade. To achieve this we will specify the // installed version as the desired version. Whether we run `dnf install` - // or not we will also always run `dnf mark install` afterwards for all - // the packages to mark them as installed by the user. + // or not we will also always run `dnf mark user` afterwards for all the + // packages to mark them as installed by the user. // // Note also that for partially/not installed packages we used to not // specify the version, expecting the candidate version to always be // installed (we did specify the candidate architecture though, since for // reasons unknown dnf may install a package of a different architecture - // otherwise). This, however, turned out to not always be the case. - // Moreover, we have observed such an undocumented behavior, that if the - // package versions are not specified, then the dnf-install command - // outcome may depend on the order of the packages specified on the - // command line: + // otherwise). This, however, turned out to not always be the case (at + // least for dnf prior to dnf5). Moreover, we have observed such an + // undocumented behavior, that if the package versions are not specified, + // then the dnf-install command outcome may depend on the order of the + // packages specified on the command line: // // $ dnf list expat.x86_64 expat-devel.x86_64 // Installed Packages @@ -2699,12 +2876,18 @@ namespace bpkg dir_path licensedir; dir_path build2dir; - // Note that the ~/rpmbuild/{.,BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} - // directory paths used by rpmbuild are actually defined as the - // %{_topdir}, %{_builddir}, %{_buildrootdir}, %{_rpmdir}, %{_sourcedir}, - // %{_specdir}, and %{_srcrpmdir} RPM macros. These macros can potentially - // be redefined in RPM configuration files, in particular, in - // ~/.rpmmacros. + // Note that the ~/rpmbuild/{.,BUILD,RPMS,SOURCES,SPECS,SRPMS} directory + // paths used by rpmbuild are actually defined as the %{_topdir}, + // %{_builddir}, %{_rpmdir}, %{_sourcedir}, %{_specdir}, and %{_srcrpmdir} + // RPM macros. These macros can potentially be redefined in RPM + // configuration files, in particular, in ~/.rpmmacros. + // + // Also note that the newer versions of rpmbuild don't create the + // ~/rpmbuild/BUILDROOT directory and don't support the %{_buildrootdir} + // macro anymore. Instead, they create the package-specific + // ~/rpmbuild/BUILD/<package>-<version>-build/BUILDROOT directory. Thus, + // we always use the $RPM_BUILD_ROOT environment variable in the %install + // section of the RPM spec file, rather than the %{_buildrootdir} macro. // dir_path topdir; // ~/rpmbuild/ dir_path specdir; // ~/rpmbuild/SPECS/ @@ -2746,7 +2929,6 @@ namespace bpkg expressions.push_back ("%{?_rpmdir}"); expressions.push_back ("%{?_rpmfilename}"); expressions.push_back ("%{?_usrsrc}"); - expressions.push_back ("%{?buildroot}"); // Note that if the architecture passed with the --target option is // invalid, then rpmbuild will fail with some ugly diagnostics since @@ -2820,7 +3002,6 @@ namespace bpkg // We only need the following macro expansions for the verification. // pop_string (); // %{?_arch} - pop_dir (); // %{?buildroot} pop_dir (); // %{?_usrsrc} pop_string (); // %{?_rpmfilename} pop_dir (); // %{?_rpmdir} @@ -2859,9 +3040,10 @@ namespace bpkg // won't fight with rpmbuild and will use this tree as the user would // do while creating the binary package manually. // - // Specifially, we will create the RPM spec file in ~/rpmbuild/SPECS/, - // install the package(s) under the ~/rpmbuild/BUILDROOT/<package-dir>/ - // chroot, and expect the generated RPM files under ~/rpmbuild/RPMS/. + // Specifically, we will create the RPM spec file in ~/rpmbuild/SPECS/, + // install the package(s) under the $RPM_BUILD_ROOT chroot (set by + // rpmbuild while executing the %install section of the RPM spec file), + // and expect the generated RPM files under ~/rpmbuild/RPMS/. // // That, in particular, means that we have no use for the --output-root // directory. We will also make sure that we don't overwrite an existing @@ -3671,8 +3853,7 @@ namespace bpkg // debugsources.list file is piped as an input to the cpio program // executed in the ~/rpmbuild/BUILD/foo-1.0.0 directory as its // current working directory, which tries to copy these source files - // to the - // ~/rpmbuild/BUILDROOT/foo-1.0.0-1.fc35.x86_64/usr/src/debug/foo-1.0.0-1.fc35.x86_64 + // to the $RPM_BUILD_ROOT/usr/src/debug/foo-1.0.0-1.fc35.x86_64 // directory. Given that these source files are actually located in // the bpkg configuration directory rather than in the // ~/rpmbuild/BUILD/foo-1.0.0 directory the cpio program fails to @@ -3760,7 +3941,7 @@ namespace bpkg os << " \\\\\\\n " << v; }; - add_macro_line ("config.install.chroot='%{buildroot}/'"); + add_macro_line ("config.install.chroot=\"$RPM_BUILD_ROOT/\""); add_macro_line ("config.install.sudo='[null]'"); // If this is a C-based language, add rpath for private installation. diff --git a/bpkg/system-package-manager-fedora.hxx b/bpkg/system-package-manager-fedora.hxx index 3e68b98..986d203 100644 --- a/bpkg/system-package-manager-fedora.hxx +++ b/bpkg/system-package-manager-fedora.hxx @@ -274,7 +274,13 @@ namespace bpkg dnf_mark_install (const strings&); pair<cstrings, const process_path&> - dnf_common (const char*, + dnf_common (const char* command, + optional<size_t> fetch_timeout, + strings& args_storage); + + pair<cstrings, const process_path&> + dnf_common (const char* command, + const char* subcommand, optional<size_t> fetch_timeout, strings& args_storage); diff --git a/bpkg/system-package-manager-fedora.test.testscript b/bpkg/system-package-manager-fedora.test.testscript index 3655514..09731b1 100644 --- a/bpkg/system-package-manager-fedora.test.testscript +++ b/bpkg/system-package-manager-fedora.test.testscript @@ -28,7 +28,7 @@ rpm.x86_64 4.17.1-3.fc35 updates rust-uuid+std-devel.noarch 1.2.1-1.fc35 updates EOI - LC_ALL=C dnf list --all --cacheonly --quiet openssl-libs openssl-devel openssl1.1 openssl1.1-devel libsigc++40 libcurl lrmi rust-uuid+std-devel rpm <- + LC_ALL=C dnf list --cacheonly --quiet openssl-libs openssl-devel openssl1.1 openssl1.1-devel libsigc++40 libcurl lrmi rust-uuid+std-devel rpm <- EOE openssl-libs '1:1.1.1q-1.fc35' 'x86_64' '1:1.1.1q-1.fc35' 'x86_64' openssl-devel '1:1.1.1q-1.fc35' 'x86_64' '1:1.1.1q-1.fc35' 'x86_64' @@ -47,7 +47,7 @@ rpm.x86_64 4.17.1-3.fc35 updates Available Packages EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++40 rpm <- + LC_ALL=C dnf list --cacheonly --quiet libsigc++40 rpm <- EOE libsigc++40 '' '' '' '' EOO @@ -61,7 +61,7 @@ lrmi.i686 0.10-28.fc35 fedora rpm.x86_64 4.17.1-3.fc35 updates EOI - LC_ALL=C dnf list --all --cacheonly --quiet lrmi rpm <- + LC_ALL=C dnf list --cacheonly --quiet lrmi rpm <- EOE lrmi '' '' '' '' EOO @@ -74,7 +74,7 @@ Available Packages rpm.x86_64 4.17.1-3.fc35 updates EOI - LC_ALL=C dnf list --all --cacheonly --quiet rpm rpm <- + LC_ALL=C dnf list --cacheonly --quiet rpm rpm <- EOE rpm '4.17.1-2.fc35' 'x86_64' '4.17.1-3.fc35' 'x86_64' EOO @@ -86,7 +86,7 @@ openssl-libs.i686 1:1.1.1q-1.fc35 @updates openssl-libs.x86_64 1:1.1.1q-1.fc35 @updates EOI - LC_ALL=C dnf list --all --cacheonly --quiet openssl-libs rpm <- + LC_ALL=C dnf list --cacheonly --quiet openssl-libs rpm <- error: rpm package doesn't exist EOE } @@ -109,7 +109,7 @@ pkgconf-pkg-config i686 0:1.8.0-1.fc35 pkgconf-pkg-config x86_64 0:1.8.0-1.fc35 EOI - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all openssl-devel-1:1.1.1q-1.fc35.x86_64 <- + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* openssl-devel-1:1.1.1q-1.fc35.x86_64 <- EOE opae-devel 2.0.0-2.3.fc35 openssl-libs 1:1.1.1q-1.fc35 @@ -124,7 +124,7 @@ cargo x86_64 0:1.65.0-1.fc35 rust-uuid-devel noarch 0:1.2.1-1.fc35 EOI - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" rust-uuid+std-devel-1.2.1-1.fc35.noarch <- + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" rust-uuid+std-devel-1.2.1-1.fc35.noarch <- EOE cargo 1.65.0-1.fc35 rust-uuid-devel 1.2.1-1.fc35 @@ -151,7 +151,7 @@ systemd i686 0:249.13-6.fc35 systemd x86_64 0:249.13-6.fc35 EOI - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all dhcp-client-12:4.4.3-4.P1.fc35.x86_64 <- + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* dhcp-client-12:4.4.3-4.P1.fc35.x86_64 <- EOE bash 5.1.8-3.fc35 coreutils 8.32-36.fc35 @@ -171,13 +171,13 @@ : no-depends : $* glibc 2.34-38.fc35 x86_64 true <:'' 2>>EOE >:'' - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all glibc-2.34-38.fc35.x86_64 <- + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* glibc-2.34-38.fc35.x86_64 <- EOE : unknown : $* glibg 2.34-38.fc35 x86_64 false <:'' 2>>EOE >:'' - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" glibg-2.34-38.fc35.x86_64 <- + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" glibg-2.34-38.fc35.x86_64 <- EOE } @@ -461,10 +461,10 @@ dnf-repoquery-requires: libpq-devel 13.4-1.fc35 x86_64 true libpq-devel.requires dnf-list: libpq libpq.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info - sudo dnf mark --quiet --assumeno install --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info + sudo dnf mark user --quiet --assumeno --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 EOE libpq 13.4 (libpq 13.4-1.fc35) installed EOO @@ -500,14 +500,14 @@ dnf-repoquery-requires: libpq-devel 13.4-1.fc35 x86_64 false libpq-devel.requires dnf-list: libpq libpq.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info sudo dnf install --quiet --assumeno libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info + sudo dnf mark user --quiet --assumeno --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info EOE libpq 13.4 (libpq 13.4-1.fc35) part installed EOO @@ -562,14 +562,14 @@ dnf-list-fetched: libpq libpq.info-fetched dnf-list-installed: libpq libpq.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info-fetched - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires-fetched - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info-fetched + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info-fetched + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires-fetched + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info-fetched sudo dnf install --quiet --assumeno libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info-installed EOE libpq 13.4 (libpq 13.4-1.fc35) part installed EOO @@ -618,12 +618,12 @@ dnf-list: libpq libpq.info dnf-list-installed: libpq libpq.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" libpq-devel-13.3-3.fc35.x86_64 <libpq-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" libpq-devel-13.3-3.fc35.x86_64 <libpq-devel.requires + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info sudo dnf install --quiet --assumeno libpq-13.3-3.fc35.x86_64 libpq-devel-13.3-3.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly libpq-13.3-3.fc35.x86_64 libpq-devel-13.3-3.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly libpq-13.3-3.fc35.x86_64 libpq-devel-13.3-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info-installed error: unexpected fedora package version for libpq info: expected: 13.3-3.fc35 info: installed: 13.4-1.fc35 @@ -672,14 +672,14 @@ dnf-list: libpq libpq.info dnf-list-installed: libpq libpq.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" libpq-devel-13.4-1.fc35.x86_64 <libpq-devel.requires + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info sudo dnf install --quiet --assumeno libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet libpq rpm <libpq.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly libpq-13.4-1.fc35.x86_64 libpq-devel-13.4-1.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libpq rpm <libpq.info-installed EOE libpq 13.4 (libpq 13.4-1.fc35) not installed EOO @@ -698,7 +698,7 @@ $* libpq <<EOI 2>>EOE != 0 dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info error: no installed system package for libpq EOE @@ -714,9 +714,9 @@ $* libpq --install libpq <<EOI 2>>EOE != 0 dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info error: no installed or available system package for libpq EOE @@ -732,7 +732,7 @@ $* libpq --install --no-fetch libpq <<EOI 2>>EOE != 0 dnf-list: libpq-devel pq-devel libpq-devel+pq-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info + LC_ALL=C dnf list --cacheonly --quiet libpq-devel pq-devel rpm <libpq-devel+pq-devel.info error: no installed or available system package for libpq EOE } @@ -761,9 +761,9 @@ $* libsqlite3 --install libsqlite3 <<EOI 2>>EOE != 0 dnf-list: libsqlite3-devel sqlite3-devel libsqlite3-devel+sqlite3-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite3-devel rpm <libsqlite3-devel+sqlite3-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsqlite3-devel sqlite3-devel rpm <libsqlite3-devel+sqlite3-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite3-devel rpm <libsqlite3-devel+sqlite3-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsqlite3-devel sqlite3-devel rpm <libsqlite3-devel+sqlite3-devel.info error: no installed or available system package for libsqlite3 EOE @@ -803,10 +803,10 @@ dnf-repoquery-requires: sqlite-devel 3.36.0-3.fc35 x86_64 true sqlite-devel.requires dnf-list: sqlite-libs sqlite-libs.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all sqlite-devel-3.36.0-3.fc35.x86_64 <sqlite-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info - sudo dnf mark --quiet --assumeno install --cacheonly sqlite-libs-3.36.0-3.fc35.x86_64 sqlite-devel-3.36.0-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* sqlite-devel-3.36.0-3.fc35.x86_64 <sqlite-devel.requires + LC_ALL=C dnf list --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info + sudo dnf mark user --quiet --assumeno --cacheonly sqlite-libs-3.36.0-3.fc35.x86_64 sqlite-devel-3.36.0-3.fc35.x86_64 EOE libsqlite3 3.36.0 (sqlite-libs 3.36.0-3.fc35) installed EOO @@ -864,14 +864,14 @@ dnf-list-fetched: sqlite-libs sqlite-libs.info-fetched dnf-list-installed: sqlite-libs sqlite-libs.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info-fetched - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" sqlite-devel-3.36.0-3.fc35.x86_64 <sqlite-devel.requires-fetched - LC_ALL=C dnf list --all --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info-fetched + LC_ALL=C dnf list --cacheonly --quiet libsqlite3-devel sqlite-devel rpm <libsqlite3-devel+sqlite-devel.info-fetched + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" sqlite-devel-3.36.0-3.fc35.x86_64 <sqlite-devel.requires-fetched + LC_ALL=C dnf list --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info-fetched sudo dnf install --quiet --assumeno sqlite-libs-3.36.0-3.fc35.x86_64 sqlite-devel-3.36.0-3.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly sqlite-libs-3.36.0-3.fc35.x86_64 sqlite-devel-3.36.0-3.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly sqlite-libs-3.36.0-3.fc35.x86_64 sqlite-devel-3.36.0-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet sqlite-libs rpm <sqlite-libs.info-installed EOE libsqlite3 3.36.0 (sqlite-libs 3.36.0-3.fc35) not installed EOO @@ -901,9 +901,9 @@ $* sqlite3 --install sqlite3 <<EOI 2>>EOE != 0 dnf-list: sqlite3 sqlite3.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 rpm <sqlite3.info + LC_ALL=C dnf list --cacheonly --quiet sqlite3 rpm <sqlite3.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 rpm <sqlite3.info + LC_ALL=C dnf list --cacheonly --quiet sqlite3 rpm <sqlite3.info error: no installed or available system package for sqlite3 EOE @@ -927,8 +927,8 @@ dnf-list: sqlite3 sqlite sqlite3+sqlite.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info - sudo dnf mark --quiet --assumeno install --cacheonly sqlite-3.36.0-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info + sudo dnf mark user --quiet --assumeno --cacheonly sqlite-3.36.0-3.fc35.x86_64 EOE sqlite3 3.36.0 (sqlite 3.36.0-3.fc35) installed EOO @@ -968,12 +968,12 @@ dnf-list-fetched: sqlite3 sqlite sqlite3+sqlite.info-fetched dnf-list-installed: sqlite sqlite.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info + LC_ALL=C dnf list --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info-fetched + LC_ALL=C dnf list --cacheonly --quiet sqlite3 sqlite rpm <sqlite3+sqlite.info-fetched sudo dnf install --quiet --assumeno sqlite-3.36.0-3.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly sqlite-3.36.0-3.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet sqlite rpm <sqlite.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly sqlite-3.36.0-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet sqlite rpm <sqlite.info-installed EOE sqlite3 3.36.0 (sqlite 3.36.0-3.fc35) not installed EOO @@ -1054,11 +1054,11 @@ dnf-list: ncurses-libs ncurses-libs.info dnf-list: ncurses-c++-libs ncurses-devel ncurses-c++-libs+ncurses-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" --installed --disableexcludes=all ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info - sudo dnf mark --quiet --assumeno install --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" --installed --setopt disable_excludes=* ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires + LC_ALL=C dnf list --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info + LC_ALL=C dnf list --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info + sudo dnf mark user --quiet --assumeno --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 EOE libncurses 6.2.0 (ncurses-libs 6.2-8.20210508.fc35) installed libncurses-c++ 6.2.0 (ncurses-c++-libs 6.2-8.20210508.fc35) installed @@ -1125,15 +1125,15 @@ dnf-list-fetched: ncurses-c++-libs ncurses-devel ncurses-c++-libs+ncurses-devel.info-fetched dnf-list-installed: ncurses-libs ncurses-c++-libs ncurses-libs+ncurses-c++-libs.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info + LC_ALL=C dnf list --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires-fetched - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info-fetched - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info-fetched + LC_ALL=C dnf list --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires-fetched + LC_ALL=C dnf list --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info-fetched + LC_ALL=C dnf list --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info-fetched sudo dnf install --quiet --assumeno ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-libs ncurses-c++-libs rpm <ncurses-libs+ncurses-c++-libs.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet ncurses-libs ncurses-c++-libs rpm <ncurses-libs+ncurses-c++-libs.info-installed EOE libncurses 6.2.0 (ncurses-libs 6.2-8.20210508.fc35) part installed libncurses-c++ 6.2.0 (ncurses-c++-libs 6.2-8.20210508.fc35) part installed @@ -1209,15 +1209,15 @@ dnf-list-fetched: ncurses-c++-libs ncurses-devel ncurses-c++-libs+ncurses-devel.info-fetched dnf-list-installed: ncurses-libs ncurses-c++-libs ncurses-libs+ncurses-c++-libs.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info + LC_ALL=C dnf list --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info-fetched - LC_ALL=C dnf repoquery --requires --quiet --cacheonly --resolve --qf "%{name} %{arch} %{epoch}:%{version}-%{release}" ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires-fetched - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info-fetched - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info-fetched + LC_ALL=C dnf list --cacheonly --quiet libncurses-devel ncurses-devel rpm <libncurses-devel+ncurses-devel.info-fetched + LC_ALL=C dnf repoquery --quiet --cacheonly --providers-of requires --queryformat "%{name} %{arch} %{epoch}:%{version}-%{release}\n" ncurses-devel-6.2-8.20210508.fc35.x86_64 <ncurses-devel.requires-fetched + LC_ALL=C dnf list --cacheonly --quiet ncurses-libs rpm <ncurses-libs.info-fetched + LC_ALL=C dnf list --cacheonly --quiet ncurses-c++-libs ncurses-devel rpm <ncurses-c++-libs+ncurses-devel.info-fetched sudo dnf install --quiet --assumeno ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet ncurses-libs ncurses-c++-libs rpm <ncurses-libs+ncurses-c++-libs.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly ncurses-libs-6.2-8.20210508.fc35.x86_64 ncurses-devel-6.2-8.20210508.fc35.x86_64 ncurses-c++-libs-6.2-8.20210508.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet ncurses-libs ncurses-c++-libs rpm <ncurses-libs+ncurses-c++-libs.info-installed EOE libncurses 6.2.0 (ncurses-libs 6.2-8.20210508.fc35) not installed libncurses-c++ 6.2.0 (ncurses-c++-libs 6.2-8.20210508.fc35) not installed @@ -1267,9 +1267,9 @@ dnf-list: libsigc++30 libsigc++30-devel libsigc++30+libsigc++30-devel.info dnf-list: libsigc++20 libsigc++20-devel libsigc++20+libsigc++20-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info - sudo dnf mark --quiet --assumeno install --cacheonly libsigc++20-2.10.7-3.fc35.x86_64 libsigc++20-devel-2.10.7-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + sudo dnf mark user --quiet --assumeno --cacheonly libsigc++20-2.10.7-3.fc35.x86_64 libsigc++20-devel-2.10.7-3.fc35.x86_64 EOE libsigc++ 2.10.7 (libsigc++20 2.10.7-3.fc35) installed EOO @@ -1313,14 +1313,14 @@ dnf-list: libsigc++20 libsigc++20-devel libsigc++20+libsigc++20-devel.info dnf-list-installed: libsigc++20 libsigc++20.info-installed EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info sudo dnf install --quiet --assumeno libsigc++20-2.10.7-3.fc35.x86_64 libsigc++20-devel-2.10.7-3.fc35.x86_64 - sudo dnf mark --quiet --assumeno install --cacheonly libsigc++20-2.10.7-3.fc35.x86_64 libsigc++20-devel-2.10.7-3.fc35.x86_64 - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 rpm <libsigc++20.info-installed + sudo dnf mark user --quiet --assumeno --cacheonly libsigc++20-2.10.7-3.fc35.x86_64 libsigc++20-devel-2.10.7-3.fc35.x86_64 + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 rpm <libsigc++20.info-installed EOE libsigc++ 2.10.7 (libsigc++20 2.10.7-3.fc35) part installed EOO @@ -1355,11 +1355,11 @@ dnf-list: libsigc++30 libsigc++30-devel libsigc++30+libsigc++30-devel.info dnf-list: libsigc++20 libsigc++20-devel libsigc++20+libsigc++20-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info error: multiple available fedora packages for libsigc++ info: candidate: libsigc++30 3.0.7-2.fc35 info: candidate: libsigc++20 2.10.7-3.fc35 @@ -1396,11 +1396,11 @@ dnf-list: libsigc++30 libsigc++30-devel libsigc++30+libsigc++30-devel.info dnf-list: libsigc++20 libsigc++20-devel libsigc++20+libsigc++20-devel.info EOI - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info sudo dnf makecache --quiet --assumeno --refresh - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info - LC_ALL=C dnf list --all --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++30 libsigc++30-devel rpm <libsigc++30+libsigc++30-devel.info + LC_ALL=C dnf list --cacheonly --quiet libsigc++20 libsigc++20-devel rpm <libsigc++20+libsigc++20-devel.info error: multiple partially installed fedora packages for libsigc++ info: candidate: libsigc++30 3.0.7-2.fc35, missing components: libsigc++30-devel info: candidate: libsigc++20 2.10.7-3.fc35, missing components: libsigc++20-devel @@ -1,7 +1,7 @@ # file : buildfile # license : MIT; see accompanying LICENSE file -./: {*/ -build/} \ +./: {*/ -build/ -doc/} \ doc{INSTALL NEWS README} legal{LICENSE AUTHORS LEGAL} \ manifest diff --git a/doc/manual.cli b/doc/manual.cli index 64275ce..e22cfd4 100644 --- a/doc/manual.cli +++ b/doc/manual.cli @@ -2576,7 +2576,11 @@ variables, and dependencies are passed to the \l{bpkg-pkg-build(1)} command at the \c{bpkg.configure.build} step. The package-specific configuration variables for this and/or the separate test packages are passed to \l{bpkg-pkg-build(1)} at the \c{bpkg.configure.build} and -\c{bpkg.test-separate-installed.configure.build} steps. For example: +\c{bpkg.test-separate-installed.configure.build} steps. The dependencies of +these packages can be configured at these steps in various configurations by +specifying the package-specific \c{--config-uuid} option(s) and configuration +variables or the \c{[?]sys:} prefix (see \l{bbot#arch-worker configuration +UUIDs}). For example: \ network-build-config: config.libfoo.network=true; Enable networking API. @@ -2620,6 +2624,15 @@ load-tests-build-config: ; Enable load testing. \\ + +default-build-config: +\\ +# Configure libbar-tests package's dependency libfoo as system on the +# bpkg.test-separate-installed.configure.build step, since it is +# already installed as a dependency of libbar. +# +{ --config-uuid=00000000-0000-0000-0000-000000000005 }+ ?sys:libfoo/* +\\ \ Note that options with values can only be specified using the single argument diff --git a/repositories.manifest b/repositories.manifest index 288344c..62acd9d 100644 --- a/repositories.manifest +++ b/repositories.manifest @@ -3,12 +3,5 @@ summary: build2 package dependency manager repository : role: prerequisite -location: ../build2.git#HEAD - -: -role: prerequisite -location: ../libbutl.git#HEAD - -: -role: prerequisite -location: ../libbpkg.git#HEAD +location: https://stage.build2.org/1 +trust: EC:50:13:E2:3D:F7:92:B4:50:0B:BF:2A:1F:7D:31:04:C6:57:6F:BC:BE:04:2E:E0:58:14:FA:66:66:21:1F:14 |