From fdfd3e0644095022b61316e220fce3f5a7a1a9ef Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 20 Jun 2023 20:22:29 +0300 Subject: Add --mask-repository-uuid pkg-build option --- bpkg/rep-mask.cxx | 136 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 17 deletions(-) (limited to 'bpkg/rep-mask.cxx') diff --git a/bpkg/rep-mask.cxx b/bpkg/rep-mask.cxx index 79aef42..d7f9c6a 100644 --- a/bpkg/rep-mask.cxx +++ b/bpkg/rep-mask.cxx @@ -26,16 +26,26 @@ namespace bpkg const shared_ptr&, bool mask); - // The idea here is to start the transaction, remove all the specified - // repositories recursively in all the configurations specified by - // repo_configs, collect the remaining repositories and repository fragments - // as unmasked, and rollback the transaction. Later on, the rep_masked*() - // functions will refer to the configuration-specific unmasked repositories - // and repository fragments lists to decide if the repository is masked or - // not in the specific configuration. + // The overall plan is as follows: + // + // - Start the transaction. + // + // - Remove all the specified repositories recursively in all the + // configurations specified by repo_configs (repos) and/or configurations + // specified explicitly via UUIDs (config_uuid_repos). + // + // - Collect the remaining repositories and repository fragments as unmasked. + // + // - Rollback the transaction. + // + // Later on, the rep_masked*() functions will refer to the configuration- + // specific unmasked repositories and repository fragments lists to decide + // if the repository/fragment is masked or not in the specific configuration. // void - rep_mask (const strings& repos) + rep_mask (const strings& repos, + const strings& config_uuid_repos, + linked_databases& current_configs) { tracer trace ("rep_mask"); @@ -55,22 +65,31 @@ namespace bpkg transaction t (mdb); + // Add a repository from a database, suppressing duplicates. + // + auto add_repo = [&rs] (database& db, shared_ptr&& r) + { + if (find_if (rs.begin (), rs.end (), + [&db, &r] (const lazy_weak_ptr& lr) + { + return lr.database () == db && lr.object_id () == r->name; + }) == rs.end ()) + rs.emplace_back (db, move (r)); + }; + + // Collect the repositories masked in all configurations. + // for (database& db: repo_configs) { for (size_t i (0); i != repos.size (); ++i) { // Add a repository, suppressing duplicates, and mark it as found. // - auto add = [&db, &rs, &found_repos, i] (shared_ptr&& r) + auto add = [&db, + &found_repos, i, + &add_repo] (shared_ptr&& r) { - if (find_if (rs.begin (), rs.end (), - [&db, &r] (const lazy_weak_ptr& lr) - { - return lr.database () == db && - lr.object_id () == r->name; - }) == rs.end ()) - rs.emplace_back (db, move (r)); - + add_repo (db, move (r)); found_repos[i] = true; }; @@ -114,6 +133,89 @@ namespace bpkg fail << "repository '" << repos[i] << "' cannot be masked: not found"; } + // Collect the repositories masked in specific configurations. + // + for (const string& cr: config_uuid_repos) + { + auto bad = [&cr] (const string& d) + { + fail << "configuration repository '" << cr << "' cannot be masked: " + << d; + }; + + size_t p (cr.find ('=')); + + if (p == string::npos) + bad ("missing '='"); + + uuid uid; + string uid_str (cr, 0, p); + + try + { + uid = uuid (uid_str); + } + catch (const invalid_argument& e) + { + bad ("invalid configuration uuid '" + uid_str + "': " + e.what ()); + } + + database* db (nullptr); + + for (database& cdb: current_configs) + { + if ((db = cdb.try_find_dependency_config (uid)) != nullptr) + break; + } + + if (db == nullptr) + bad ("no configuration with uuid " + uid.string () + + " is linked with " + + (current_configs.size () == 1 + ? mdb.config_orig.representation () + : "specified current configurations")); + + string rp (cr, p + 1); + + if (repository_name (rp)) + { + if (shared_ptr r = db->find (rp)) + add_repo (*db, move (r)); + else + bad ("repository name '" + rp + "' not found in configuration " + + uid.string ()); + } + else + { + using query = query; + + // Verify that the repository URL is not misspelled or empty. + // + try + { + repository_url u (rp); + assert (!u.empty ()); + } + catch (const invalid_argument& e) + { + bad ("invalid repository location '" + rp + "': " + e.what ()); + } + + bool found (false); + for (shared_ptr r: + pointer_result ( + db->query (query::location.url == rp))) + { + add_repo (*db, move (r)); + found = true; + } + + if (!found) + bad ("repository location '" + rp + "' not found in configuration " + + uid.string ()); + } + } + // First, remove the repository references from the dependent repository // fragments. Note that rep_remove() removes the dangling repositories. // -- cgit v1.1