aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2021-12-01 16:16:17 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2021-12-01 18:21:38 +0300
commitdfb2b32071be8003c9048128cc8cf52bf2137d30 (patch)
tree7a1d0f21c34b631956e627f3e38ac90d74cbb084
parent4f31188d4a7ce3cd9b657cc58e06632b9ccd7d8f (diff)
Improve pkg-build diagnostics issued when unable to satisfy dependency constraint
-rw-r--r--bpkg/pkg-build.cxx81
-rw-r--r--tests/pkg-build.testscript9
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
}