From 76632ec8816369f5b7cf503a37e75fe814bb12bf Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 9 Nov 2023 19:23:14 +0300 Subject: Fix unexpected 'unable to satisfy dependency' error in pkg_configure() by turning collect_order_dependent() into collect_dependent() --- bpkg/pkg-build-collect.cxx | 187 ++++++++++--------------- bpkg/pkg-build-collect.hxx | 76 +++++----- bpkg/pkg-build.cxx | 29 ++-- tests/common/satisfy/libbar-2.1.0.tar.gz | Bin 0 -> 414 bytes tests/common/satisfy/libbax-1.0.0.tar.gz | Bin 0 -> 347 bytes tests/common/satisfy/libbax-2.0.0.tar.gz | Bin 0 -> 350 bytes tests/common/satisfy/libbox-1.0.0.tar.gz | Bin 0 -> 361 bytes tests/common/satisfy/libbox-2.0.0.tar.gz | Bin 0 -> 367 bytes tests/common/satisfy/libfoo-2.0.0.tar.gz | Bin 0 -> 368 bytes tests/common/satisfy/t4f/libbar-1.2.0.tar.gz | 1 + tests/common/satisfy/t4f/libbar-2.1.0.tar.gz | 1 + tests/common/satisfy/t4f/libbax-1.0.0.tar.gz | 1 + tests/common/satisfy/t4f/libbax-2.0.0.tar.gz | 1 + tests/common/satisfy/t4f/libbox-1.0.0.tar.gz | 1 + tests/common/satisfy/t4f/libbox-2.0.0.tar.gz | 1 + tests/common/satisfy/t4f/libfoo-2.0.0.tar.gz | 1 + tests/common/satisfy/t4f/repositories.manifest | 4 + tests/pkg-build.testscript | 138 +++++++++++++++++- tests/pkg-build/t4f | 1 + 19 files changed, 276 insertions(+), 166 deletions(-) create mode 100644 tests/common/satisfy/libbar-2.1.0.tar.gz create mode 100644 tests/common/satisfy/libbax-1.0.0.tar.gz create mode 100644 tests/common/satisfy/libbax-2.0.0.tar.gz create mode 100644 tests/common/satisfy/libbox-1.0.0.tar.gz create mode 100644 tests/common/satisfy/libbox-2.0.0.tar.gz create mode 100644 tests/common/satisfy/libfoo-2.0.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbar-1.2.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbar-2.1.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbax-1.0.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbax-2.0.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbox-1.0.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libbox-2.0.0.tar.gz create mode 120000 tests/common/satisfy/t4f/libfoo-2.0.0.tar.gz create mode 100644 tests/common/satisfy/t4f/repositories.manifest create mode 120000 tests/pkg-build/t4f diff --git a/bpkg/pkg-build-collect.cxx b/bpkg/pkg-build-collect.cxx index d251a77..c0a592f 100644 --- a/bpkg/pkg-build-collect.cxx +++ b/bpkg/pkg-build-collect.cxx @@ -1675,9 +1675,9 @@ namespace bpkg << bp.available_name_version_db () << " (" << c->value << ')';}); - // Note that in contrast to collect_order_dependents(), here - // we also save both unsatisfied constraints and the - // dependency chain, for the sake of the diagnostics. + // Note that in contrast to collect_dependents(), here we also + // save both unsatisfied constraints and the dependency chain, + // for the sake of the diagnostics. // vector ucs { unsatisfied_constraint { @@ -5806,7 +5806,7 @@ namespace bpkg // then it doesn't need to be reconfigured either since nothing // changes for its config clauses. Otherwise, the // build_package::adjust_reconfigure flag will be added normally - // by collect_order_dependents(). + // by collect_dependents(). // collect_existing_dependent (o, ed, @@ -7091,50 +7091,49 @@ namespace bpkg return order (db, name, chain, fdb, reorder); } - void build_packages:: - collect_order_dependents (const repointed_dependents& rpt_depts, - unsatisfied_dependents& unsatisfied_depts) + set build_packages:: + collect_dependents (const repointed_dependents& rpt_depts, + unsatisfied_dependents& unsatisfied_depts) { + set r; + + // First, cache the packages in the map since we will be adding new + // entries to the map while collecting dependents of the initial package + // set, recursively. + // // Note: the pointer is stable (points to a value in std::map). // - set visited_deps; + vector deps; - // For each package on the list we want to insert all its dependents - // before it so that they get configured after the package on which they - // depend is configured (remember, our build order is reverse, with the - // last package being built first). This applies to both packages that are - // already on the list as well as the ones that we add, recursively. - // - for (auto i (begin ()); i != end (); ++i) + for (auto& p: map_) { - const build_package& p (*i); + build_package& d (p.second.package); // Prune if this is not a configured package being up/down-graded // or reconfigured. // - assert (p.action); - - // Dropped package may have no dependents. - // - if (*p.action != build_package::drop && p.reconfigure ()) - collect_order_dependents (i, - rpt_depts, - unsatisfied_depts, - visited_deps); + if (d.action && *d.action != build_package::drop && d.reconfigure ()) + deps.push_back (&d); } + + // Note: the pointer is stable (see above for details). + // + set visited_deps; + + for (build_package* p: deps) + collect_dependents (*p, rpt_depts, unsatisfied_depts, visited_deps, r); + + return r; } void build_packages:: - collect_order_dependents (iterator pos, - const repointed_dependents& rpt_depts, - unsatisfied_dependents& unsatisfied_depts, - set& visited_deps) + collect_dependents (build_package& p, + const repointed_dependents& rpt_depts, + unsatisfied_dependents& unsatisfied_depts, + set& visited_deps, + set& r) { - tracer trace ("collect_order_dependents"); - - assert (pos != end ()); - - build_package& p (*pos); + tracer trace ("collect_dependents"); // Bail out if the dependency has already been visited and add it to the // visited set otherwise. @@ -7167,14 +7166,8 @@ namespace bpkg // dependent. But first "prune" if the dependent is being dropped or // this is a replaced prerequisite of the repointed dependent. // - // Note that the package drops are not ordered at this stage, since to - // order them properly all the package reconfigurations must be - // determined. - // - // Also note that the repointed dependents are always collected and - // have all their collected prerequisites ordered (including new and - // old ones). See collect_build_prerequisites() and order() for - // details. + // Note that the repointed dependents are always collected (see + // collect_build_prerequisites() for details). // bool check (ud != 0 && dc); @@ -7187,30 +7180,27 @@ namespace bpkg if (dp.action && *dp.action == build_package::drop) continue; - if (i->second.position != end ()) - { - repointed_dependents::const_iterator j ( - rpt_depts.find (package_key {ddb, dn})); + repointed_dependents::const_iterator j ( + rpt_depts.find (package_key {ddb, dn})); - if (j != rpt_depts.end ()) - { - const map& prereqs_flags (j->second); + if (j != rpt_depts.end ()) + { + const map& prereqs_flags (j->second); - auto k (prereqs_flags.find (package_key {pdb, n})); + auto k (prereqs_flags.find (package_key {pdb, n})); - if (k != prereqs_flags.end () && !k->second) - continue; - } - - // There is one tricky aspect: the dependent could be in the - // process of being reconfigured or up/downgraded as well. In this - // case all we need to do is detect this situation and skip the - // test since all the (new) constraints of this package have been - // satisfied in collect_build(). - // - if (check) - check = !dp.dependencies; + if (k != prereqs_flags.end () && !k->second) + continue; } + + // There is one tricky aspect: the dependent could be in the process + // of being reconfigured or up/downgraded as well. In this case all + // we need to do is detect this situation and skip the test since + // all the (new) constraints of this package have been satisfied in + // collect_build(). + // + if (check) + check = !dp.dependencies; } if (check) @@ -7272,57 +7262,32 @@ namespace bpkg build_package::adjust_reconfigure}; }; - // We can have three cases here: the package is already on the list, - // the package is in the map (but not on the list) and it is in - // neither. - // - // If the existing entry is pre-entered, is an adjustment, or is a - // build that is not supposed to be built (not in the list), then we - // merge it into the new adjustment entry. Otherwise (is a build in - // the list), we just add the reconfigure adjustment flag to it. + // If the existing entry is pre-entered or is an adjustment, then we + // merge it into the new adjustment entry. Otherwise (is a build), we + // just add the reconfigure adjustment flag to it, unless it is + // already being reconfigured. In the later case we don't add the + // dependent to the resulting set since we neither add a new entry to + // the map nor modify an existing one. // + bool add (true); if (i != map_.end ()) { build_package& dp (i->second.package); - iterator& dpos (i->second.position); - if (!dp.action || // Pre-entered. - *dp.action != build_package::build || // Non-build. - dpos == end ()) // Build not in the list. + if (!dp.action || // Pre-entered. + *dp.action != build_package::build) // Adjustment. { build_package bp (adjustment ()); bp.merge (move (dp)); dp = move (bp); } - else // Build in the list. - dp.flags |= build_package::adjust_reconfigure; - - // It may happen that the dependent is already in the list but is - // not properly ordered against its dependencies that get into the - // list via another dependency path. Thus, we check if the dependent - // is to the right of its dependency and, if that's the case, - // reinsert it in front of the dependency. - // - if (dpos != end ()) + else // Build. { - for (auto i (pos); i != end (); ++i) - { - if (i == dpos) - { - erase (dpos); - dpos = insert (pos, dp); - - // Remove the moved dependent from the visited dependencies - // set, if present, so its own dependents can be reordered to - // the left of this dependent. - // - visited_deps.erase (&dp); - break; - } - } + if (!dp.reconfigure ()) + dp.flags |= build_package::adjust_reconfigure; + else + add = false; } - else - dpos = insert (pos, dp); } else { @@ -7330,10 +7295,13 @@ namespace bpkg // i = map_.emplace (package_key {ddb, dn}, data_type {end (), adjustment ()}).first; - - i->second.position = insert (pos, i->second.package); } + if (add) + r.insert (i->first); + + build_package& dp (i->second.package); + // Add this dependent's constraint, if present, to the dependency's // constraints list for completeness, while suppressing duplicates. // @@ -7344,7 +7312,7 @@ namespace bpkg constraint_type c (move (*dc), ddb, move (dn), - i->second.package.selected->version, + dp.selected->version, true /* selected_dependent */); if (find_if (p.constraints.begin (), p.constraints.end (), @@ -7358,16 +7326,13 @@ namespace bpkg } } - // Recursively collect our own dependents inserting them before us. + // Recursively collect our own dependents. // // Note that we cannot end up with an infinite recursion for - // configured packages due to a dependency cycle (see order() for - // details). + // configured packages due to a dependency cycle since we "prune" for + // visited dependencies (also see order() for details). // - collect_order_dependents (i->second.position, - rpt_depts, - unsatisfied_depts, - visited_deps); + collect_dependents (dp, rpt_depts, unsatisfied_depts, visited_deps, r); } } } diff --git a/bpkg/pkg-build-collect.hxx b/bpkg/pkg-build-collect.hxx index 74a48a0..86878f0 100644 --- a/bpkg/pkg-build-collect.hxx +++ b/bpkg/pkg-build-collect.hxx @@ -1571,6 +1571,27 @@ namespace bpkg const function&, postponed_configuration* = nullptr); + // If a configured package is being up/down-graded or reconfigured then + // that means all its configured dependents could be affected and we have + // to reconfigure them. This function examines every such a package that + // is already in the map and collects all its configured dependents. We + // also need to make sure the dependents are ok with the up/downgrade. If + // some dependency constraints are not satisfied, then cache them and + // proceed further as if no problematic constraints are imposed (see + // unsatisfied_dependents for details). Return the set of the collected + // dependents. + // + // Should we reconfigure just the direct depends or also include indirect, + // recursively? Consider this plausible scenario as an example: We are + // upgrading a package to a version that provides an additional API. When + // its direct dependent gets reconfigured, it notices this new API and + // exposes its own extra functionality that is based on it. Now it would + // make sense to let its own dependents (which would be our original + // package's indirect ones) to also notice this. + // + std::set + collect_dependents (const repointed_dependents&, unsatisfied_dependents&); + // Order the previously-collected package with the specified name and // configuration returning its position. // @@ -1584,27 +1605,6 @@ namespace bpkg const function&, bool reorder = true); - // If a configured package is being up/down-graded then that means all its - // dependents could be affected and we have to reconfigure them. This - // function examines every package that is already on the list and - // collects and orders all its dependents. We also need to make sure the - // dependents are ok with the up/downgrade. If some dependency constraints - // are not satisfied, then cache them and proceed further as if no - // problematic constraints are imposed (see unsatisfied_dependents for - // details). - // - // Should we reconfigure just the direct depends or also include indirect, - // recursively? Consider this plauisible scenario as an example: We are - // upgrading a package to a version that provides an additional API. When - // its direct dependent gets reconfigured, it notices this new API and - // exposes its own extra functionality that is based on it. Now it would - // make sense to let its own dependents (which would be our original - // package's indirect ones) to also notice this. - // - void - collect_order_dependents (const repointed_dependents&, - unsatisfied_dependents&); - void clear (); @@ -1744,6 +1744,20 @@ namespace bpkg unsatisfied_dependents&, bool add_required_by); + // Skip the dependents collection for the specified dependency if that has + // already been done. + // + // Note that if this function has already been called for this dependency, + // then all its dependents are already in the map and their dependency + // constraints have been checked. + // + void + collect_dependents (build_package&, + const repointed_dependents&, + unsatisfied_dependents&, + std::set& visited_deps, + std::set& result); + struct package_ref { database& db; @@ -1761,26 +1775,6 @@ namespace bpkg const function&, bool reorder); - // Skip the dependents collection/ordering for the specified dependency if - // that has already been done. - // - // Note that if this function has already been called for this dependency, - // then all its dependents are already in the map and the dependency - // constraints have been checked for them. Also they are in the list and - // are ordered to the left of this dependency, unless this dependency has - // been moved to the left itself since the previous visit. Such a move can - // only happen if this dependency is a dependent of some other dependency - // whose dependents have been collected/ordered since that previous visit. - // This function tracks such moves and just removes the moved dependencies - // from the visited set, so their dependents can be properly reordered - // after the move. - // - void - collect_order_dependents (iterator, - const repointed_dependents&, - unsatisfied_dependents&, - std::set& visited_deps); - private: struct data_type { diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index ede26bf..5844397 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -4543,6 +4543,9 @@ namespace bpkg continue; } + set depts ( + pkgs.collect_dependents (rpt_depts, unsatisfied_depts)); + // Now that we have collected all the package versions that we need to // build, arrange them in the "dependency order", that is, with every // package on the list only possibly depending on the ones after @@ -4554,9 +4557,10 @@ namespace bpkg // // The order of dependency upgrades/downgrades/drops is not really // deterministic. We, however, do upgrades/downgrades before hold_pkgs - // so that they appear (e.g., on the plan) last. We handle drops - // later, though, after collecting/ordering dependents when all the - // package reconfigurations are determined. + // so that they appear (e.g., on the plan) after the packages being + // built to hold. We handle drops last, though, so that the unused + // packages are likely get purged before the package fetches, so that + // the disk space they occupy can be reused. // for (const dep& d: deps) { @@ -4576,6 +4580,9 @@ namespace bpkg find_prereq_database, false /* reorder */); + // Order the existing dependents which have participated in + // negotiation of the configuration of their dependencies. + // for (const postponed_configuration& cfg: postponed_cfgs) { for (const auto& d: cfg.dependents) @@ -4588,6 +4595,14 @@ namespace bpkg } } + // Order the existing dependents whose dependencies are being + // up/down-graded or reconfigured. + // + for (const package_key& p: depts) + pkgs.order (p.db, p.name, find_prereq_database, false /* reorder */); + + // Order the re-collected packages (deviated dependents, etc). + // for (build_package* p: postponed_recs) { assert (p->recursive_collection); @@ -4595,12 +4610,6 @@ namespace bpkg pkgs.order (p->db, p->name (), find_prereq_database); } - // Collect and order all the dependents that we will need to - // reconfigure because of the up/down-grades of packages that are now - // on the list. - // - pkgs.collect_order_dependents (rpt_depts, unsatisfied_depts); - // Make sure all the packages that we need to unhold are on the list. // for (const dependency_package& p: dep_pkgs) @@ -6463,7 +6472,7 @@ namespace bpkg // In the simulation mode unconstrain all the unsatisfactory // dependencies, if any, while configuring the dependent (see - // build_packages::collect_order_dependents() for details). + // build_packages::collect_dependents() for details). // // Note: must be called at most once. // diff --git a/tests/common/satisfy/libbar-2.1.0.tar.gz b/tests/common/satisfy/libbar-2.1.0.tar.gz new file mode 100644 index 0000000..0ff50c5 Binary files /dev/null and b/tests/common/satisfy/libbar-2.1.0.tar.gz differ diff --git a/tests/common/satisfy/libbax-1.0.0.tar.gz b/tests/common/satisfy/libbax-1.0.0.tar.gz new file mode 100644 index 0000000..7f4dfd0 Binary files /dev/null and b/tests/common/satisfy/libbax-1.0.0.tar.gz differ diff --git a/tests/common/satisfy/libbax-2.0.0.tar.gz b/tests/common/satisfy/libbax-2.0.0.tar.gz new file mode 100644 index 0000000..f130da0 Binary files /dev/null and b/tests/common/satisfy/libbax-2.0.0.tar.gz differ diff --git a/tests/common/satisfy/libbox-1.0.0.tar.gz b/tests/common/satisfy/libbox-1.0.0.tar.gz new file mode 100644 index 0000000..90227f7 Binary files /dev/null and b/tests/common/satisfy/libbox-1.0.0.tar.gz differ diff --git a/tests/common/satisfy/libbox-2.0.0.tar.gz b/tests/common/satisfy/libbox-2.0.0.tar.gz new file mode 100644 index 0000000..15d457f Binary files /dev/null and b/tests/common/satisfy/libbox-2.0.0.tar.gz differ diff --git a/tests/common/satisfy/libfoo-2.0.0.tar.gz b/tests/common/satisfy/libfoo-2.0.0.tar.gz new file mode 100644 index 0000000..fd8eeb3 Binary files /dev/null and b/tests/common/satisfy/libfoo-2.0.0.tar.gz differ diff --git a/tests/common/satisfy/t4f/libbar-1.2.0.tar.gz b/tests/common/satisfy/t4f/libbar-1.2.0.tar.gz new file mode 120000 index 0000000..b4a7773 --- /dev/null +++ b/tests/common/satisfy/t4f/libbar-1.2.0.tar.gz @@ -0,0 +1 @@ +../libbar-1.2.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libbar-2.1.0.tar.gz b/tests/common/satisfy/t4f/libbar-2.1.0.tar.gz new file mode 120000 index 0000000..0df079a --- /dev/null +++ b/tests/common/satisfy/t4f/libbar-2.1.0.tar.gz @@ -0,0 +1 @@ +../libbar-2.1.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libbax-1.0.0.tar.gz b/tests/common/satisfy/t4f/libbax-1.0.0.tar.gz new file mode 120000 index 0000000..137b938 --- /dev/null +++ b/tests/common/satisfy/t4f/libbax-1.0.0.tar.gz @@ -0,0 +1 @@ +../libbax-1.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libbax-2.0.0.tar.gz b/tests/common/satisfy/t4f/libbax-2.0.0.tar.gz new file mode 120000 index 0000000..465832f --- /dev/null +++ b/tests/common/satisfy/t4f/libbax-2.0.0.tar.gz @@ -0,0 +1 @@ +../libbax-2.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libbox-1.0.0.tar.gz b/tests/common/satisfy/t4f/libbox-1.0.0.tar.gz new file mode 120000 index 0000000..3bc2a0c --- /dev/null +++ b/tests/common/satisfy/t4f/libbox-1.0.0.tar.gz @@ -0,0 +1 @@ +../libbox-1.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libbox-2.0.0.tar.gz b/tests/common/satisfy/t4f/libbox-2.0.0.tar.gz new file mode 120000 index 0000000..1ec50e6 --- /dev/null +++ b/tests/common/satisfy/t4f/libbox-2.0.0.tar.gz @@ -0,0 +1 @@ +../libbox-2.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/libfoo-2.0.0.tar.gz b/tests/common/satisfy/t4f/libfoo-2.0.0.tar.gz new file mode 120000 index 0000000..406696d --- /dev/null +++ b/tests/common/satisfy/t4f/libfoo-2.0.0.tar.gz @@ -0,0 +1 @@ +../libfoo-2.0.0.tar.gz \ No newline at end of file diff --git a/tests/common/satisfy/t4f/repositories.manifest b/tests/common/satisfy/t4f/repositories.manifest new file mode 100644 index 0000000..4cc7c0a --- /dev/null +++ b/tests/common/satisfy/t4f/repositories.manifest @@ -0,0 +1,4 @@ +: 1 +: +location: ../t4a +role: complement diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript index 3cb3f03..4766e2a 100644 --- a/tests/pkg-build.testscript +++ b/tests/pkg-build.testscript @@ -106,6 +106,16 @@ # | |-- libfoo-1.1.0+1.tar.gz # | `-- repositories.manifest # | +# |-- t4f +# | |-- libfoo-2.0.0.tar.gz -> libbar == 1.2.0 +# | |-- libbar-1.2.0.tar.gz +# | |-- libbar-2.1.0.tar.gz -> libbox +# | |-- libbox-1.0.0.tar.gz -> libbax +# | |-- libbox-2.0.0.tar.gz -> libbax == 1.0.0 +# | |-- libbax-1.0.0.tar.gz +# | |-- libbax-2.0.0.tar.gz +# | `-- repositories.manifest +# | # |-- t5 # | |-- libbar-1.2.0.tar.gz # | |-- libbox-1.2.0.tar.gz @@ -486,6 +496,7 @@ posix = ($cxx.target.class != 'windows') cp -r $src/t4c $out/t4c && $rep_create $out/t4c &$out/t4c/packages.manifest cp -r $src/t4d $out/t4d && $rep_create $out/t4d &$out/t4d/packages.manifest cp -r $src/t4e $out/t4e && $rep_create $out/t4e &$out/t4e/packages.manifest + cp -r $src/t4f $out/t4f && $rep_create $out/t4f &$out/t4f/packages.manifest cp -r $src/t5 $out/t5 && $rep_create $out/t5 &$out/t5/packages.manifest cp -r $src/t6 $out/t6 && $rep_create $out/t6 &$out/t6/packages.manifest cp -r $src/t7a $out/t7a && $rep_create $out/t7a &$out/t7a/packages.manifest @@ -3849,10 +3860,9 @@ test.arguments += --sys-no-query : adjust-merge-build : - : Test that the registered in the map but not ordered package build - : (libfoo) is properly merged into the reconfigure adjustment as a - : dependent of the reconfigured dependency (see collect_order_dependents() - : for more details). + : Test that the registered in the map package build (libfoo) is properly + : merged into the reconfigure adjustment as a dependent of the + : reconfigured dependency (see collect_dependents() for more details). : { $clone_root_cfg; @@ -3886,6 +3896,113 @@ test.arguments += --sys-no-query $pkg_drop libbaz libbar libfoo } + + : reconfiguration + : + { + +$clone_root_cfg + +$rep_add $rep/t4f && $rep_fetch + + : re-order + : + : This test reproduced a failure of the collect_order_dependents() + : function (now turned into collect_dependents()) to properly order + : dependents of a being upgraded package, if the current version of this + : package is a dependent of a being reconfigured dependency. The now + : fixed bug ended up with the 'unable to satisfy dependency' failure of + : the subsequent pkg_configure() function call for the described case. + : + { + $clone_cfg; + + $* libbar libbox/1.0.0 ?libbax/1.0.0 2>!; + + $pkg_status -ar >>EOO; + libbax configured !1.0.0 available 2.0.0 + !libbox configured !1.0.0 available 2.0.0 + libbax configured !1.0.0 available 2.0.0 + !libbar configured 2.1.0 + !libbox configured !1.0.0 available 2.0.0 + libbax configured !1.0.0 available 2.0.0 + EOO + + $* libfoo libbax 2>>EOE; + warning: package libfoo dependency on (libbar == 1.2.0) is forcing downgrade of libbar/2.1.0 to 1.2.0 + disfigured libbar/2.1.0 + disfigured libbox/1.0.0 + disfigured libbax/1.0.0 + fetched libbax/2.0.0 + unpacked libbax/2.0.0 + fetched libbar/1.2.0 + unpacked libbar/1.2.0 + fetched libfoo/2.0.0 + unpacked libfoo/2.0.0 + configured libbax/2.0.0 + configured libbox/1.0.0 + configured libbar/1.2.0 + configured libfoo/2.0.0 + EOE + + $pkg_status -ar >>EOO; + !libbax configured 2.0.0 + !libbox configured !1.0.0 available 2.0.0 + !libbax configured 2.0.0 + !libbar configured 1.2.0 available 2.1.0 + !libfoo configured 2.0.0 + !libbar configured 1.2.0 available 2.1.0 + EOO + + $pkg_drop libbax libbox libbar libfoo + } + + : re-order-unsatisfied + : + : Similar to the above but the dependent of the mentioned package is + : unsatisfied with its dependencies. + : + { + $clone_cfg; + + $* libbar libbox ?libbax/1.0.0 2>!; + + $pkg_status -ar >>EOO; + libbax configured !1.0.0 available 2.0.0 + !libbox configured 2.0.0 + libbax configured !1.0.0 available 2.0.0 + !libbar configured 2.1.0 + !libbox configured 2.0.0 + libbax configured !1.0.0 available 2.0.0 + EOO + + $* libfoo libbax/2.0.0 --verbose 5 2>>~%EOE% != 0; + %.* + trace: pkg_build: refine package collection/plan execution from scratch + trace: collect_build: add libfoo/2.0.0 + trace: collect_build: add libbax/2.0.0 + trace: collect_build_prerequisites: begin libfoo/2.0.0 + trace: collect_build: add libbar/1.2.0 + warning: package libfoo dependency on (libbar == 1.2.0) is forcing downgrade of libbar/2.1.0 to 1.2.0 + trace: collect_build_prerequisites: no cfg-clause for dependency libbar/1.2.0 of dependent libfoo/2.0.0 + trace: collect_build_prerequisites: begin libbar/1.2.0 + trace: collect_build_prerequisites: end libbar/1.2.0 + trace: collect_build_prerequisites: end libfoo/2.0.0 + trace: collect_build_prerequisites: skip unsatisfied existing dependent libbox of dependency libbax/2.0.0 due to constraint (libbax == 1.0.0) + trace: collect_build_prerequisites: begin libbax/2.0.0 + trace: collect_build_prerequisites: end libbax/2.0.0 + trace: collect_dependents: postpone failure for existing dependent libbox unsatisfied with dependency libbax/2.0.0 (== 1.0.0) + trace: execute_plan: simulate: yes + %.* + error: unable to upgrade package libbax/1.0.0 to 2.0.0 + info: because configured package libbox/2.0.0 depends on (libbax == 1.0.0) + info: consider re-trying with --upgrade|-u potentially combined with --recursive|-r + info: or explicitly request up/downgrade of package libbox + info: or explicitly specify package libbax version to manually satisfy these constraints + %.* + EOE + + $pkg_drop libbox libbar + } + } } : upgrade @@ -3913,6 +4030,19 @@ test.arguments += --sys-no-query configured libbar/0.0.2 EOE + +$pkg_status -ar >>EOO + libfix configured 0.0.1 available 0.0.3 + !libfoo configured !0.0.1 available 1.0.0 + libfix configured 0.0.1 available 0.0.3 + !libbaz configured !0.0.2 available 0.1.0 0.0.4 0.0.3 + !libfoo configured !0.0.1 available 1.0.0 + libfix configured 0.0.1 available 0.0.3 + !libbar configured !0.0.2 available 1.0.0 0.0.3 + !libbaz configured !0.0.2 available 0.1.0 0.0.4 0.0.3 + !libfoo configured !0.0.1 available 1.0.0 + libfix configured 0.0.1 available 0.0.3 + EOO + clone_cfg = [cmdline] cp --no-cleanup -r ../cfg ./ &cfg/*** : immediate diff --git a/tests/pkg-build/t4f b/tests/pkg-build/t4f new file mode 120000 index 0000000..00f2c86 --- /dev/null +++ b/tests/pkg-build/t4f @@ -0,0 +1 @@ +../common/satisfy/t4f \ No newline at end of file -- cgit v1.1