diff options
Diffstat (limited to 'bpkg/package-skeleton.cxx')
-rw-r--r-- | bpkg/package-skeleton.cxx | 455 |
1 files changed, 321 insertions, 134 deletions
diff --git a/bpkg/package-skeleton.cxx b/bpkg/package-skeleton.cxx index fee4bbc..78635e7 100644 --- a/bpkg/package-skeleton.cxx +++ b/bpkg/package-skeleton.cxx @@ -16,12 +16,14 @@ #include <libbuild2/context.hxx> #include <libbuild2/variable.hxx> #include <libbuild2/operation.hxx> +#include <libbuild2/diagnostics.hxx> #include <libbuild2/lexer.hxx> #include <libbuild2/parser.hxx> #include <libbuild2/config/utility.hxx> +#include <bpkg/bpkg.hxx> #include <bpkg/package.hxx> #include <bpkg/database.hxx> #include <bpkg/manifest-utility.hxx> @@ -31,19 +33,6 @@ using namespace butl; namespace bpkg { - // These are defined in bpkg.cxx and initialized in main(). - // - extern strings build2_cmd_vars; - extern build2::scheduler build2_sched; - extern build2::global_mutexes build2_mutexes; - extern build2::file_cache build2_fcache; - - void - build2_init (const common_options&); -} - -namespace bpkg -{ // Check whether the specified configuration variable override has a project // variable (i.e., its name starts with config.<project>). If the last // argument is not NULL, then set it to the length of the variable portion. @@ -152,7 +141,7 @@ namespace bpkg // (build2 stuff is only forward-declared in the header). // static build2::scope_map::iterator - bootstrap (package_skeleton&, const strings&); + bootstrap (package_skeleton&, const strings&, bool old = false); package_skeleton:: ~package_skeleton () @@ -160,18 +149,23 @@ namespace bpkg } package_skeleton:: - package_skeleton (package_skeleton&& v) + package_skeleton (package_skeleton&& v) noexcept : package (move (v.package)), system (v.system), available (move (v.available)), + load_config_flags (v.load_config_flags), co_ (v.co_), db_ (v.db_), var_prefix_ (move (v.var_prefix_)), config_vars_ (move (v.config_vars_)), + config_var_srcs_ (move (v.config_var_srcs_)), disfigure_ (v.disfigure_), config_srcs_ (v.config_srcs_), src_root_ (move (v.src_root_)), out_root_ (move (v.out_root_)), + src_root_specified_ (v.src_root_specified_), + old_src_root_ (move (v.old_src_root_)), + old_out_root_ (move (v.old_out_root_)), created_ (v.created_), verified_ (v.verified_), loaded_old_config_ (v.loaded_old_config_), @@ -194,21 +188,26 @@ namespace bpkg } package_skeleton& package_skeleton:: - operator= (package_skeleton&& v) + operator= (package_skeleton&& v) noexcept { if (this != &v) { package = move (v.package); system = v.system; available = move (v.available); + load_config_flags = v.load_config_flags; co_ = v.co_; db_ = v.db_; var_prefix_ = move (v.var_prefix_); config_vars_ = move (v.config_vars_); + config_var_srcs_ = move (v.config_var_srcs_); disfigure_ = v.disfigure_; config_srcs_ = v.config_srcs_; src_root_ = move (v.src_root_); out_root_ = move (v.out_root_); + src_root_specified_ = v.src_root_specified_; + old_src_root_ = move (v.old_src_root_); + old_out_root_ = move (v.old_out_root_); created_ = v.created_; verified_ = v.verified_; loaded_old_config_ = v.loaded_old_config_; @@ -238,14 +237,19 @@ namespace bpkg : package (v.package), system (v.system), available (v.available), + load_config_flags (v.load_config_flags), co_ (v.co_), db_ (v.db_), var_prefix_ (v.var_prefix_), config_vars_ (v.config_vars_), + config_var_srcs_ (v.config_var_srcs_), disfigure_ (v.disfigure_), config_srcs_ (v.config_srcs_), src_root_ (v.src_root_), out_root_ (v.out_root_), + src_root_specified_ (v.src_root_specified_), + old_src_root_ (v.old_src_root_), + old_out_root_ (v.old_out_root_), created_ (v.created_), verified_ (v.verified_), loaded_old_config_ (v.loaded_old_config_), @@ -307,10 +311,14 @@ namespace bpkg bool df, const vector<config_variable>* css, optional<dir_path> src_root, - optional<dir_path> out_root) + optional<dir_path> out_root, + optional<dir_path> old_src_root, + optional<dir_path> old_out_root, + uint16_t lcf) : package (move (pk)), system (sys), available (move (ap)), + load_config_flags (lcf), co_ (&co), db_ (&package.db.get ()), var_prefix_ ("config." + package.name.variable ()), @@ -323,14 +331,21 @@ namespace bpkg else assert (system); + if (!config_vars_.empty ()) + config_var_srcs_ = vector<config_source> (config_vars_.size (), + config_source::user); + // We are only interested in old user configuration variables. // if (config_srcs_ != nullptr) { if (find_if (config_srcs_->begin (), config_srcs_->end (), - [] (const config_variable& v) + [this] (const config_variable& v) { - return v.source == config_source::user; + return ((load_config_flags & load_config_user) != 0 && + v.source == config_source::user) || + ((load_config_flags & load_config_dependent) != 0 && + v.source == config_source::dependent); }) == config_srcs_->end ()) config_srcs_ = nullptr; } @@ -352,8 +367,8 @@ namespace bpkg { // For now tighten it even further so that we can continue // using repositories without package skeleton information - // (bootstrap.build, root.build). See load_old_config() for - // details. + // (bootstrap.build, root.build). See + // load_old_config_impl() for details. // #if 0 return project_override (v, var_prefix_); @@ -369,11 +384,27 @@ namespace bpkg { src_root_ = move (*src_root); + assert (!src_root_.empty ()); // Must exist. + + src_root_specified_ = true; + if (out_root) out_root_ = move (*out_root); } else assert (!out_root); + + if (old_src_root) + { + old_src_root_ = move (*old_src_root); + + assert (!old_src_root_.empty ()); // Must exist. + + if (old_out_root) + old_out_root_ = move (*old_out_root); + } + else + assert (!old_out_root); } // Serialize a variable assignment for a command line override. @@ -391,7 +422,7 @@ namespace bpkg else { storage.clear (); - names_view nv (reverse (val, storage)); + names_view nv (reverse (val, storage, true /* reduce */)); if (!nv.empty ()) { @@ -406,7 +437,8 @@ namespace bpkg return r; } - // Reverse value to names. + // Reverse value to names reducing empty simple value to empty list of + // names. // static optional<build2::names> reverse_value (const build2::value& val) @@ -417,7 +449,7 @@ namespace bpkg return nullopt; names storage; - names_view nv (reverse (val, storage)); + names_view nv (reverse (val, storage, true /* reduce */)); return (nv.data () == storage.data () ? move (storage) @@ -462,11 +494,12 @@ namespace bpkg ctx_ == nullptr); if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); try { using namespace build2; + using build2::info; // This is what needs to happen to the variables of different origins in // the passed configuration: @@ -486,13 +519,22 @@ namespace bpkg // construction (in evaluate_{prefer_accept,require}()): we do not add // as dependent variables that have the override origin. // - scope& rs ( - *bootstrap ( - *this, merge_cmd_vars (dependent_cmd_vars (cfg)))->second.front ()); + scope* rs; + { + auto df = build2::make_diag_frame ( + [this] (const build2::diag_record& dr) + { + dr << info << "while loading build system skeleton of package " + << package.name; + }); - // Load project's root.build. - // - load_root (rs); + rs = bootstrap ( + *this, merge_cmd_vars (dependent_cmd_vars (cfg)))->second.front (); + + // Load project's root.build. + // + load_root (*rs); + } package_configuration old (move (cfg)); cfg.package = move (old.package); @@ -515,14 +557,16 @@ namespace bpkg // variable), then the saved variables map seem like the natural place // to keep this information. // - for (const variable& var: rs.ctx.var_pool) + // Note: go straight for the public variable pool. + // + for (const variable& var: rs->ctx.var_pool) { if (!project_variable (var.name, var_prefix_)) continue; using config::variable_origin; - pair<variable_origin, lookup> ol (config::origin (rs, var)); + pair<variable_origin, lookup> ol (config::origin (*rs, var)); switch (ol.first) { @@ -616,8 +660,10 @@ namespace bpkg create_context (*this, strings {}); context& ctx (*ctx_); + // Note: go straight for the public variable pool. + // scope& gs (ctx.global_scope.rw ()); - auto& vp (ctx.var_pool.rw ()); + auto& vp (gs.var_pool (true /* public */)); for (const string& v: config_vars_) { @@ -690,11 +736,12 @@ namespace bpkg ctx_ == nullptr); if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); try { using namespace build2; + using build2::info; // For now we treat any failure to load root.build as bad configuration, // which is not very precise. One idea to make this more precise would @@ -702,15 +749,23 @@ namespace bpkg // (e.g., either via an attribute or via special config.assert directive // or some such). // - // For now we rely on load_defaults() and load_old_config() to "flush" - // out any unrelated errors (e.g., one of the modules configuration is - // bad, etc). However, if that did not happen naturally, then we must do - // it ourselves. + // For now we rely on load_defaults() and load_old_config_impl() to + // "flush" out any unrelated errors (e.g., one of the modules + // configuration is bad, etc). However, if that did not happen + // naturally, then we must do it ourselves. // if (!verified_) { + auto df = build2::make_diag_frame ( + [this] (const build2::diag_record& dr) + { + dr << info << "while loading build system skeleton of package " + << package.name; + }); + scope& rs ( *bootstrap (*this, merge_cmd_vars (strings {}))->second.front ()); + load_root (rs); verified_ = true; @@ -723,6 +778,8 @@ namespace bpkg // Load project's root.build while redirecting the diagnostics stream. // + // Note: no diag_frame unlike all the other places. + // ostringstream ds; auto dg (make_guard ([ods = diag_stream] () {diag_stream = ods;})); diag_stream = &ds; @@ -758,10 +815,12 @@ namespace bpkg // Print the location of a depends value in the specified manifest file. // - // Note that currently we only use this function for the external packages. - // We could also do something similar for normal packages by pointing to the - // manifest we have serialized. In this case we would also need to make sure - // the temp directory is not cleaned in case of an error. Maybe one day. + // Note that currently we only use this function for the being reconfigured + // and external packages (i.e. when the existing source directory is + // specified). We could also do something similar for the remaining cases by + // pointing to the manifest we have serialized. In this case we would also + // need to make sure the temp directory is not cleaned in case of an error. + // Maybe one day. // static void depends_location (const build2::diag_record& dr, @@ -834,20 +893,19 @@ namespace bpkg uint64_t il (1); auto df = build2::make_diag_frame ( - [this, &cond, &rs, depends_index] (const build2::diag_record& dr) + [this, &cond, depends_index] (const build2::diag_record& dr) { dr << info << "enable condition: (" << cond << ")"; - // For external packages we have the manifest so print the location - // of the depends value in questions. + // If an existing source directory has been specified, then we have + // the manifest and so print the location of the depends value in + // questions. // - if (rs.out_eq_src ()) + if (src_root_specified_) + depends_location (dr, src_root_ / manifest_file, depends_index); + else dr << info << "in depends manifest value of package " << package.name; - else - depends_location (dr, - rs.src_path () / manifest_file, - depends_index); }); lexer l (is, in, il /* start line */); @@ -903,9 +961,9 @@ namespace bpkg // values that are derived from them in root.build). It seems like we have // two options here: either enter them as true overrides similar to // config_vars_ or just evaluate them similar to loading config.build - // (which, BTW, we might have, in case of an external package). The big - // problem with the former approach is that it will then prevent any - // further reflect clauses from modifying the same values. + // (which, BTW, we might have, in case of a being reconfigured or external + // package). The big problem with the former approach is that it will then + // prevent any further reflect clauses from modifying the same values. // // So overall it feels like we have iterative/compartmentalized // configuration process. A feedback loop, in a sense. And it's the @@ -1031,7 +1089,7 @@ namespace bpkg // Note: keep it active until the end (see the override detection). // auto df = build2::make_diag_frame ( - [this, &refl, &rs, depends_index] (const build2::diag_record& dr) + [this, &refl, depends_index] (const build2::diag_record& dr) { // Probably safe to assume a one-line fragment contains a variable // assignment. @@ -1042,16 +1100,15 @@ namespace bpkg dr << info << "reflect clause:\n" << trim_right (string (refl)); - // For external packages we have the manifest so print the - // location of the depends value in questions. + // If an existing source directory has been specified, then we have + // the manifest and so print the location of the depends value in + // questions. // - if (rs.out_eq_src ()) + if (src_root_specified_) + depends_location (dr, src_root_ / manifest_file, depends_index); + else dr << info << "in depends manifest value of package " << package.name; - else - depends_location (dr, - rs.src_path () / manifest_file, - depends_index); }); lexer l (is, in, il /* start line */); @@ -1065,10 +1122,11 @@ namespace bpkg // Add to the vars set the reflect variables collected previously. // - auto& vp (rs.var_pool ()); for (const reflect_variable_value& v: reflect_) { - const variable* var (vp.find (v.name)); + // Note: go straight for the public variable pool. + // + const variable* var (rs.ctx.var_pool.find (v.name)); assert (var != nullptr); // Must be there (set by load()). auto p (vars.insert (rvar {var, nullptr, 0})); @@ -1248,21 +1306,20 @@ namespace bpkg uint64_t il (1); auto df = build2::make_diag_frame ( - [this, &prefer, &rs, depends_index] (const build2::diag_record& dr) + [this, &prefer, depends_index] (const build2::diag_record& dr) { dr << info << "prefer clause:\n" << trim_right (string (prefer)); - // For external packages we have the manifest so print the - // location of the depends value in questions. + // If an existing source directory has been specified, then we + // have the manifest and so print the location of the depends + // value in questions. // - if (rs.out_eq_src ()) + if (src_root_specified_) + depends_location (dr, src_root_ / manifest_file, depends_index); + else dr << info << "in depends manifest value of package " << package.name; - else - depends_location (dr, - rs.src_path () / manifest_file, - depends_index); }); lexer l (is, in, il /* start line */); @@ -1310,20 +1367,19 @@ namespace bpkg uint64_t il (1); auto df = build2::make_diag_frame ( - [this, &accept, &rs, depends_index] (const build2::diag_record& dr) + [this, &accept, depends_index] (const build2::diag_record& dr) { dr << info << "accept condition: (" << accept << ")"; - // For external packages we have the manifest so print the - // location of the depends value in questions. + // If an existing source directory has been specified, then we + // have the manifest and so print the location of the depends + // value in questions. // - if (rs.out_eq_src ()) + if (src_root_specified_) + depends_location (dr, src_root_ / manifest_file, depends_index); + else dr << info << "in depends manifest value of package " << package.name; - else - depends_location (dr, - rs.src_path () / manifest_file, - depends_index); }); lexer l (is, in, il /* start line */); @@ -1543,21 +1599,20 @@ namespace bpkg uint64_t il (1); auto df = build2::make_diag_frame ( - [this, &require, &rs, depends_index] (const build2::diag_record& dr) + [this, &require, depends_index] (const build2::diag_record& dr) { dr << info << "require clause:\n" << trim_right (string (require)); - // For external packages we have the manifest so print the - // location of the depends value in questions. + // If an existing source directory has been specified, then we + // have the manifest and so print the location of the depends + // value in questions. // - if (rs.out_eq_src ()) + if (src_root_specified_) + depends_location (dr, src_root_ / manifest_file, depends_index); + else dr << info << "in depends manifest value of package " << package.name; - else - depends_location (dr, - rs.src_path () / manifest_file, - depends_index); }); lexer l (is, in, il /* start line */); @@ -1824,7 +1879,7 @@ namespace bpkg empty_print () { if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); return (dependent_vars_.empty () && reflect_.empty () && @@ -1855,7 +1910,7 @@ namespace bpkg using build2::config::variable_origin; if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); auto print = [&os, indent, @@ -1880,8 +1935,10 @@ namespace bpkg // First comes the user configuration. // - for (const string& v: config_vars_) + for (size_t i (0); i != config_vars_.size (); ++i) { + const string& v (config_vars_[i]); + size_t vn; if (project_override (v, var_prefix_, &vn)) { @@ -1895,8 +1952,17 @@ namespace bpkg continue; } + const char* s (nullptr); + + switch (config_var_srcs_[i]) + { + case config_source::user: s = "user"; break; + case config_source::dependent: s = "dependent"; break; + case config_source::reflect: assert (false); // Must never be loaded. + } + print (v) << " (" << (system ? "expected " : "") - << "user configuration)"; + << s << " configuration)"; } } @@ -1924,15 +1990,24 @@ namespace bpkg } } + void package_skeleton:: + load_old_config () + { + if (!loaded_old_config_) + load_old_config_impl (); + } + pair<strings, vector<config_variable>> package_skeleton:: collect_config () && { + // NOTE: remember to update config_checksum() if changing anything here. + assert (db_ != nullptr); // Must be called only once. using build2::config::variable_origin; if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); // Merge all the variables into a single list in the correct order // and assign their sources while at it. @@ -1969,11 +2044,19 @@ namespace bpkg // variables which are project variables (i.e., names start with // config.<project>). // + size_t pn (var_prefix_.size ()); for (const string& v: config_vars_) { - if (project_override (v, var_prefix_)) + size_t vn; + if (project_override (v, var_prefix_, &vn)) { - string n (var_name (v)); + // Skip config.<project>.develop (can potentially be passed by + // bdep-init) if the package doesn't use it. + // + if (!develop_ && v.compare (pn, vn - pn, ".develop") == 0) + continue; + + string n (v, 0, vn); // Check for a duplicate. // @@ -2039,13 +2122,61 @@ namespace bpkg return make_pair (move (vars), move (srcs)); } + string package_skeleton:: + config_checksum () + { + // Note: this is parallel to collect_config() logic but is not destructive. + + assert (db_ != nullptr); // Must be called before collect_config(). + + if (!loaded_old_config_) + load_old_config_impl (); + + sha256 cs; + + if (!config_vars_.empty ()) + { + cstrings vs; + size_t pn (var_prefix_.size ()); + for (const string& v: config_vars_) + { + size_t vn; + if (project_override (v, var_prefix_, &vn)) + { + // Skip config.<project>.develop (can potentially be passed by + // bdep-init) if the package doesn't use it. + // + if (develop_ || v.compare (pn, vn - pn, ".develop") != 0) + cs.append (v); + } + } + } + + if (!dependent_vars_.empty ()) + { + for (const string& v: dependent_vars_) + cs.append (v); + } + + if (!reflect_.empty ()) + { + for (const reflect_variable_value& v: reflect_) + { + if (v.origin != build2::config::variable_origin::override_) + cs.append (serialize_cmdline (v.name, v.value)); + } + } + + return !cs.empty () ? cs.string () : string (); + } + const strings& package_skeleton:: merge_cmd_vars (const strings& dependent_vars, const strings& dependency_vars, bool cache) { // Merge variable overrides (note that the order is important). See also a - // custom/optimized version in load_old_config(). + // custom/optimized version in load_old_config_impl(). // if (!cache || !cmd_vars_cache_) { @@ -2093,13 +2224,14 @@ namespace bpkg } void package_skeleton:: - load_old_config () + load_old_config_impl () { assert (!loaded_old_config_ && ctx_ == nullptr); try { using namespace build2; + using build2::info; // This load that must be done without config.config.disfigure. Also, it // would be nice to optimize for the common case where the only load is @@ -2136,13 +2268,25 @@ namespace bpkg } } - scope& rs (*bootstrap (*this, *cmd_vars)->second.front ()); + scope* rs; + { + auto df = build2::make_diag_frame ( + [this] (const build2::diag_record& dr) + { + dr << info << "while loading build system skeleton of package " + << package.name; + }); - // Load project's root.build. - // - load_root (rs); + rs = bootstrap (*this, *cmd_vars, true /* old */)->second.front (); - if (const variable* var = rs.var_pool ().find (var_prefix_ + ".develop")) + // Load project's root.build. + // + load_root (*rs); + } + + // Note: go straight for the public variable pool. + // + if (const variable* var = rs->ctx.var_pool.find (var_prefix_ + ".develop")) { // Use the fact that the variable is typed as a proxy for it being // defined with config directive (the more accurate way would be via @@ -2156,27 +2300,32 @@ namespace bpkg // // Also, build2 warns about unused variables being dropped. // - // Note that currently load_old_config() is disabled unless there is - // a config.*.develop variable; see package_skeleton ctor. + // Note that currently load_old_config_impl() is disabled unless + // there is a config.*.develop variable or we were asked to load + // dependent configuration; see package_skeleton ctor. - // Extract and merge old user configuration variables from config.build - // (or equivalent) into config_vars. + // Extract and merge old user and/or dependent configuration variables + // from config.build (or equivalent) into config_vars. // if (config_srcs_ != nullptr) { assert (!disfigure_); - auto i (config_vars_.begin ()); // Insert position, see below. + auto i (config_vars_.begin ()); // Insert position, see below. + auto j (config_var_srcs_.begin ()); // Insert position, see below. names storage; for (const config_variable& v: *config_srcs_) { - if (v.source != config_source::user) + if (!(((load_config_flags & load_config_user) != 0 && + v.source == config_source::user) || + ((load_config_flags & load_config_dependent) != 0 && + v.source == config_source::dependent))) continue; using config::variable_origin; - pair<variable_origin, lookup> ol (config::origin (rs, v.name)); + pair<variable_origin, lookup> ol (config::origin (*rs, v.name)); switch (ol.first) { @@ -2201,6 +2350,7 @@ namespace bpkg i, serialize_cmdline (v.name, *ol.second, storage)) + 1; + j = config_var_srcs_.insert (j, v.source) + 1; break; } case variable_origin::undefined: @@ -2219,7 +2369,10 @@ namespace bpkg } loaded_old_config_ = true; - verified_ = true; // Managed to load without errors. + + if (old_src_root_.empty ()) + verified_ = true; // Managed to load without errors. + ctx_ = nullptr; } catch (const build2::failed&) @@ -2242,11 +2395,12 @@ namespace bpkg } if (!loaded_old_config_) - load_old_config (); + load_old_config_impl (); try { using namespace build2; + using build2::info; using build2::config::variable_origin; // If we have any dependency configurations, then here we need to add @@ -2283,6 +2437,13 @@ namespace bpkg dependency_vars, dependency_vars.empty () /* cache */)); + auto df = build2::make_diag_frame ( + [this] (const build2::diag_record& dr) + { + dr << info << "while loading build system skeleton of package " + << package.name; + }); + auto rsi (bootstrap (*this, cmd_vars)); scope& rs (*rsi->second.front ()); @@ -2329,7 +2490,9 @@ namespace bpkg assert (vt != nullptr); } - return rs.var_pool ().insert (name, vt); + // Note: go straight for the public variable pool. + // + return rs.var_pool (true /* public */).insert (name, vt); }; for (const reflect_variable_value& v: reflect_) @@ -2436,10 +2599,11 @@ namespace bpkg new context (build2_sched, build2_mutexes, build2_fcache, - false /* match_only */, // Shouldn't matter. - false /* no_external_modules */, - false /* dry_run */, // Shouldn't matter. - false /* keep_going */, // Shouldnt' matter. + nullopt /* match_only */, // Shouldn't matter. + false /* no_external_modules */, + false /* dry_run */, // Shouldn't matter. + false /* no_diag_buffer */, // Shouldn't matter. + false /* keep_going */, // Shouldnt' matter. cmd_vars)); } catch (const build2::failed&) @@ -2451,7 +2615,7 @@ namespace bpkg // Bootstrap the package skeleton. // static build2::scope_map::iterator - bootstrap (package_skeleton& skl, const strings& cmd_vars) + bootstrap (package_skeleton& skl, const strings& cmd_vars, bool old) { assert (skl.db_ != nullptr && skl.ctx_ == nullptr && @@ -2473,6 +2637,12 @@ namespace bpkg // Create the skeleton filesystem state, if it doesn't exist yet. // + if (old && skl.old_src_root_.empty ()) + old = false; + + dir_path& skl_src_root (old ? skl.old_src_root_ : skl.src_root_); + dir_path& skl_out_root (old ? skl.old_out_root_ : skl.out_root_); + if (!skl.created_) { const available_package& ap (*skl.available); @@ -2482,14 +2652,28 @@ namespace bpkg // they never clash with other temporary subdirectories (git // repositories, etc). // - if (skl.src_root_.empty () || skl.out_root_.empty ()) + // Note: for old src/out, everything should already exist. + // + if (!old && (skl_src_root.empty () || skl_out_root.empty ())) { // Cannot be specified if src_root_ is unspecified. // - assert (skl.out_root_.empty ()); + assert (skl_out_root.empty ()); + + // Note that only configurations which can be used as repository + // information sources has the temporary directory facility + // pre-initialized (see pkg-build.cxx for details). Thus, we may need + // to initialize it ourselves. + // + const dir_path& c (skl.db_->config_orig); + auto i (tmp_dirs.find (c)); - auto i (tmp_dirs.find (skl.db_->config_orig)); - assert (i != tmp_dirs.end ()); + if (i == tmp_dirs.end ()) + { + init_tmp (c); + + i = tmp_dirs.find (c); + } // Make sure the source and out root directories, if set, are absolute // and normalized. @@ -2502,14 +2686,16 @@ namespace bpkg d /= "skeletons"; d /= skl.package.name.string () + '-' + ap.version.string (); - if (skl.src_root_.empty ()) - skl.src_root_ = move (d); // out_root_ is the same. + if (skl_src_root.empty ()) + skl_src_root = move (d); // out_root_ is the same. else - skl.out_root_ = move (d); // Don't even need to create it. + skl_out_root = move (d); // Don't even need to create it. } - if (!exists (skl.src_root_)) + if (!exists (skl_src_root)) { + assert (!old); // An old package version cannot not exist. + // Create the buildfiles. // // Note that it's probably doesn't matter which naming scheme to use @@ -2519,7 +2705,7 @@ namespace bpkg { bool an (*ap.alt_naming); - path bf (skl.src_root_ / + path bf (skl_src_root / (an ? alt_bootstrap_file : std_bootstrap_file)); mk_p (bf.directory ()); @@ -2544,11 +2730,11 @@ namespace bpkg if (ap.root_build) save (*ap.root_build, - skl.src_root_ / (an ? alt_root_file : std_root_file)); + skl_src_root / (an ? alt_root_file : std_root_file)); for (const buildfile& f: ap.buildfiles) { - path p (skl.src_root_ / + path p (skl_src_root / (an ? alt_build_dir : std_build_dir) / f.path); @@ -2589,7 +2775,7 @@ namespace bpkg m.dependencies.push_back (das); } - path mf (skl.src_root_ / manifest_file); + path mf (skl_src_root / manifest_file); try { @@ -2614,7 +2800,8 @@ namespace bpkg } } - skl.created_ = true; + if (!old) + skl.created_ = true; } try @@ -2647,10 +2834,10 @@ namespace bpkg // Note that it's ok for out_root to not exist (external package). // - const dir_path& src_root (skl.src_root_); - const dir_path& out_root (skl.out_root_.empty () - ? skl.src_root_ - : skl.out_root_); + const dir_path& src_root (skl_src_root); + const dir_path& out_root (skl_out_root.empty () + ? skl_src_root + : skl_out_root); auto rsi (create_root (ctx, out_root, src_root)); scope& rs (*rsi->second.front ()); |