diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2023-04-04 08:05:21 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2023-04-04 08:05:21 +0200 |
commit | 7b06ee81ab0e8a2199c4dce07ec67282c4f52f62 (patch) | |
tree | 70d2d0d47a8c572cfe3e56b5f892694fca11ae5a /libbuild2/install/functions.cxx | |
parent | 31b32815407db4263c2aad3c4ca721fd8a9f3c8a (diff) |
Add support for installation filtering (GH issue #147)
Diffstat (limited to 'libbuild2/install/functions.cxx')
-rw-r--r-- | libbuild2/install/functions.cxx | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/libbuild2/install/functions.cxx b/libbuild2/install/functions.cxx index 9f5fa44..d62b578 100644 --- a/libbuild2/install/functions.cxx +++ b/libbuild2/install/functions.cxx @@ -5,6 +5,7 @@ #include <libbuild2/variable.hxx> #include <libbuild2/install/utility.hxx> +#include <libbuild2/install/operation.hxx> namespace build2 { @@ -17,6 +18,8 @@ namespace build2 // $install.resolve(<dir>[, <rel_base>]) // + // @@ TODO: add overload to call resolve_file(). + // // Resolve potentially relative install.* value to an absolute and // normalized directory based on (other) install.* values visible from // the calling scope. @@ -80,6 +83,70 @@ namespace build2 move (dir), rel_base ? move (*rel_base) : dir_path ()); }; + + // @@ TODO: add $install.chroot(). + + // $install.filter(<path>[, <type>]) + // + // Apply filters from config.install.filter and return true if the + // specified filesystem entry should be installed/uninstalled. Note that + // the entry is specified as an absolute and normalized installation + // path (so not $path($>) but $install.resolve($>)). + // + // The type argument can be one of `regular`, `directory`, or `symlink`. + // If unspecified, either `directory` or `regular` is assumed, based on + // whether path is syntactially a directory (ends with a directory + // separator). + // + // Note that this function is not pure and can only be called from a + // install or uninstall operation recipe. + // + f.insert (".filter", false) += [] (const scope* s, + path p, + optional<names> ot) + { + if (s == nullptr) + fail << "install.filter() called out of scope" << endf; + + context& ctx (s->ctx); + + if (ctx.phase != run_phase::match && + ctx.phase != run_phase::execute) + fail << "install.filter() can only be called from recipe"; + + if (ctx.current_inner_oif != &op_install && + ctx.current_inner_oif != &op_uninstall) + fail << "install.filter() can only be called during install/uninstall"; + + entry_type t; + if (ot) + { + string v (convert<string> (move (*ot))); + + if (v == "regular") t = entry_type::regular; + else if (v == "directory") t = entry_type::directory; + else if (v == "symlink") t = entry_type::symlink; + else throw invalid_argument ("unknown type '" + v + '\''); + } + else + t = p.to_directory () ? entry_type::directory : entry_type::regular; + + // Split into directory and leaf. + // + dir_path d; + if (t == entry_type::directory) + { + d = path_cast<dir_path> (move (p)); + p = path (); // No leaf. + } + else + { + d = p.directory (); + p.make_leaf (); + } + + return context_data::filter (*s->root_scope (), d, p, t); + }; } } } |