aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/algorithm.cxx260
-rw-r--r--libbuild2/algorithm.hxx14
2 files changed, 151 insertions, 123 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index b0e8eb0..e15fcbc 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -2324,102 +2324,104 @@ namespace build2
return execute_prerequisites (a, t);
}
- target_state
- perform_clean_extra (action a, const file& ft,
- const clean_extras& extras,
- const clean_adhoc_extras& adhoc_extras)
+ static target_state
+ clean_extra (context& ctx,
+ const path& fp,
+ const clean_extras& es,
+ path& ep, bool& ed)
{
- // Clean the extras first and don't print the commands at verbosity level
- // below 3. Note the first extra file/directory that actually got removed
- // for diagnostics below.
- //
- // Note that dry-run is taken care of by the filesystem functions.
- //
- target_state er (target_state::unchanged);
- bool ed (false);
- path ep;
+ assert (!fp.empty ()); // Must be assigned.
- context& ctx (ft.ctx);
+ target_state er (target_state::unchanged);
- auto clean_extra = [&er, &ed, &ep, &ctx] (const file& f,
- const path* fp,
- const clean_extras& es)
+ for (const char* e: es)
{
- for (const char* e: es)
- {
- size_t n;
- if (e == nullptr || (n = strlen (e)) == 0)
- continue;
+ size_t n;
+ if (e == nullptr || (n = strlen (e)) == 0)
+ continue;
- path p;
- bool d;
+ path p;
+ bool d;
- if (path::traits_type::absolute (e))
- {
- p = path (e);
- d = p.to_directory ();
- }
- else
- {
- if ((d = (e[n - 1] == '/')))
- --n;
+ if (path::traits_type::absolute (e))
+ {
+ p = path (e);
+ d = p.to_directory ();
+ }
+ else
+ {
+ if ((d = (e[n - 1] == '/')))
+ --n;
- if (fp == nullptr)
- {
- fp = &f.path ();
- assert (!fp->empty ()); // Must be assigned.
- }
+ p = fp;
+ for (; *e == '-'; ++e)
+ p = p.base ();
- p = *fp;
- for (; *e == '-'; ++e)
- p = p.base ();
+ p.append (e, n);
+ }
- p.append (e, n);
- }
+ target_state r (target_state::unchanged);
- target_state r (target_state::unchanged);
+ if (d)
+ {
+ dir_path dp (path_cast<dir_path> (p));
- if (d)
+ switch (rmdir_r (ctx, dp, true, 3))
{
- dir_path dp (path_cast<dir_path> (p));
-
- switch (rmdir_r (ctx, dp, true, 3))
+ case rmdir_status::success:
{
- case rmdir_status::success:
- {
- r = target_state::changed;
- break;
- }
- case rmdir_status::not_empty:
- {
- if (verb >= 3)
- text << dp << " is current working directory, not removing";
- break;
- }
- case rmdir_status::not_exist:
+ r = target_state::changed;
break;
}
+ case rmdir_status::not_empty:
+ {
+ if (verb >= 3)
+ text << dp << " is current working directory, not removing";
+ break;
+ }
+ case rmdir_status::not_exist:
+ break;
}
- else
- {
- if (rmfile (ctx, p, 3))
- r = target_state::changed;
- }
-
- if (r == target_state::changed && ep.empty ())
- {
- ed = d;
- ep = move (p);
- }
+ }
+ else
+ {
+ if (rmfile (ctx, p, 3))
+ r = target_state::changed;
+ }
- er |= r;
+ if (r == target_state::changed && ep.empty ())
+ {
+ ed = d;
+ ep = move (p);
}
- };
+
+ er |= r;
+ }
+
+ return er;
+ }
+
+ target_state
+ perform_clean_extra (action a, const file& ft,
+ const clean_extras& extras,
+ const clean_adhoc_extras& adhoc_extras)
+ {
+ context& ctx (ft.ctx);
+
+ // Clean the extras first and don't print the commands at verbosity level
+ // below 3. Note the first extra file/directory that actually got removed
+ // for diagnostics below.
+ //
+ // Note that dry-run is taken care of by the filesystem functions.
+ //
+ target_state er (target_state::unchanged);
+ bool ed (false);
+ path ep;
const path& fp (ft.path ());
if (!fp.empty () && !extras.empty ())
- clean_extra (ft, nullptr, extras);
+ er |= clean_extra (ctx, fp, extras, ep, ed);
target_state tr (target_state::unchanged);
@@ -2454,7 +2456,7 @@ namespace build2
}));
if (i != adhoc_extras.end ())
- clean_extra (*mf, mp, i->extras);
+ er |= clean_extra (ctx, *mp, i->extras, ep, ed);
}
if (!clean)
@@ -2521,29 +2523,19 @@ namespace build2
}
target_state
- perform_clean (action a, const target& t)
+ perform_clean_group_extra (action a, const mtime_target& g,
+ const clean_extras& extras)
{
- const file& f (t.as<file> ());
- assert (!f.path ().empty ());
- return perform_clean_extra (a, f, {});
- }
+ context& ctx (g.ctx);
- target_state
- perform_clean_depdb (action a, const target& t)
- {
- const file& f (t.as<file> ());
- assert (!f.path ().empty ());
- return perform_clean_extra (a, f, {".d"});
- }
+ target_state er (target_state::unchanged);
+ bool ed (false);
+ path ep;
- target_state
- perform_clean_group (action a, const target& xg)
- {
- const mtime_target& g (xg.as<mtime_target> ());
+ if (!extras.empty ())
+ er |= clean_extra (ctx, g.dir / path (g.name), extras, ep, ed);
- // Similar logic to perform_clean_extra() above.
- //
- target_state r (target_state::unchanged);
+ target_state tr (target_state::unchanged);
if (cast_true<bool> (g[g.ctx.var_clean]))
{
@@ -2552,53 +2544,75 @@ namespace build2
if (const target* m = gv.members[gv.count - 1])
{
if (rmfile (m->as<file> ().path (), *m))
- r |= target_state::changed;
+ tr |= target_state::changed;
}
}
}
g.mtime (timestamp_nonexistent);
- r |= reverse_execute_prerequisites (a, g);
- return r;
+ if (tr != target_state::changed && er == target_state::changed)
+ {
+ if (verb > (ctx.current_diag_noise ? 0 : 1) && verb < 3)
+ {
+ if (ed)
+ text << "rm -r " << path_cast<dir_path> (ep);
+ else
+ text << "rm " << ep;
+ }
+ }
+
+ tr |= reverse_execute_prerequisites (a, g);
+
+ tr |= er;
+ return tr;
}
target_state
- perform_clean_group_depdb (action a, const target& g)
+ perform_clean (action a, const target& t)
{
- context& ctx (g.ctx);
+ const file& f (t.as<file> ());
+ assert (!f.path ().empty ());
+ return perform_clean_extra (a, f, {});
+ }
- // The same twisted target state merging logic as in perform_clean_extra().
- //
- target_state er (target_state::unchanged);
- path ep;
+ target_state
+ perform_clean_depdb (action a, const target& t)
+ {
+ const file& f (t.as<file> ());
+ assert (!f.path ().empty ());
+ return perform_clean_extra (a, f, {".d"});
+ }
- group_view gv (g.group_members (a));
- if (gv.count != 0)
+ target_state
+ perform_clean_group (action a, const target& t)
+ {
+ return perform_clean_group_extra (a, t.as<mtime_target> (), {});
+ }
+
+ target_state
+ perform_clean_group_depdb (action a, const target& t)
+ {
+ path d;
+ clean_extras extras;
{
- for (size_t i (0); i != gv.count; ++i)
+ group_view gv (t.group_members (a));
+ if (gv.count != 0)
{
- if (const target* m = gv.members[i])
+ for (size_t i (0); i != gv.count; ++i)
{
- ep = m->as<file> ().path () + ".d";
- break;
+ if (const target* m = gv.members[i])
+ {
+ d = m->as<file> ().path () + ".d";
+ break;
+ }
}
- }
- assert (!ep.empty ());
- if (rmfile (ctx, ep, 3))
- er = target_state::changed;
- }
-
- target_state tr (perform_clean_group (a, g));
-
- if (tr != target_state::changed && er == target_state::changed)
- {
- if (verb > (ctx.current_diag_noise ? 0 : 1) && verb < 3)
- text << "rm " << ep;
+ assert (!d.empty ());
+ extras.push_back (d.string ().c_str ());
+ }
}
- tr |= er;
- return tr;
+ return perform_clean_group_extra (a, t.as<mtime_target> (), extras);
}
}
diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx
index c767f5a..8a6eb65 100644
--- a/libbuild2/algorithm.hxx
+++ b/libbuild2/algorithm.hxx
@@ -840,6 +840,20 @@ namespace build2
return perform_clean_extra (a, f, clean_extras (e));
}
+ // Similar to perform_clean_group() but with extras similar to
+ // perform_clean_extra(). Note that the extras are derived from the group
+ // "path" (g.dir / g.name).
+ //
+ LIBBUILD2_SYMEXPORT target_state
+ perform_clean_group_extra (action, const mtime_target&, const clean_extras&);
+
+ inline target_state
+ perform_clean_group_extra (action a, const mtime_target& g,
+ initializer_list<const char*> e)
+ {
+ return perform_clean_group_extra (a, g, clean_extras (e));
+ }
+
// Update/clean a backlink issuing appropriate diagnostics at appropriate
// levels depending on the overload and the changed argument.
//