From 03c40ed68ce10b26a5f9f509e914b1b54f060215 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 4 Sep 2021 15:41:41 +0300 Subject: Add --backlink, --dangling, and --recursive options to cfg-info --- bpkg/cfg-info.cli | 33 ++++++++++++++--- bpkg/cfg-info.cxx | 101 +++++++++++++++++++++++++++++++++++++++++++--------- bpkg/cfg-link.cli | 2 +- bpkg/cfg-link.cxx | 2 +- bpkg/cfg-link.hxx | 2 +- bpkg/cfg-unlink.cli | 4 +-- bpkg/cfg-unlink.cxx | 12 +++---- bpkg/database.cxx | 33 ++++++++++------- bpkg/database.hxx | 7 ++++ bpkg/package.hxx | 2 +- 10 files changed, 153 insertions(+), 45 deletions(-) (limited to 'bpkg') diff --git a/bpkg/cfg-info.cli b/bpkg/cfg-info.cli index 8002abd..8801ec9 100644 --- a/bpkg/cfg-info.cli +++ b/bpkg/cfg-info.cli @@ -19,14 +19,22 @@ namespace bpkg \h|DESCRIPTION| The \cb{cfg-info} command prints the current configuration's absolute - path, id, type, and name. If the \cb{--link} option is specified then - this information is also printed for each linked configuration, if any. + path, id, type, and name. If the \cb{--link} and/or \cb{--backlink} + options are specified, then this information is also printed for each + linked and/or implicitly backlinked configuration, if any. Note that the + dangling implicit backlinks are silently skipped, unless \cb{--dangling} + is specified, in which case this information is also printed for them. Note that the information is written to \cb{stdout}, not \cb{stderr}. + If the \cb{--recursive} option is specified together with \cb{--link} + and/or \cb{--backlink}, then this information is printed for linked + and/or implicitly backlinked configuration, recursively. + The output format is regular with each value printed on a separate line - and prefixed with the value name. If the \cb{--link} option is specified - then information blocks corresponding to configurations are separated - with blank lines. For example: + and prefixed with the value name. If the \cb{--link}, \cb{--backlink}, + and/or \cb{--dangling} options are specified, then information blocks + corresponding to linked configurations are separated with blank + lines. For example: \ path: /path/to/cfg/ @@ -55,6 +63,21 @@ namespace bpkg { "Print linked configurations." } + + bool --backlink + { + "Print implicitly backlinked configurations." + } + + bool --dangling + { + "Print dangling implicit backlinks." + } + + bool --recursive + { + "Print linked configurations recursively." + } }; " diff --git a/bpkg/cfg-info.cxx b/bpkg/cfg-info.cxx index da49d62..fc65b7b 100644 --- a/bpkg/cfg-info.cxx +++ b/bpkg/cfg-info.cxx @@ -3,8 +3,11 @@ #include +#include #include // cout +#include +#include #include #include @@ -20,35 +23,101 @@ namespace bpkg dir_path c (o.directory ()); l4 ([&]{trace << "configuration: " << c;}); - database db (c, trace, o.link ()); + if (o.recursive () && !o.link () && !o.backlink ()) + fail << "--recursive requires --link or --backlink"; try { cout.exceptions (ostream::badbit | ostream::failbit); - auto print = [] (const database& db) + // Return false if the configuration information has already been + // printed and print the information and return true otherwise. + // + auto print = [first = true, + printed = set {}] + (const dir_path& path, + const uuid& uid, + const string& type, + const optional& name) mutable { - cout << "path: " << db.config << endl - << "uuid: " << db.uuid << endl - << "type: " << db.type << endl - << "name: " << (db.name ? *db.name : "") << endl; + if (!printed.insert (path).second) + return false; + + if (!first) + cout << endl; + else + first = false; + + cout << "path: " << path << endl + << "uuid: " << uid << endl + << "type: " << type << endl + << "name: " << (name ? *name : "") << endl; + + return true; }; - print (db); + using query = odb::query; - // Note that there will be no explicit links loaded, unless the --link - // option is specified. + query q (false); + + if (o.link ()) + q = q || query::expl; + + if (o.backlink () || o.dangling ()) + q = q || (!query::expl && query::id != 0); + + // Make the output consistent across runs. // - for (const linked_config& lc: db.explicit_links ()) + q = q + "ORDER BY" + query::id; + + auto print_db = [&o, &q, &print] (database& db, + bool links, + const auto& print_db) { - // Skip the self-link. - // - if (lc.id != 0) + if (!print (db.config, db.uuid, db.type, db.name)) + return; + + if (links) { - cout << endl; - print (lc.db); + for (auto& c: db.query (q)) + { + const dir_path& d (c.make_effective_path (db.config)); + + auto print_link = [&o, &db, &c, &print_db] () + { + database& ldb (db.attach (c.path)); + db.verify_link (c, ldb); + + // While at it, also verify the backlink. + // + if (c.expl) + db.backlink (ldb); + + print_db (ldb, o.recursive (), print_db); + }; + + if (c.expl) + { + if (o.link ()) + print_link (); + } + else if (exists (d)) + { + if (o.backlink ()) + print_link (); + } + else if (o.dangling ()) + print (d, c.uuid, c.type, c.name); + } } - } + }; + + database db (c, trace, false /* pre_attach */); + transaction t (db); + + print_db (db, o.link () || o.backlink () || o.dangling (), print_db); + + t.commit (); } catch (const io_error&) { diff --git a/bpkg/cfg-link.cli b/bpkg/cfg-link.cli index 562d4c1..906a4d5 100644 --- a/bpkg/cfg-link.cli +++ b/bpkg/cfg-link.cli @@ -20,7 +20,7 @@ namespace bpkg The \cb{cfg-link} command links the specified \cb{bpkg} configuration with the current configuration. Note that it also establishes an implicit - back-link from the specified to the current configuration. See + backlink from the specified to the current configuration. See \l{bpkg-cfg-create(1)} for background on linked configurations. To unlink previously linked configurations use \l{bpkg-cfg-unlink(1)}. diff --git a/bpkg/cfg-link.cxx b/bpkg/cfg-link.cxx index 5cbeef7..1146d22 100644 --- a/bpkg/cfg-link.cxx +++ b/bpkg/cfg-link.cxx @@ -139,7 +139,7 @@ namespace bpkg // if (lcf != nullptr) { - // Verify the back-link integrity. + // Verify the backlink integrity. // shared_ptr cf ( ldb.query_one (query::uuid == db.uuid.string ())); diff --git a/bpkg/cfg-link.hxx b/bpkg/cfg-link.hxx index 116512b..ee625fa 100644 --- a/bpkg/cfg-link.hxx +++ b/bpkg/cfg-link.hxx @@ -17,7 +17,7 @@ namespace bpkg // Link the configuration specified as the directory path with the current // configuration, attach the linked configuration database, and return the - // link. Note that it also establishes an implicit back-link of the current + // link. Note that it also establishes an implicit backlink of the current // configuration with the linked one. // // The specified configuration path must be absolute and normalized. If the diff --git a/bpkg/cfg-unlink.cli b/bpkg/cfg-unlink.cli index ade3373..6514882 100644 --- a/bpkg/cfg-unlink.cli +++ b/bpkg/cfg-unlink.cli @@ -21,7 +21,7 @@ namespace bpkg The \cb{cfg-unlink} command unlinks the specified \cb{bpkg} configuration from the current configuration (the first form) or removes dangling - implicit back-links (the second form). See \l{bpkg-cfg-create(1)} for + implicit backlinks (the second form). See \l{bpkg-cfg-create(1)} for background on linked configurations. In the first form the configuration to unlink can be specified either as @@ -54,7 +54,7 @@ namespace bpkg bool --dangling { - "Remove dangling implicit back-links." + "Remove dangling implicit backlinks." } }; diff --git a/bpkg/cfg-unlink.cxx b/bpkg/cfg-unlink.cxx index e29d949..52d8969 100644 --- a/bpkg/cfg-unlink.cxx +++ b/bpkg/cfg-unlink.cxx @@ -69,7 +69,7 @@ namespace bpkg // Unlink the configuration in the in-memory model, so we can evaluate // if the dependent configurations are still linked with it. // - // Note that we don't remove the back-link here, since this is not + // Note that we don't remove the backlink here, since this is not // required for the check. // if (!priv) @@ -162,7 +162,7 @@ namespace bpkg // assert (uc != nullptr); - // Implicit back-link. + // Implicit backlink. // shared_ptr cc ( udb.query_one (query::uuid == mdb.uuid.string ())); @@ -172,7 +172,7 @@ namespace bpkg // assert (cc != nullptr); - // If the back-link turns out to be explicit, then, unless the + // If the backlink turns out to be explicit, then, unless the // configuration being unlinked is private, we just turn the explicit // link into an implicit one rather then remove the direct and back // links. @@ -181,7 +181,7 @@ namespace bpkg { info << "configurations " << udb.config_orig << " and " << mdb.config_orig << " are mutually linked, turning the link " - << "to " << udb.config_orig << " into implicit back-link"; + << "to " << udb.config_orig << " into implicit backlink"; uc->expl = false; mdb.update (uc); @@ -237,7 +237,7 @@ namespace bpkg if (!exists (c.effective_path (db.config))) { if (verb > 1) - text << "removing dangling implicit back-link " << c.path; + text << "removing dangling implicit backlink " << c.path; db.erase (c); ++count; @@ -247,7 +247,7 @@ namespace bpkg t.commit (); if (verb && !o.no_result ()) - text << "removed " << count << " dangling implicit back-link(s)"; + text << "removed " << count << " dangling implicit backlink(s)"; return 0; } diff --git a/bpkg/database.cxx b/bpkg/database.cxx index ab2bcfc..451ade3 100644 --- a/bpkg/database.cxx +++ b/bpkg/database.cxx @@ -697,7 +697,7 @@ namespace bpkg if (!lc.expl && !exists (d)) { if (verb > 1) - info << "skipping dangling implicit back-link " << lc.path << + info << "skipping dangling implicit backlink " << lc.path << info << "use 'cfg-unlink --dangling' to clean up"; continue; @@ -714,17 +714,7 @@ namespace bpkg // if (lc.expl) { - shared_ptr cf ( - db.query_one (q::uuid == uuid.string ())); - - if (cf == nullptr) - fail << "configuration " << db.config_orig << " is linked with " - << config_orig << " but latter is not implicitly linked " - << "with former"; - - // While at it, verify the integrity of the other end of the link. - // - db.verify_link (*cf, *this); + shared_ptr cf (backlink (db)); if (!cf->expl) continue; @@ -746,6 +736,25 @@ namespace bpkg return implicit_links_; } + shared_ptr database:: + backlink (database& db) + { + using q = odb::query; + + shared_ptr cf ( + db.query_one (q::uuid == uuid.string ())); + + if (cf == nullptr) + fail << "configuration " << db.config_orig << " is linked with " + << config_orig << " but latter is not implicitly linked " + << "with former"; + + // While at it, verify the integrity of the other end of the link. + // + db.verify_link (*cf, *this); + return cf; + } + linked_databases database:: dependent_configs (bool sys_rep) { diff --git a/bpkg/database.hxx b/bpkg/database.hxx index 40474d3..889f8a0 100644 --- a/bpkg/database.hxx +++ b/bpkg/database.hxx @@ -376,6 +376,13 @@ namespace bpkg void verify_link (const configuration&, database&); + // Assuming that the passed configuration is explicitly linked to the + // current one, return the corresponding backlink. Issue diagnostics and + // fail if the backlink is not found. + // + shared_ptr + backlink (database&); + // Set the specified tracer for the whole linked databases cluster. // using tracer_type = odb::tracer; diff --git a/bpkg/package.hxx b/bpkg/package.hxx index 6256481..13efcd4 100644 --- a/bpkg/package.hxx +++ b/bpkg/package.hxx @@ -160,7 +160,7 @@ namespace bpkg dir_path path; // Empty for the self-link. // True if the link is created explicitly by the user rather than - // automatically as a back-link. + // automatically as a backlink. // bool expl; -- cgit v1.1