aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/install/operation.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-04-04 14:10:27 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-04-04 14:10:27 +0200
commit8b9701d2ad76a9a571c445b318557261a4922758 (patch)
tree1de11ba8c7e1d465f4a95005d7115774696a2a87 /libbuild2/install/operation.cxx
parent7b06ee81ab0e8a2199c4dce07ec67282c4f52f62 (diff)
Remove global override restriction from config.install.filter
Diffstat (limited to 'libbuild2/install/operation.cxx')
-rw-r--r--libbuild2/install/operation.cxx285
1 files changed, 6 insertions, 279 deletions
diff --git a/libbuild2/install/operation.cxx b/libbuild2/install/operation.cxx
index 1b63bc0..ce5d24a 100644
--- a/libbuild2/install/operation.cxx
+++ b/libbuild2/install/operation.cxx
@@ -19,255 +19,10 @@ namespace build2
{
namespace install
{
- bool context_data::
- filter (const scope& rs,
- const dir_path& base,
- const path& leaf,
- entry_type type)
- {
- assert (type != entry_type::unknown &&
- (type == entry_type::directory) == leaf.empty ());
-
- context& ctx (rs.ctx);
-
- auto& d (*static_cast<context_data*> (ctx.current_inner_odata.get ()));
-
- if (d.filters == nullptr || d.filters->empty ())
- return true;
-
- tracer trace ("install::context_data::filter");
-
- // Parse, resolve, and apply each filter in order.
- //
- // If redoing all this work for every entry proves too slow, we can
- // consider some form of caching (e.g., on the per-project basis).
- //
- size_t limit (0); // See below.
-
- for (const pair<string, string>& kv: *d.filters)
- {
- path k;
- try
- {
- k = path (kv.first);
-
- if (k.absolute ())
- k.normalize ();
- }
- catch (const invalid_path&)
- {
- fail << "invalid path '" << kv.first << "' in config.install.filter "
- << "value";
- }
-
- bool v;
- {
- const string& s (kv.second);
-
- size_t p (s.find (','));
-
- if (s.compare (0, p, "true") == 0)
- v = true;
- else if (s.compare (0, p, "false") == 0)
- v = false;
- else
- fail << "expected true or false instead of '" << string (s, 0, p)
- << "' in config.install.filter value";
-
- if (p != string::npos)
- {
- if (s.compare (p + 1, string::npos, "symlink") == 0)
- {
- if (type != entry_type::symlink)
- continue;
- }
- else
- fail << "unknown modifier '" << string (s, p + 1) << "' in "
- << "config.install.filter value";
- }
- }
-
- // @@ TODO (see below for all the corner cases). Note that in a sense
- // we already have the match file in any subdirectory support via
- // simple patterns so perhaps this is not worth the trouble. Or we
- // could support some limited form (e.g., `**` should be in the
- // last component). But it may still be tricky to determine if
- // it is a sub-filter.
- //
- if (path_pattern_recursive (k))
- fail << "recursive wildcard pattern '" << kv.first << "' in "
- << "config.install.filter value";
-
- if (k.simple () && !k.to_directory ())
- {
- // Simple name/pattern matched against the leaf.
- //
- // @@ What if it is `**`?
- //
- if (path_pattern (k))
- {
- if (!path_match (leaf, k))
- continue;
- }
- else
- {
- if (k != leaf)
- continue;
- }
- }
- else
- {
- // Split into directory and leaf.
- //
- // @@ What if leaf is `**`?
- //
- dir_path d;
- if (k.to_directory ())
- {
- d = path_cast<dir_path> (move (k));
- k = path (); // No leaf.
- }
- else
- {
- d = k.directory ();
- k.make_leaf ();
- }
-
- // Resolve relative directory.
- //
- // Note that this resolution is potentially project-specific (that
- // is, different projects may have different install.* locaitons).
- //
- // Note that if the first component is/contains a wildcard (e.g.,
- // `*/`), then the resulution will fail, which feels correct (what
- // does */ mean?).
- //
- if (d.relative ())
- {
- // @@ Strictly speaking, this should be base, not root scope.
- //
- d = resolve_dir (rs, move (d));
- }
-
- // Return the number of path components in the path.
- //
- auto path_comp = [] (const path& p)
- {
- size_t n (0);
- for (auto i (p.begin ()); i != p.end (); ++i)
- ++n;
- return n;
- };
-
- // We need the sub() semantics but which uses pattern match instead
- // of equality for the prefix. Looks like chopping off the path and
- // calling path_match() on that is the best we can do.
- //
- // @@ Assumes no `**` components.
- //
- auto path_sub = [&path_comp] (const dir_path& ent,
- const dir_path& pat,
- size_t n = 0)
- {
- if (n == 0)
- n = path_comp (pat);
-
- dir_path p;
- for (auto i (ent.begin ()); n != 0 && i != ent.end (); --n, ++i)
- p.combine (*i, i.separator ());
-
- return path_match (p, pat);
- };
-
- // The following checks should continue on no match and fall through
- // to return.
- //
- if (k.empty ()) // Directory.
- {
- // Directories have special semantics.
- //
- // Consider this sequence of filters:
- //
- // include/x86_64-linux-gnu/@true
- // include/x86_64-linux-gnu/details/@false
- // include/@false
- //
- // It seems the semantics we want is that only subcomponent
- // filters should apply. Maybe remember the latest matched
- // directory as a current limit? But perhaps we don't need to
- // remember the directory itself but the number of path
- // components?
- //
- // I guess for patterns we will use the actual matched directory,
- // not the pattern, to calculate the limit? @@ Because we
- // currently don't support `**`, we for now can count components
- // in the pattern.
-
- // Check if this is a sub-filter.
- //
- size_t n (path_comp (d));
- if (n <= limit)
- continue;
-
- if (path_pattern (d))
- {
- if (!path_sub (base, d, n))
- continue;
- }
- else
- {
- if (!base.sub (d))
- continue;
- }
-
- if (v)
- {
- limit = n;
- continue; // Continue looking for sub-filters.
- }
- }
- else
- {
- if (path_pattern (d))
- {
- if (!path_sub (base, d))
- continue;
- }
- else
- {
- if (!base.sub (d))
- continue;
- }
-
- if (path_pattern (k))
- {
- // @@ Does not handle `**`.
- //
- if (!path_match (leaf, k))
- continue;
- }
- else
- {
- if (k != leaf)
- continue;
- }
- }
- }
-
- l4 ([&]{trace << (base / leaf)
- << (v ? " included by " : " excluded by ")
- << kv.first << '@' << kv.second;});
- return v;
- }
-
- return true;
- }
-
#ifndef BUILD2_BOOTSTRAP
context_data::
- context_data (const install::filters* fs, const path* mf)
- : filters (fs),
- manifest_name (mf),
+ context_data (const path* mf)
+ : manifest_name (mf),
manifest_os (mf != nullptr
? open_file_or_stdout (manifest_name, manifest_ofs)
: manifest_ofs),
@@ -513,8 +268,7 @@ namespace build2
}
#else
context_data::
- context_data (const install::filters* fs, const path*)
- : filters (fs)
+ context_data (const path*)
{
}
@@ -583,14 +337,10 @@ namespace build2
if (inner)
{
- // See if we need to filter and/or write the installation manifest.
+ // See if we need to write the installation manifest.
//
// Note: go straight for the public variable pool.
//
- const filters* fs (
- cast_null<filters> (
- ctx.global_scope[*ctx.var_pool.find ("config.install.filter")]));
-
const path* mf (
cast_null<path> (
ctx.global_scope[*ctx.var_pool.find ("config.install.manifest")]));
@@ -600,30 +350,7 @@ namespace build2
// value of config.install.root.
ctx.current_inner_odata = context::current_data_ptr (
- new context_data (fs, mf),
- [] (void* p) {delete static_cast<context_data*> (p);});
- }
- }
-
- static void
- uninstall_pre (context& ctx,
- const values& params,
- bool inner,
- const location& l)
- {
- // Note: a subset of install_pre().
- //
- if (!params.empty ())
- fail (l) << "unexpected parameters for operation uninstall";
-
- if (inner)
- {
- const filters* fs (
- cast_null<filters> (
- ctx.global_scope[*ctx.var_pool.find ("config.install.filter")]));
-
- ctx.current_inner_odata = context::current_data_ptr (
- new context_data (fs, nullptr),
+ new context_data (mf),
[] (void* p) {delete static_cast<context_data*> (p);});
}
}
@@ -682,7 +409,7 @@ namespace build2
0 /* concurrency */, // Run serially
&pre_uninstall,
nullptr,
- &uninstall_pre,
+ nullptr,
nullptr,
nullptr,
nullptr