aboutsummaryrefslogtreecommitdiff
path: root/bpkg/rep-remove.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/rep-remove.cxx')
-rw-r--r--bpkg/rep-remove.cxx158
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);
+ }
+ }
}