diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2021-12-01 16:16:17 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2021-12-01 18:21:38 +0300 |
commit | dfb2b32071be8003c9048128cc8cf52bf2137d30 (patch) | |
tree | 7a1d0f21c34b631956e627f3e38ac90d74cbb084 | |
parent | 4f31188d4a7ce3cd9b657cc58e06632b9ccd7d8f (diff) |
Improve pkg-build diagnostics issued when unable to satisfy dependency constraint
-rw-r--r-- | bpkg/pkg-build.cxx | 81 | ||||
-rw-r--r-- | tests/pkg-build.testscript | 9 |
2 files changed, 73 insertions, 17 deletions
diff --git a/bpkg/pkg-build.cxx b/bpkg/pkg-build.cxx index c0374ac..d027866 100644 --- a/bpkg/pkg-build.cxx +++ b/bpkg/pkg-build.cxx @@ -182,9 +182,8 @@ namespace bpkg // Note that we return (loaded) lazy_shared_ptr in order to also convey // the database to which it belongs. // - static - vector<pair<shared_ptr<available_package>, - lazy_shared_ptr<repository_fragment>>> + static vector<pair<shared_ptr<available_package>, + lazy_shared_ptr<repository_fragment>>> find_available (const linked_databases& dbs, const package_name& name, const optional<version_constraint>& c) @@ -232,9 +231,8 @@ namespace bpkg // fragments, their prerequisite repositories, and their complements, // recursively (note: recursivity applies to complements, not prerequisites). // - static - vector<pair<shared_ptr<available_package>, - lazy_shared_ptr<repository_fragment>>> + static vector<pair<shared_ptr<available_package>, + lazy_shared_ptr<repository_fragment>>> find_available (const package_name& name, const optional<version_constraint>& c, const config_repo_fragments& rfs, @@ -268,6 +266,35 @@ namespace bpkg return r; } + // As above but only look for packages from a single repository fragment, + // its prerequisite repositories, and its complements, recursively (note: + // recursivity applies to complements, not prerequisites). Doesn't provide + // the repository fragments the packages come from. + // + // It is assumed that the repository fragment lazy pointer contains the + // database information. + // + static vector<shared_ptr<available_package>> + find_available (const package_name& name, + const optional<version_constraint>& c, + const lazy_shared_ptr<repository_fragment>& rf, + bool prereq = true) + { + vector<shared_ptr<available_package>> r; + + database& db (rf.database ()); + for (auto& ap: filter (rf.load (), query_available (db, name, c), prereq)) + r.emplace_back (move (ap)); + + if (r.empty ()) + { + if (shared_ptr<available_package> ap = find_imaginary_stub (name)) + r.emplace_back (move (ap)); + } + + return r; + } + // As above but only look for a single package from the specified repository // fragment, its prerequisite repositories, and their complements, // recursively (note: recursivity applies to complements, not @@ -1534,17 +1561,45 @@ namespace bpkg } diag_record dr (fail); - dr << "unknown dependency " << dn; - // We need to be careful not to print the wildcard-based - // constraint. + // Issue diagnostics differently based on the presence of + // available packages for the unsatisfied dependency. // - if (d.constraint && (!dep_constr || !wildcard (*dep_constr))) - dr << ' ' << *d.constraint; + // Note that there can't be any stubs, since they satisfy any + // constraint and we won't be here if they were. + // + vector<shared_ptr<available_package>> aps ( + find_available (dn, nullopt /* version_constraint */, af)); + + if (!aps.empty ()) + { + dr << "unable to satisfy dependency constraint (" << dn; - dr << " of package " << name << pdb; + // We need to be careful not to print the wildcard-based + // constraint. + // + if (d.constraint && (!dep_constr || !wildcard (*dep_constr))) + dr << ' ' << *d.constraint; - if (!af->location.empty () && (!dep_constr || system)) + dr << ") of package " << name << pdb << + info << "available " << dn << " versions:"; + + for (const shared_ptr<available_package>& ap: aps) + dr << ' ' << ap->version; + } + else + { + dr << "no package available for dependency " << dn + << " of package " << name << pdb; + } + + // Avoid printing this if the dependent package is external since + // it's more often confusing than helpful (they are normally not + // fetched manually). + // + if (!af->location.empty () && + !af->location.directory_based () && + (!dep_constr || system)) dr << info << "repository " << af->location << " appears to " << "be broken" << info << "or the repository state could be stale" << diff --git a/tests/pkg-build.testscript b/tests/pkg-build.testscript index 48fea7b..058a08b 100644 --- a/tests/pkg-build.testscript +++ b/tests/pkg-build.testscript @@ -431,7 +431,7 @@ test.options += --no-progress : $clone_root_cfg; $* $src/libbar-1.0.0.tar.gz 2>>EOE != 0 - error: unknown dependency libfoo of package libbar + error: no package available for dependency libfoo of package libbar info: while satisfying libbar/1.0.0 EOE @@ -443,7 +443,7 @@ test.options += --no-progress $cfg_create -d cfg2 &cfg2/***; $cfg_link -d cfg cfg2; $* $src/libbar-1.0.0.tar.gz +{ --config-id 1 } 2>>~%EOE% != 0 - %error: unknown dependency libfoo of package libbar \[cfg2.\]% + %error: no package available for dependency libfoo of package libbar \[cfg2.\]% %info: while satisfying libbar/1.0.0 \[cfg2.\]% EOE @@ -1633,7 +1633,7 @@ test.options += --no-progress $rep_fetch; $* libfoo 2>>~%EOE% != 0; - error: unknown dependency libhello >= 1.0 of package libfoo + error: no package available for dependency libhello of package libfoo %.+ EOE @@ -2052,7 +2052,8 @@ test.options += --no-progress $rep_fetch $rep/t0a $rep/t0c; $* libbar/1.0.0 ?libfoo/0.0.1 2>>EOE != 0 - error: unknown dependency libfoo == 0.0.1 of package libbar + error: unable to satisfy dependency constraint (libfoo == 0.0.1) of package libbar + info: available libfoo versions: 1.0.0 info: while satisfying libbar/1.0.0 EOE } |