From 4bc9390c48cee736917ead5d20aa216fe10bae47 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 3 Dec 2021 20:30:46 +0300 Subject: Prepare for supporting multiple dependencies in dependency alternative --- libbrep/package.hxx | 56 +++++++++++++++--- libbrep/package.xml | 113 ++++++++++++++++++++++++++++++++++++ load/load.cxx | 74 +++++++++++++++-------- migrate/migrate.cxx | 70 +++++++++++++++++++++- mod/mod-package-version-details.cxx | 32 +++++----- mod/page.cxx | 46 +++++++++------ tests/load/driver.cxx | 38 ++++++------ 7 files changed, 340 insertions(+), 89 deletions(-) diff --git a/libbrep/package.hxx b/libbrep/package.hxx index 0ce8553..1927298 100644 --- a/libbrep/package.hxx +++ b/libbrep/package.hxx @@ -20,7 +20,7 @@ // #define LIBBREP_PACKAGE_SCHEMA_VERSION_BASE 21 -#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 21, closed) +#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 22, closed) namespace brep { @@ -156,7 +156,17 @@ namespace brep operator!= (const dependency&, const dependency&); #pragma db value - class dependency_alternatives: public vector + class dependency_alternative: public small_vector + { + public: + optional enable; + + dependency_alternative () = default; + dependency_alternative (optional e): enable (move (e)) {} + }; + + #pragma db value + class dependency_alternatives: public small_vector { public: bool conditional; @@ -183,7 +193,7 @@ namespace brep test_dependency_type t, bool b, optional c) - : dependency {std::move (n), std::move (c), nullptr /* package */}, + : dependency {move (n), move (c), nullptr /* package */}, type (t), buildtime (b) { @@ -551,20 +561,48 @@ namespace brep // dependencies // - using _dependency_key = odb::nested_key; + // Note that this is a 2-level nested container which is mapped to three + // container tables each containing data of each dimension. + + // Container of the dependency_alternatives values. + // + #pragma db member(dependencies) id_column("") value_column("") + + // Container of the dependency_alternative values. + // + using _dependency_alternative_key = + odb::nested_key; + using _dependency_alternatives_type = - std::map<_dependency_key, dependency>; + std::map<_dependency_alternative_key, dependency_alternative>; - #pragma db value(_dependency_key) - #pragma db member(_dependency_key::outer) column("dependency_index") - #pragma db member(_dependency_key::inner) column("index") + #pragma db value(_dependency_alternative_key) + #pragma db member(_dependency_alternative_key::outer) column("dependency_index") + #pragma db member(_dependency_alternative_key::inner) column("index") - #pragma db member(dependencies) id_column("") value_column("") #pragma db member(dependency_alternatives) \ virtual(_dependency_alternatives_type) \ after(dependencies) \ get(odb::nested_get (this.dependencies)) \ set(odb::nested_set (this.dependencies, std::move (?))) \ + id_column("") key_column("") value_column("") + + // Container of the dependency values. + // + using _dependency_key = odb::nested2_key; + using _dependency_alternative_dependencies_type = + std::map<_dependency_key, dependency>; + + #pragma db value(_dependency_key) + #pragma db member(_dependency_key::outer) column("dependency_index") + #pragma db member(_dependency_key::middle) column("alternative_index") + #pragma db member(_dependency_key::inner) column("index") + + #pragma db member(dependency_alternative_dependencies) \ + virtual(_dependency_alternative_dependencies_type) \ + after(dependency_alternatives) \ + get(odb::nested2_get (this.dependencies)) \ + set(odb::nested2_set (this.dependencies, std::move (?))) \ id_column("") key_column("") value_column("dep_") // requirements diff --git a/libbrep/package.xml b/libbrep/package.xml index 69f5731..9e162ed 100644 --- a/libbrep/package.xml +++ b/libbrep/package.xml @@ -1,4 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/load/load.cxx b/load/load.cxx index 3408284..34e59a7 100644 --- a/load/load.cxx +++ b/load/load.cxx @@ -418,6 +418,8 @@ load_packages (const shared_ptr& rp, } using brep::dependency; + using brep::dependency_alternative; + using brep::dependency_alternatives; for (package_manifest& pm: pms) { @@ -493,31 +495,46 @@ load_packages (const shared_ptr& rp, } } - dependencies ds; + dependencies tds; - for (auto& pda: pm.dependencies) + for (auto& das: pm.dependencies) { // Ignore special build2 and bpkg dependencies. We may not have // packages for them and also showing them for every package is // probably not very helpful. // - if (pda.buildtime && !pda.empty ()) + if (das.buildtime && !das.empty ()) { - const package_name& n (pda.front ().name); + const auto& da (das.front ()); + + assert (da.size () == 1); // @@ DEP + + const package_name& n (da[0].name); if (n == "build2" || n == "bpkg") continue; } - ds.emplace_back (pda.conditional, pda.buildtime, move (pda.comment)); + tds.emplace_back (das.conditional, + das.buildtime, + move (das.comment)); + + dependency_alternatives& tdas (tds.back ()); - for (auto& pd: pda) + for (auto& da: das) { - // The package member will be assigned during dependency - // resolution procedure. - // - ds.back ().push_back (dependency {move (pd.name), - move (pd.constraint), - nullptr /* package */}); + tdas.push_back (dependency_alternative (move (da.enable))); + dependency_alternative& tda (tdas.back ()); + + for (auto& d: da) + { + // The package member will be assigned during dependency + // resolution procedure. + // + tda.push_back ( + dependency {move (d.name), + move (d.constraint), + nullptr /* package */}); + } } } @@ -560,7 +577,7 @@ load_packages (const shared_ptr& rp, move (pm.build_email), move (pm.build_warning_email), move (pm.build_error_email), - move (ds), + move (tds), move (pm.requirements), move (ts), move (pm.builds), @@ -1022,6 +1039,7 @@ static void resolve_dependencies (package& p, database& db, bool ignore_unresolved) { using brep::dependency; + using brep::dependency_alternative; using brep::dependency_alternatives; // Resolve dependencies for internal packages only. @@ -1130,17 +1148,20 @@ resolve_dependencies (package& p, database& db, bool ignore_unresolved) throw failed (); }; - for (dependency_alternatives& da: p.dependencies) + for (dependency_alternatives& das: p.dependencies) { - for (dependency& d: da) + // Practically it is enough to resolve at least one dependency alternative + // to build a package. Meanwhile here we consider an error specifying in + // the manifest file an alternative which can't be resolved, unless + // unresolved dependencies are allowed. + // + for (dependency_alternative& da: das) { - // Practically it is enough to resolve at least one dependency - // alternative to build a package. Meanwhile here we consider an error - // specifying in the manifest file an alternative which can't be - // resolved, unless unresolved dependencies are allowed. - // - if (!resolve (d, false /* test */) && !ignore_unresolved) - bail (d, "dependency"); + for (dependency& d: da) + { + if (!resolve (d, false /* test */) && !ignore_unresolved) + bail (d, "dependency"); + } } } @@ -1204,10 +1225,13 @@ detect_dependency_cycle (const package_id& id, chain.push_back (id); shared_ptr p (db.load (id)); - for (const auto& da: p->dependencies) + for (const auto& das: p->dependencies) { - for (const auto& d: da) - detect_dependency_cycle (d.package.object_id (), chain, db); + for (const auto& da: das) + { + for (const auto& d: da) + detect_dependency_cycle (d.package.object_id (), chain, db); + } } chain.pop_back (); diff --git a/migrate/migrate.cxx b/migrate/migrate.cxx index 6c66bf0..627ee4f 100644 --- a/migrate/migrate.cxx +++ b/migrate/migrate.cxx @@ -208,7 +208,6 @@ create (database& db, bool extra_only) const // Register the data migration functions for the package database schema. // -#if 0 template using package_migration_entry_base = data_migration_entry; @@ -223,8 +222,75 @@ struct package_migration_entry: package_migration_entry_base static const package_migration_entry<22> package_migrate_v22 ([] (database& db) { + // Note that package_dependency_alternative_dependencies.alternative_index + // is copied from package_dependency_alternatives.index and + // package_dependency_alternative_dependencies.index is set to 0. + // + db.execute ( + "INSERT INTO \"package_dependency_alternative_dependencies\" " + "(\"tenant\", " + "\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"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_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_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\", " + "\"dep_package_tenant\", " + "\"dep_package_name\", " + "\"dep_package_version_epoch\", " + "\"dep_package_version_canonical_upstream\", " + "\"dep_package_version_canonical_release\", " + "\"dep_package_version_revision\") " + "SELECT " + "\"tenant\", " + "\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"dependency_index\", " + "\"index\", " + "0, " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"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_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\", " + "\"dep_package_tenant\", " + "\"dep_package_name\", " + "\"dep_package_version_epoch\", " + "\"dep_package_version_canonical_upstream\", " + "\"dep_package_version_canonical_release\", " + "\"dep_package_version_revision\" " + "FROM \"package_dependency_alternatives\""); }); -#endif // Register the data migration functions for the build database schema. // diff --git a/mod/mod-package-version-details.cxx b/mod/mod-package-version-details.cxx index 90c33b1..68d43de 100644 --- a/mod/mod-package-version-details.cxx +++ b/mod/mod-package-version-details.cxx @@ -320,31 +320,33 @@ handle (request& rq, response& rs) << TABLE(CLASS="proplist", ID="depends") << TBODY; - for (const auto& da: ds) + for (const auto& das: ds) { s << TR(CLASS="depends") << TH; - if (da.conditional) + if (das.conditional) s << '?'; - if (da.buildtime) + if (das.buildtime) s << '*'; s << ~TH << TD << SPAN(CLASS="value"); - for (const auto& d: da) + for (const auto& da: das) { - if (&d != &da[0]) + if (&da != &das[0]) s << " | "; - print_dependency (d); + assert (da.size () == 1); // @@ DEP + + print_dependency (da[0]); } s << ~SPAN - << SPAN_COMMENT (da.comment) + << SPAN_COMMENT (das.comment) << ~TD << ~TR; } @@ -360,34 +362,34 @@ handle (request& rq, response& rs) << TABLE(CLASS="proplist", ID="requires") << TBODY; - for (const auto& ra: rm) + for (const auto& ras: rm) { s << TR(CLASS="requires") << TH; - if (ra.conditional) + if (ras.conditional) s << "?"; - if (ra.buildtime) + if (ras.buildtime) s << "*"; - if (ra.conditional || ra.buildtime) + if (ras.conditional || ras.buildtime) s << " "; s << ~TH << TD << SPAN(CLASS="value"); - for (const auto& r: ra) + for (const auto& ra: ras) { - if (&r != &ra[0]) + if (&ra != &ras[0]) s << " | "; - s << r; + s << ra; } s << ~SPAN - << SPAN_COMMENT (ra.comment) + << SPAN_COMMENT (ras.comment) << ~TD << ~TR; } diff --git a/mod/page.cxx b/mod/page.cxx index f2f1843..af9c795 100644 --- a/mod/page.cxx +++ b/mod/page.cxx @@ -416,22 +416,26 @@ namespace brep if (!dependencies_.empty ()) s << "; "; - for (const auto& d: dependencies_) + for (const dependency_alternatives& das: dependencies_) { - if (&d != &dependencies_[0]) + if (&das != &dependencies_[0]) s << ", "; - if (d.conditional) + if (das.conditional) s << "?"; - if (d.buildtime) + if (das.buildtime) s << "*"; // Suppress package name duplicates. // set names; - for (const auto& da: d) - names.emplace (da.name); + for (const dependency_alternative& da: das) + { + assert (da.size () == 1); // @@ DEP + + names.emplace (da[0].name); + } bool mult (names.size () > 1); @@ -439,9 +443,13 @@ namespace brep s << "("; bool first (true); - for (const auto& da: d) + for (const dependency_alternative& da: das) { - const package_name& n (da.name); + assert (da.size () == 1); // @@ DEP + + const dependency& d (da[0]); + + const package_name& n (d.name); if (names.find (n) != names.end ()) { names.erase (n); @@ -454,9 +462,9 @@ namespace brep // Try to display the dependency as a link if it is resolved. // Otherwise display it as plain text. // - if (da.package != nullptr) + if (d.package != nullptr) { - shared_ptr p (da.package.load ()); + shared_ptr p (d.package.load ()); assert (p->internal () || !p->other_repositories.empty ()); shared_ptr r ( @@ -507,23 +515,23 @@ namespace brep << SPAN(CLASS="value") << requirements_.size () << "; "; - for (const auto& r: requirements_) + for (const auto& ras: requirements_) { - if (&r != &requirements_[0]) + if (&ras != &requirements_[0]) s << ", "; - if (r.conditional) + if (ras.conditional) s << "?"; - if (r.buildtime) + if (ras.buildtime) s << "*"; - if (r.empty ()) + if (ras.empty ()) { // If there is no requirement alternatives specified, then print the // comment first word. // - const auto& c (r.comment); + const auto& c (ras.comment); if (!c.empty ()) { auto n (c.find (' ')); @@ -535,14 +543,14 @@ namespace brep } else { - bool mult (r.size () > 1); + bool mult (ras.size () > 1); if (mult) s << "("; - for (const auto& ra: r) + for (const auto& ra: ras) { - if (&ra != &r[0]) + if (&ra != &ras[0]) s << " | "; s << ra; diff --git a/tests/load/driver.cxx b/tests/load/driver.cxx index 51627b7..25403c7 100644 --- a/tests/load/driver.cxx +++ b/tests/load/driver.cxx @@ -270,7 +270,7 @@ test_git_repos (const cstrings& loader_args, assert (p->dependencies.size () == 1); assert (p->dependencies[0].size () == 1); - assert (p->dependencies[0][0] == + assert (p->dependencies[0][0][0] == dep ("libmisc", version_constraint ( dep_ver ("1.0"), false, dep_ver ("1.0"), false))); @@ -466,12 +466,12 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv2->dependencies[0].size () == 1); assert (fpv2->dependencies[1].size () == 1); - assert (fpv2->dependencies[0][0] == + assert (fpv2->dependencies[0][0][0] == dep ("libbar", version_constraint ( nullopt, true, dep_ver ("2.4.0"), false))); - assert (fpv2->dependencies[1][0] == + assert (fpv2->dependencies[1][0][0] == dep ("libexp", version_constraint ( dep_ver ("+2-1.2"), false, dep_ver ("+2-1.2"), false))); @@ -513,27 +513,27 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv2a->dependencies[1].size () == 1); assert (fpv2a->dependencies[2].size () == 2); - assert (fpv2a->dependencies[0][0] == + assert (fpv2a->dependencies[0][0][0] == dep ("libmisc", version_constraint ( dep_ver ("0.1"), false, dep_ver ("2.0.0-"), true))); - assert (fpv2a->dependencies[0][1] == + assert (fpv2a->dependencies[0][1][0] == dep ("libmisc", version_constraint ( dep_ver ("2.0"), false, dep_ver ("5.0"), false))); - assert (fpv2a->dependencies[1][0] == + assert (fpv2a->dependencies[1][0][0] == dep ("libgenx", version_constraint ( dep_ver ("0.2"), true, dep_ver ("3.0"), true))); - assert (fpv2a->dependencies[2][0] == + assert (fpv2a->dependencies[2][0][0] == dep ("libexpat", version_constraint ( nullopt, true, dep_ver ("5.2"), true))); - assert (fpv2a->dependencies[2][1] == + assert (fpv2a->dependencies[2][1][0] == dep ("libexpat", version_constraint ( dep_ver ("1"), true, dep_ver ("5.1"), false))); @@ -573,7 +573,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv3->dependencies.size () == 1); assert (fpv3->dependencies[0].size () == 1); - assert (fpv3->dependencies[0][0] == + assert (fpv3->dependencies[0][0][0] == dep ("libmisc", version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); @@ -612,7 +612,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv4->dependencies.size () == 1); assert (fpv4->dependencies[0].size () == 1); - assert (fpv4->dependencies[0][0] == + assert (fpv4->dependencies[0][0][0] == dep ("libmisc", version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); @@ -696,13 +696,13 @@ test_pkg_repos (const cstrings& loader_args, assert (xpv->dependencies.size () == 2); assert (xpv->dependencies[0].size () == 1); - assert (xpv->dependencies[0][0] == + assert (xpv->dependencies[0][0][0] == dep ("libexpat", version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); assert (xpv->dependencies[1].size () == 1); - assert (xpv->dependencies[1][0] == dep ("libgenx", nullopt)); + assert (xpv->dependencies[1][0][0] == dep ("libgenx", nullopt)); assert (xpv->requirements.empty ()); @@ -783,12 +783,12 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv5->dependencies[0].comment == "Crashes with 1.1.0-2.3.0."); - assert (fpv5->dependencies[0][0] == + assert (fpv5->dependencies[0][0][0] == dep ("libmisc", version_constraint ( nullopt, true, dep_ver ("1.1"), true))); - assert (fpv5->dependencies[0][1] == + assert (fpv5->dependencies[0][1][0] == dep ("libmisc", version_constraint ( dep_ver ("2.3.0+0"), true, nullopt, true))); @@ -796,7 +796,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv5->dependencies[1].size () == 1); assert (fpv5->dependencies[1].comment.empty ()); - assert (fpv5->dependencies[1][0] == + assert (fpv5->dependencies[1][0][0] == dep ("libexp", version_constraint ( dep_ver ("1.0"), false, nullopt, true))); @@ -804,8 +804,8 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv5->dependencies[2].size () == 2); assert (fpv5->dependencies[2].comment == "The newer the better."); - assert (fpv5->dependencies[2][0] == dep ("libstudxml", nullopt)); - assert (fpv5->dependencies[2][1] == dep ("libexpat", nullopt)); + assert (fpv5->dependencies[2][0][0] == dep ("libstudxml", nullopt)); + assert (fpv5->dependencies[2][1][0] == dep ("libexpat", nullopt)); requirements& fpvr5 (fpv5->requirements); assert (fpvr5.size () == 5); @@ -867,10 +867,10 @@ test_pkg_repos (const cstrings& loader_args, assert (epv->dependencies.size () == 2); assert (epv->dependencies[0].size () == 1); - assert (epv->dependencies[0][0] == dep ("libmisc", nullopt)); + assert (epv->dependencies[0][0][0] == dep ("libmisc", nullopt)); assert (epv->dependencies[1].size () == 1); - assert (epv->dependencies[1][0] == + assert (epv->dependencies[1][0][0] == dep ("libpq", version_constraint ( dep_ver ("9.0.0"), false, nullopt, true))); -- cgit v1.1