diff options
Diffstat (limited to 'bpkg/rep-remove.cxx')
-rw-r--r-- | bpkg/rep-remove.cxx | 158 |
1 files changed, 104 insertions, 54 deletions
diff --git a/bpkg/rep-remove.cxx b/bpkg/rep-remove.cxx index 26d5725..22702a5 100644 --- a/bpkg/rep-remove.cxx +++ b/bpkg/rep-remove.cxx @@ -143,8 +143,20 @@ namespace bpkg rm_r (td, true /* dir_itself */, 3, rm_error_mode::warn); } + static void + rep_remove_fragment (database&, + transaction&, + const shared_ptr<repository_fragment>&, + bool mask); + + // In the mask repositories mode don't cleanup the repository state in the + // filesystem (see rep-mask.hxx for the details on repository masking). + // void - rep_remove (database& db, transaction& t, const shared_ptr<repository>& r) + rep_remove (database& db, + transaction& t, + const shared_ptr<repository>& r, + bool mask) { assert (!r->name.empty ()); // Can't be the root repository. @@ -164,16 +176,10 @@ namespace bpkg // Remove dangling repository fragments. // for (const repository::fragment_type& fr: r->fragments) - rep_remove_fragment (db, t, fr.fragment.load ()); - - // If there are no repositories stayed in the database then no repository - // fragments should stay either. - // - if (db.query_value<repository_count> () == 0) - assert (db.query_value<repository_fragment_count> () == 0); + rep_remove_fragment (db, t, fr.fragment.load (), mask); - // Cleanup the repository state if present and there are no more - // repositories referring this state. + // Unless in the mask repositories mode, cleanup the repository state if + // present and there are no more repositories referring this state. // // Note that this step is irreversible on failure. If something goes wrong // we will end up with a state-less fetched repository and the @@ -184,44 +190,58 @@ namespace bpkg // then remove them after committing the transaction. Though, we still may // fail in the middle due to the filesystem error. // - dir_path d (repository_state (r->location)); - - if (!d.empty ()) + if (!mask) { - dir_path sd (db.config_orig / repos_dir / d); + dir_path d (repository_state (r->location)); - if (exists (sd)) + if (!d.empty ()) { - // There is no way to get the list of repositories that share this - // state other than traversing all repositories of this type. - // - bool rm (true); - - using query = query<repository>; + dir_path sd (db.config_orig / repos_dir / d); - for (shared_ptr<repository> rp: - pointer_result ( - db.query<repository> ( - query::name != "" && - query::location.type == to_string (r->location.type ())))) + if (exists (sd)) { - if (repository_state (rp->location) == d) + // There is no way to get the list of repositories that share this + // state other than traversing all repositories of this type. + // + bool rm (true); + + using query = query<repository>; + + for (shared_ptr<repository> rp: + pointer_result ( + db.query<repository> ( + query::name != "" && + query::location.type == to_string (r->location.type ())))) { - rm = false; - break; + if (repository_state (rp->location) == d) + { + rm = false; + break; + } } - } - if (rm) - rmdir (db.config_orig, sd); + if (rm) + rmdir (db.config_orig, sd); + } } } } void + rep_remove (database& db, transaction& t, const shared_ptr<repository>& r) + { + rep_remove (db, t, r, false /* mask */); + } + + // In the mask repositories mode don't remove the repository fragment from + // locations of the available packages it contains (see rep-mask.hxx for the + // details on repository masking). + // + static void rep_remove_fragment (database& db, transaction& t, - const shared_ptr<repository_fragment>& rf) + const shared_ptr<repository_fragment>& rf, + bool mask) { tracer trace ("rep_remove_fragment"); @@ -235,39 +255,26 @@ namespace bpkg "fragment=" + query::_val (rf->name)) != 0) return; - // Remove the repository fragment from locations of the available packages - // it contains. Note that this must be done before the repository fragment - // removal. + // Unless in the mask repositories mode, remove the repository fragment + // from locations of the available packages it contains. Note that this + // must be done before the repository fragment removal. // - rep_remove_package_locations (db, t, rf->name); + if (!mask) + rep_remove_package_locations (db, t, rf->name); // Remove the repository fragment. // db.erase (rf); - // If there are no repository fragments stayed in the database then no - // repositories nor packages should stay either. - // - // Note that a repository is removed prior to the removal of fragments it - // contains (see rep_remove()). Also note that the packages contained in a - // repository fragment are removed, if this is the only containing - // fragment, prior to the fragment removal (see above). - // - if (db.query_value<repository_fragment_count> () == 0) - { - assert (db.query_value<repository_count> () == 0); - assert (db.query_value<available_package_count> () == 0); - } - // Remove dangling complements and prerequisites. // // Prior to removing a prerequisite/complement we need to make sure it // still exists, which may not be the case due to the dependency cycle. // - auto remove = [&db, &t] (const lazy_weak_ptr<repository>& rp) + auto remove = [&db, &t, mask] (const lazy_weak_ptr<repository>& rp) { if (shared_ptr<repository> r = db.find<repository> (rp.object_id ())) - rep_remove (db, t, r); + rep_remove (db, t, r, mask); }; for (const lazy_weak_ptr<repository>& cr: rf->complements) @@ -284,6 +291,14 @@ namespace bpkg } void + rep_remove_fragment (database& db, + transaction& t, + const shared_ptr<repository_fragment>& rf) + { + return rep_remove_fragment (db, t, rf, false /* mask */); + } + + void rep_remove_clean (const common_options& o, database& db, bool quiet) { tracer trace ("rep_remove_clean"); @@ -336,7 +351,7 @@ namespace bpkg try { - for (const dir_entry& de: dir_iterator (rd, false /* ignore_dangling */)) + for (const dir_entry& de: dir_iterator (rd, dir_iterator::no_follow)) { if (de.ltype () == entry_type::directory) rmdir (db.config_orig, rd / path_cast<dir_path> (de.path ())); @@ -486,6 +501,10 @@ namespace bpkg text << "removed " << r.object_id (); } +#ifndef NDEBUG + rep_remove_verify (db, t); +#endif + // If the --all option is specified then no user-added repositories should // remain. // @@ -503,4 +522,35 @@ namespace bpkg return 0; } + + void + rep_remove_verify (database& db, transaction&, bool verify_packages) + { + size_t rn (db.query_value<repository_count> ()); + size_t fn (db.query_value<repository_fragment_count> ()); + + // If there are no repositories stayed in the database then no repository + // fragments should stay either. + // + assert (rn != 0 || fn == 0); + + // If there are no repository fragments stayed in the database then no + // repositories with fragments nor packages should stay either. + // + // Note that repositories may not have any fragments if they are not + // fetched yet or due to the refname exclusions in the repository URL + // fragments (see repository-types(1) for details). + // + if (fn == 0) + { + // If there are some repositories have stayed, then make sure that none + // of them have any fragments. + // + assert (rn == 0 || + db.query_value<fragment_repository_count> ("repository!=''") == 0); + + if (verify_packages) + assert (db.query_value<available_package_count> () == 0); + } + } } |