From 48c9bb1534b17f2e5a9182dc76d2bd1b93e32574 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 26 Jul 2023 19:55:52 +0300 Subject: Fix unexpected 'manual configuration of dependents with prefer or require clauses is not yet supported' error (GH issue #302) --- bpkg/pkg-build.cxx | 47 ++-- bpkg/pkg-configure.cxx | 168 +++++++++++-- bpkg/pkg-configure.hxx | 46 +++- .../t8a/libfoo-1.0.0.tar.gz | Bin 0 -> 407 bytes .../t8a/libfoo-2.0.0.tar.gz | Bin 0 -> 406 bytes .../dependency-alternatives/t8a/tax-1.0.0.tar.gz | Bin 0 -> 373 bytes .../dependency-alternatives/t8a/tex-1.0.0.tar.gz | Bin 0 -> 470 bytes .../dependency-alternatives/t8a/tix-1.0.0.tar.gz | Bin 0 -> 425 bytes .../dependency-alternatives/t8a/tox-1.0.0.tar.gz | Bin 0 -> 504 bytes .../dependency-alternatives/t8a/tux-1.0.0.tar.gz | Bin 0 -> 431 bytes tests/pkg-build.testscript | 265 +++++++++++++++++++-- 11 files changed, 458 insertions(+), 68 deletions(-) create mode 100644 tests/common/dependency-alternatives/t8a/libfoo-1.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/libfoo-2.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/tax-1.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/tex-1.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/tix-1.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/tox-1.0.0.tar.gz create mode 100644 tests/common/dependency-alternatives/t8a/tux-1.0.0.tar.gz diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index ed23ea5..9a73ea6 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -5699,10 +5699,9 @@ namespace bpkg // On the package reconfiguration we will try to resolve dependencies to // the same prerequisites (see pkg_configure() for details). For that, we - // will save prerequisites before disfiguring the dependents. Note, - // though, that this is not required for dependents with the collected - // prerequisites builds since the dependency alternatives are already - // selected for them. + // will save prerequisites before disfiguring a package. Note, though, + // that this is not required for the recursively collected packages since + // the dependency alternatives are already selected for them. // map> previous_prerequisites; @@ -5727,7 +5726,7 @@ namespace bpkg bool external (false); if (!simulate) { - external = sp != nullptr && sp->external () && p.external (); + external = (sp != nullptr && sp->external () && p.external ()); // Reset the keep_out flag if the package being unpacked is not // external. @@ -5736,16 +5735,27 @@ namespace bpkg p.keep_out = false; } - if (*p.action != build_package::drop && - !p.dependencies && - !sp->prerequisites.empty ()) + // Save prerequisites before disfiguring the package. + // + // Note that we add the prerequisites list to the map regardless if + // there are any prerequisites or not to, in particular, indicate the + // package reconfiguration mode to the subsequent + // pkg_configure_prerequisites() call (see the function documentation + // for details). + // + if (*p.action != build_package::drop && !p.dependencies && !p.system) { vector& ps (previous_prerequisites[&p]); - ps.reserve (sp->prerequisites.size ()); + assert (sp != nullptr); // Shouldn't be here otherwise. + + if (!sp->prerequisites.empty ()) + { + ps.reserve (sp->prerequisites.size ()); - for (const auto& pp: sp->prerequisites) - ps.push_back (pp.first.object_id ()); + for (const auto& pp: sp->prerequisites) + ps.push_back (pp.first.object_id ()); + } } // For an external package being replaced with another external, keep @@ -6195,12 +6205,6 @@ namespace bpkg info << "while configuring " << p.name () << p.db; })); - auto prereqs = [&p, &previous_prerequisites] () - { - auto i (previous_prerequisites.find (&p)); - return i != previous_prerequisites.end () ? &i->second : nullptr; - }; - configure_prerequisites_result cpr; if (p.system) { @@ -6219,6 +6223,15 @@ namespace bpkg } else { + // Should only be called for packages whose prerequisites are saved. + // + auto prereqs = [&p, &previous_prerequisites] () + { + auto i (previous_prerequisites.find (&p)); + assert (i != previous_prerequisites.end ()); + return &i->second; + }; + if (ap != nullptr) { assert (*p.action == build_package::build); diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx index 291929b..5bb7dfa 100644 --- a/bpkg/pkg-configure.cxx +++ b/bpkg/pkg-configure.cxx @@ -51,11 +51,109 @@ namespace bpkg // assert (unconstrain_deps == nullptr || simulate); + // No use case for both being specified. + // + assert (alts == nullptr || prev_prereqs == nullptr); + tracer_guard tg (db, trace); package_prerequisites prereqs; strings vars; + // Notes on the buildfile clauses evaluation: + // + // - In the manual configuration mode (alts == NULL, prev_prereqs == NULL) + // we always evaluate the enable and reflect clauses. We, however, fail + // if any of the prefer or require clauses are specified in any of the + // enabled dependency alternatives, assuming that this package didn't + // negotiate its preferences/requirements for the dependency + // configurations. + // + // Note that evaluating the require and prefer clauses in this case is + // meaningless since we don't reconfigure the dependencies nor negotiate + // configurations with other dependents. What we should probably do is + // load configurations of the dependencies and use them while evaluating + // the dependent's enable and reflect clauses as we go along. Probably + // we should still evaluate the accept clauses to make sure that the + // dependency is configured acceptably for the dependent. + // + // - In the pre-selected alternatives mode (alts != NULL, prev_prereqs == + // NULL) we don't evaluate the enable, prefer, and require clauses since + // they have already been evaluated as a part of the dependency + // alternatives selection and the dependency configurations negotiation. + // We, however always evaluate the reflect clauses. + // + // - In the reconfiguration mode (prev_prereqs != NULL, alts == NULL) we + // don't evaluate the prefer and require clauses, assuming that was done + // on some previous pkg-build run when this package and its dependencies + // have been configured. But because of this we may not evaluate the + // enable and reflect clauses which refer to dependency configuration + // variables. Thus, for now we fail if such an enable or reflect clause + // is encountered and evaluate all the enable and reflect clauses + // otherwise. In the future it feels like such cases should somehow + // be handled at the pkg-build level (e.g., detect such situations and + // cause the dependent re-evaluation instead of re-configuration). Note + // that if/when this is implemented, the current logic could still be + // used as an optimization (reflection of dependency configuration is + // not very common). + // + // @@ It seems there is a hole in the reconfiguration mode: + // + // foo -> libfoo {require {config.libfoo.proto=1} + // reflect {config.foo.reflect=1}} | + // libfoo {require {config.libfoo.proto=2} + // reflect {config.foo.reflect=2}} + // -> libbar {require {config.libfoo.proto=2}} + // -> libbaz + // + // foo is configured with config.foo.reflect=2 + // + // If afterwords libbaz is upgraded, the foo is + // reconfigured with config.foo.reflect=1 + // + // It feels more and more that the proper solution here is to go + // "nuclear" and to always "upgrade" re-configuration for a package + // with any prefer/require into a complete re-evaluation. The most + // likely drawback of this approach would be unnecessary + // re-evaluations if we use the "any prefer/require in any + // alternative" condition. So we may need to exclude some common + // simple cases where such an upgrade is not needed. For example: + // + // foo -> libfoo require {config.libfoo.proto=1} + // foo -> libbar require {config.libbar.proto=1} + // foo -> libbaz + // + // Feels like the condition will have to be based on the presence + // of clauses plus their textual analysis. + // + bool manual (alts == nullptr && prev_prereqs == nullptr); + + // In the reconfiguration mode keep track of configuration variable + // prefixes (in the 'config..' form) for dependencies in the + // selected alternatives with the prefer or require clauses specified and + // fail if any enable or reflect clause refers to them. + // + // Note that the enable and reflect clauses may only refer to dependency + // configuration variables of already selected alternatives with the + // prefer or require clauses specified. + // + vector banned_var_prefixes; + + auto verify_banned_vars = [&ps, + &banned_var_prefixes] (const string& clause, + const char* what) + { + for (const string& p: banned_var_prefixes) + { + if (clause.find (p) != string::npos) + { + fail << "unable to reconfigure dependent " << ps.package.name + << " with " << what << " clause that refers to dependency " + << "configuration variables"; + } + } + }; + // Alternatives argument must be parallel to the dependencies argument if // specified. // @@ -75,18 +173,6 @@ namespace bpkg size_t>, 2> edas; - // If the dependency alternatives are not pre-selected, then evaluate - // the enable clauses. - // - // Note that evaluating the require and prefer clauses in this case is - // meaningless since we don't reconfigure the dependencies nor negotiate - // configurations with other dependents. What we should probably do is - // load configurations of the dependencies and use them while evaluating - // the dependent's enable and reflect clauses as we go along. Probably - // we should still evaluate the accept clauses to make sure that the - // dependency is configured acceptably for the dependent. For now we - // fail and will support this maybe later. - // if (alts == nullptr) { if (toolchain_buildtime_dependency (o, das, &ps.package.name)) @@ -96,14 +182,23 @@ namespace bpkg { const dependency_alternative& da (das[i]); - if (!da.enable || ps.evaluate_enable (*da.enable, make_pair (di, i))) + // Evaluate the dependency alternative enable clause, if present, + // unless it refers to any banned variables in which case we fail. + // + if (da.enable) { - if (da.prefer || da.require) - fail << "manual configuration of dependents with prefer or " - << "require clauses is not yet supported"; + if (!banned_var_prefixes.empty ()) + verify_banned_vars (*da.enable, "enable"); - edas.push_back (make_pair (ref (da), i)); + if (!ps.evaluate_enable (*da.enable, make_pair (di, i))) + continue; } + + if (manual && (da.prefer || da.require)) + fail << "manual configuration of dependents with prefer or " + << "require clauses is not yet supported"; + + edas.push_back (make_pair (ref (da), i)); } if (edas.empty ()) @@ -130,7 +225,9 @@ namespace bpkg // for (const vector* pps (prev_prereqs);;) { - bool satisfied (false); + const pair, + size_t>* selected_alt (nullptr); + for (const auto& eda: edas) { const dependency_alternative& da (eda.first); @@ -335,12 +432,7 @@ namespace bpkg } } - // Evaluate the dependency alternative reflect clause, if present. - // - if (da.reflect) - ps.evaluate_reflect (*da.reflect, make_pair (di, dai)); - - satisfied = true; + selected_alt = &eda; break; } @@ -348,7 +440,7 @@ namespace bpkg // "recreate dependency decisions" mode. In the latter case fall back // to the "make dependency decisions" mode and retry. // - if (!satisfied) + if (selected_alt == nullptr) { if (pps != nullptr) { @@ -359,6 +451,32 @@ namespace bpkg fail << "unable to satisfy dependency on " << das; } + const dependency_alternative& da (selected_alt->first); + + // In the reconfiguration mode ban the usage of the selected + // alternative dependency configuration variables in the subsequent + // enable and reflect clauses. + // + if (alts == nullptr && !manual && (da.prefer || da.require)) + { + for (const dependency& d: da) + banned_var_prefixes.push_back ( + "config." + d.name.variable () + '.'); + } + + // Evaluate the selected dependency alternative reflect clause, if + // present, unless it refers to any banned variables in which case we + // fail. + // + if (da.reflect) + { + if (!banned_var_prefixes.empty ()) + verify_banned_vars (*da.reflect, "reflect"); + + ps.evaluate_reflect (*da.reflect, + make_pair (di, selected_alt->second)); + } + // The dependency alternative is selected and its dependencies are // resolved to the selected packages. So proceed to the next depends // value. diff --git a/bpkg/pkg-configure.hxx b/bpkg/pkg-configure.hxx index 24e06a3..876d11a 100644 --- a/bpkg/pkg-configure.hxx +++ b/bpkg/pkg-configure.hxx @@ -45,11 +45,10 @@ namespace bpkg // Given dependencies of a package, return its prerequisite packages, // configuration variables that resulted from selection of these // prerequisites (import, reflection, etc), and sources of the configuration - // variables resulted from evaluating the reflect clauses. See - // pkg_configure() for the semantics of the dependency list. Fail if for - // some of the dependency alternative lists there is no satisfactory - // alternative (all its dependencies are configured, satisfy the respective - // constraints, etc). + // variables resulted from evaluating the reflect clauses. Fail if for some + // of the dependency alternative lists there is no satisfactory alternative + // (all its dependencies are configured, satisfy the respective constraints, + // etc). // // The package dependency constraints are expected to be complete. // @@ -62,12 +61,41 @@ namespace bpkg // be parallel to the dependencies argument and specify indexes of the // selected alternatives. // - // If prerequisites corresponding to the previous configured state of the - // package are specified, then for each depends value try to select an - // alternative where dependencies all belong to this list (the "recreate + // If the dependency alternatives are not pre-selected (alternatives == + // NULL), then for each depends value select the first satisfactory + // alternative encountered. If, however, prerequisites corresponding to the + // previous configured state of the package are specified + // (prev_prerequisites != NULL), then for each depends value try to select + // an alternative where dependencies all belong to this list (the "recreate // dependency decisions" mode). Failed that, select an alternative as if no // prerequisites are specified (the "make dependency decisions" mode). // + // Note that there are actually 3 possible use cases for + // pkg_configure_prerequisites(): + // + // - The package is being configured manually. In this case its dependency + // alternatives are not pre-selected and there is no information about its + // previous configured state (alternatives == NULL, prev_prerequisites == + // NULL). + // + // - The package is being built, upgraded, or re-evaluated. In this case its + // dependency alternatives are pre-selected, their enable, prefer, and + // require clauses are evaluated, and there is no need in the previous + // configured state information (alternatives != NULL, prev_prerequisites + // == NULL). + // + // - The package is being reconfigured for a reason other than any of the + // mentioned above (dependency up/down-grade/reconfiguration, deorphaning, + // pkg-build --disfigure is specified, etc). In this case its dependency + // alternatives are not pre-selected but the previous configured state + // information is provided (alternatives == NULL, prev_prerequisites != + // NULL). + // + // - There are no use cases when both dependency alternatives are + // pre-selected and the previous configured state information needs to be + // provided. Thus, alternatives and prev_prerequisites must never be both + // NULL. + // // Optionally, remove constraints from the specified dependencies // (unconstrain_deps). Only allowed in the simulation mode. // @@ -122,7 +150,7 @@ namespace bpkg // required. // // Note: expects all the non-external packages to be configured to be - // already unpackged (for subproject discovery). + // already unpacked (for subproject discovery). // void pkg_configure (const common_options&, diff --git a/tests/common/dependency-alternatives/t8a/libfoo-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/libfoo-1.0.0.tar.gz new file mode 100644 index 0000000..f2dcb15 Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/libfoo-1.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/libfoo-2.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/libfoo-2.0.0.tar.gz new file mode 100644 index 0000000..2b6f0f5 Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/libfoo-2.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/tax-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/tax-1.0.0.tar.gz new file mode 100644 index 0000000..7c2b99d Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/tax-1.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/tex-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/tex-1.0.0.tar.gz new file mode 100644 index 0000000..663b09a Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/tex-1.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/tix-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/tix-1.0.0.tar.gz new file mode 100644 index 0000000..34ea3da Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/tix-1.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/tox-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/tox-1.0.0.tar.gz new file mode 100644 index 0000000..c767026 Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/tox-1.0.0.tar.gz differ diff --git a/tests/common/dependency-alternatives/t8a/tux-1.0.0.tar.gz b/tests/common/dependency-alternatives/t8a/tux-1.0.0.tar.gz new file mode 100644 index 0000000..e171e87 Binary files /dev/null and b/tests/common/dependency-alternatives/t8a/tux-1.0.0.tar.gz differ diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript index 945402b..80e83a2 100644 --- a/tests/pkg-build.testscript +++ b/tests/pkg-build.testscript @@ -146,17 +146,27 @@ # | |-- libbox-0.1.0.tar.gz # | |-- libbox-0.1.1.tar.gz # | |-- libbox-1.0.0.tar.gz -# | |-- foo-1.0.0.tar.gz -> {libbar libbaz} ^1.0.0 -# | |-- fox-1.0.0.tar.gz -> libbar ^1.0.0 | libbaz ^1.0.0 -# | |-- fix-1.0.0.tar.gz -> libbaz ^1.0.0 | libbar ^1.0.0 +# | |-- libfoo-1.0.0.tar.gz +# | |-- libfoo-2.0.0.tar.gz +# | |-- bar -> libbar +# | |-- baz -> libbaz +# | |-- box -> libbiz ^1.0.0 config.box.backend=libbiz | +# | | libbox >= 0.1.1 config.box.backend=libbox, +# | | libbaz # | |-- fax-1.0.0.tar.gz -> libbar ^1.0.0 ? ($cxx.target.class == 'windows') config.fax.backend=libbar | # | | libbaz ^1.0.0 ? ($cxx.target.class != 'windows') config.fax.backend=libbaz, # | | libbiz ? ($config.fax.libbiz) config.fax.extras='[b\i$z]', # | | libbox ? ($config.fax.libbox && $config.fax.backend == libbaz && $config.fax.extras == '[b\i$z]') +# | |-- fix-1.0.0.tar.gz -> libbaz ^1.0.0 | libbar ^1.0.0 +# | |-- foo-1.0.0.tar.gz -> {libbar libbaz} ^1.0.0 +# | |-- fox-1.0.0.tar.gz -> libbar ^1.0.0 | libbaz ^1.0.0 # | |-- fux -> libbiz ? (!$config.fux.libbiz_old) | libbiz ^0.1.0 ? ($config.fux.libbiz_old) -# | |-- box -> libbiz ^1.0.0 config.box.backend=libbiz | -# | | libbox >= 0.1.1 config.box.backend=libbox, -# | | libbaz +# | |-- tax -> libfoo == 1.0.0 | libfoo == 2.0.0 +# | |-- tex -> libfoo {prefer{} accept(false) reflect {...}} +# | |-- tix -> libfoo >= 2.0.0 reflect {...} | libfoo >= 1.0.0 reflect {...} +# | |-- tox -> libfoo >= 2.0.0 {prefer{} accept(false) reflect {...}} | libfoo >= 1.0.0 reflect {...} +# | |-- tux -> libfoo {prefer{config.libfoo.protocol = "1"} accept(false) +# | | -> libbox ? (config.libfoo.protocol == "1") # | `-- repositories.manifest # | # |-- t9 @@ -275,7 +285,7 @@ # | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...)} # | |-- baz-1.0.0.tar.gz -> liba {prefer {...} accept (...)} # | |-- biz-1.0.0.tar.gz -> liba {prefer {...} accept (...)} -# | |-- box-1.0.0.tar.gz -> liba {prefer {} accept (true) reflect (...)} +# | |-- box-1.0.0.tar.gz -> liba {prefer {} accept (true) reflect {...}} # | `-- repositories.manifest # | # |-- t13b @@ -287,14 +297,14 @@ # | # |-- t13c # | |-- liba-0.1.0.tar.gz -# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)} +# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}} # | |-- baz-1.0.0.tar.gz -> liba {require {...}} # | `-- repositories.manifest # | # |-- t13d # | |-- liba-0.1.0.tar.gz # | |-- libb-0.1.0.tar.gz -# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)}, +# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}}, # | | libb ? (...) # | |-- baz-1.0.0.tar.gz -> bar, liba {require {...}} # | `-- repositories.manifest @@ -317,14 +327,14 @@ # |-- t13g # | |-- liba-0.1.0.tar.gz # | |-- libb-0.1.0.tar.gz -# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)}, -# | | libb {prefer {...} accept (...) reflect (...)} -# | |-- baz-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)}, +# | |-- bar-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}}, +# | | libb {prefer {...} accept (...) reflect {...}} +# | |-- baz-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}}, # | | libb ? (...) -# | |-- biz-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)}, -# | | libb {prefer {...} accept (...) reflect (...)} -# | |-- box-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect (...)}, -# | | libb {prefer {...} accept (...) reflect (...)} +# | |-- biz-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}}, +# | | libb {prefer {...} accept (...) reflect {...}} +# | |-- box-1.0.0.tar.gz -> liba {prefer {...} accept (...) reflect {...}}, +# | | libb {prefer {...} accept (...) reflect {...}} # | `-- repositories.manifest # | # |-- t13h @@ -335,7 +345,7 @@ # | # |-- t13i # | |-- liba-0.1.0.tar.gz -# | |-- bar-1.0.0.tar.gz -> liba {require {...} reflect (...)} +# | |-- bar-1.0.0.tar.gz -> liba {require {...} reflect {...}} # | `-- repositories.manifest # | # |-- t13j @@ -5023,6 +5033,227 @@ test.arguments += --sys-no-query $pkg_drop fax } } + + : reconfigure-dependent + : + : Test some cases when a dependent needs to be reconfigured due to an + : upgraded dependency. + : + { + +$clone_cfg + + test.arguments += --yes + + : keep-alternative + : + { + $clone_cfg; + + $* tax ?libfoo/1.0.0 2>!; + + $pkg_status -r >>EOO; + !tax configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + $* --upgrade --recursive 2>!; # Noop. + + $pkg_status -r >>EOO; + !tax configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + $* ?libfoo 2>!; # Noop. + + $pkg_status -r >>EOO; + !tax configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + $* ?libfoo/2.0.0 2>>EOE != 0; + error: package libfoo doesn't satisfy its dependents + info: libfoo/2.0.0 doesn't satisfy tax/1.0.0 + EOE + + $pkg_status -r >>EOO; + !tax configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + $pkg_drop tax + } + + : re-evaluate-dependent + : + { + $clone_cfg; + + $* tex ?libfoo/1.0.0 2>!; + + $pkg_status -r >>EOO; + !tex configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + cat cfg/tex-1.0.0/build/config.build >>~%EOO%; + %.* + config.tex.libfoo_protocol = 1 + %.* + EOO + + # @@ Strangely, if upgrade with -ur instead of ?libfoo, then status + # prints 'libfoo configured !2.0.0' instead of + # 'libfoo configured 2.0.0'. + # + $* ?libfoo 2>>~%EOE%; + disfigured tex/1.0.0 + disfigured libfoo/1.0.0 + fetched libfoo/2.0.0 + unpacked libfoo/2.0.0 + configured libfoo/2.0.0 + configured tex/1.0.0 + %info: .+tex-1.0.0.+ is up to date% + updated tex/1.0.0 + EOE + + cat cfg/tex-1.0.0/build/config.build >>~%EOO%; + %.* + config.tex.libfoo_protocol = 2 + %.* + EOO + + $pkg_status -r >>EOO; + !tex configured 1.0.0 + libfoo configured 2.0.0 + EOO + + $pkg_drop tex + } + + : re-evaluate-reflect + : + { + $clone_cfg; + + # @@ The fact that `$* tix` fails as follows but `$* tix ?libfoo` + # doesn't looks confusing: + # + # error: unable to select dependency alternative for package tix/1.0.0 + # info: explicitly specify dependency packages to manually select the alternative + # info: alternative: libfoo + # info: alternative: libfoo + # info: while satisfying tix/1.0.0 + # + # Note: + # + # tix -> libfoo>=2.0.0 reflect{...} | libfoo>=1.0.0 reflect{...} + # + $* tix ?libfoo/1.0.0 2>!; + + $pkg_status -r >>EOO; + !tix configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + cat cfg/tix-1.0.0/build/config.build >>~%EOO%; + %.* + config.tix.reflect = 1 + %.* + EOO + + $* ?libfoo 2>>~%EOE%; + disfigured tix/1.0.0 + disfigured libfoo/1.0.0 + fetched libfoo/2.0.0 + unpacked libfoo/2.0.0 + configured libfoo/2.0.0 + configured tix/1.0.0 + %info: .+tix-1.0.0.+ is up to date% + updated tix/1.0.0 + EOE + + $pkg_status -r >>EOO; + !tix configured 1.0.0 + libfoo configured 2.0.0 + EOO + + cat cfg/tix-1.0.0/build/config.build >>~%EOO%; + %.* + config.tix.reflect = 2 + %.* + EOO + + $pkg_drop tix + } + + : fail-select-alt-with-reflect + : + { + $clone_cfg; + + $* tox ?libfoo/1.0.0 2>!; + + $pkg_status -r >>EOO; + !tox configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + cat cfg/tox-1.0.0/build/config.build >>~%EOO%; + %.* + config.tox.libfoo_protocol = '1 or 2' + %.* + EOO + + # Note that the current behavior should actually be considered as a + # bug which we will fix eventually. The proper behaviour would be to + # re-evaluate this dependent rather than just to re-configure. + # + $* ?libfoo 2>>~%EOE% != 0; + error: unable to reconfigure dependent tox with reflect clause that refers to dependency configuration variables + info: while configuring tox + EOE + + $pkg_status -r >>EOO; + !tox configured 1.0.0 + libfoo configured !1.0.0 available 2.0.0 + EOO + + cat cfg/tox-1.0.0/build/config.build >>~%EOO%; + %.* + config.tox.libfoo_protocol = '1 or 2' + %.* + EOO + + $pkg_drop tox + } + + : fail-enable-banned-var + : + { + $clone_cfg; + + $* tux ?libbox/0.1.0 2>!; + + $pkg_status -r >>EOO; + !tux configured 1.0.0 + libbox configured !0.1.0 available 1.0.0 0.1.1 + libfoo configured 2.0.0 + EOO + + $* ?libbox 2>>EOE != 0; + error: unable to reconfigure dependent tux with enable clause that refers to dependency configuration variables + info: while configuring tux + EOE + + $pkg_status -r >>EOO; + !tux configured 1.0.0 + libbox configured !0.1.0 available 1.0.0 0.1.1 + libfoo configured 2.0.0 + EOO + + $pkg_drop tux + } + } } : version-replacement -- cgit v1.1