From ca650053f66bb4b9f4f1de87aa41e8353bc97e1c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 4 Jun 2019 13:38:11 +0200 Subject: Add --existing|-e option to bpkg-cfg-create With this option cfg-create initializes a bpkg configuration based on an existing build system configuration instead of creating a new one. --- bpkg/cfg-create.cli | 31 ++++++++++++------- bpkg/cfg-create.cxx | 88 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 84 insertions(+), 35 deletions(-) diff --git a/bpkg/cfg-create.cli b/bpkg/cfg-create.cli index bac601d..571c614 100644 --- a/bpkg/cfg-create.cli +++ b/bpkg/cfg-create.cli @@ -16,25 +16,28 @@ namespace bpkg "\h|SYNOPSIS| - \c{\b{bpkg cfg-create}|\b{create} [] []} + \c{\b{bpkg cfg-create}|\b{create} [] []\n + \b{bpkg cfg-create}|\b{create} [] \b{--existing|-e}} \c{ = ( | )...} \h|DESCRIPTION| The \cb{cfg-create} command creates a new \cb{bpkg} configuration with - the specified \cb{build2} modules and configuration variables. The - \cb{bpkg} configuration itself is a build system configuration; see - build system driver (\l{b(1)}) \cb{create} meta-operation for details. + the specified \cb{build2} modules and configuration variables (the first + form) or initializes one based on an existing build system configuration + (the second form). The \cb{bpkg} configuration itself is a build system + configuration; see build system driver (\l{b(1)}) \cb{create} + meta-operation for details. - Unless the \cb{--wipe} option is specified, \cb{cfg-create} expects the - configuration directory to be empty or to not exist (in which case it - will be created). + Unless the \cb{--existing|-e} or \cb{--wipe} option is specified, + \cb{cfg-create} expects the configuration directory to be empty or to not + exist (in which case it will be created). - By default, the resulting configuration loads the \cb{config}, \cb{test}, - \cb{dist}, and \cb{install} modules. However, additional modules and, if - required, their configuration variables can be specified as the - \cb{cfg-create} arguments. For example: + By default, the configuration created with the first form loads the + \cb{config}, \cb{test}, \cb{dist}, and \cb{install} modules. However, + additional modules and, if required, their configuration variables can be + specified as the \cb{cfg-create} arguments. For example: \ bpkg create cxx config.cxx=clang++ config.install.root=/usr/local @@ -63,6 +66,12 @@ namespace bpkg directory." } + bool --existing|-e + { + "Initialize a \cb{bpkg} configuration based on an existing build system + configuration." + } + bool --wipe { "Wipe the configuration directory clean before creating the new diff --git a/bpkg/cfg-create.cxx b/bpkg/cfg-create.cxx index d6f9cdc..14fb982 100644 --- a/bpkg/cfg-create.cxx +++ b/bpkg/cfg-create.cxx @@ -18,41 +18,58 @@ namespace bpkg { tracer trace ("cfg_create"); + if (o.existing () && o.wipe ()) + fail << "both --existing|-e and --wipe specified"; + if (o.wipe () && !o.directory_specified ()) fail << "--wipe requires explicit --directory|-d"; dir_path c (o.directory ()); l4 ([&]{trace << "creating configuration in " << c;}); - // If the directory already exists, make sure it is empty. Otherwise - // create it. + // Verify the existing directory is compatible with our mode. // if (exists (c)) { - l5 ([&]{trace << "directory " << c << " exists";}); - - if (!empty (c)) + if (o.existing ()) { - l5 ([&]{trace << "directory " << c << " not empty";}); - - if (!o.wipe ()) - fail << "directory " << c << " is not empty" << - info << "use --wipe to clean it up but be careful"; - - rm_r (c, false); + // Bail if the .bpkg/ directory already exists and is not empty. + // + // If you are wondering why don't we allow --wipe here, it's the + // existing packages that may be littering the configuration -- + // cleaning those up will be messy. + // + dir_path d (c / bpkg_dir); + + if (exists (d) && !empty (d)) + fail << "directory " << d << " already exists"; + } + else + { + // If the directory already exists, make sure it is empty. + // + if (!empty (c)) + { + if (!o.wipe ()) + fail << "directory " << c << " is not empty" << + info << "use --wipe to clean it up but be careful"; + + rm_r (c, false); + } } } else { - l5 ([&]{trace << "directory " << c << " does not exist";}); + // Note that we allow non-existent directory even in the --existing mode + // in case the user wants to add the build system configuration later. + // mk_p (c); } // Sort arguments into modules and configuration variables. // - string mods; // build2 create meta-operation parameters. + strings mods; strings vars; - while (args.more ()) { string a (args.next ()); @@ -63,8 +80,7 @@ namespace bpkg } else if (!a.empty ()) { - mods += mods.empty () ? ", " : " "; - mods += a; + mods.push_back (move (a)); } else fail << "empty string as argument"; @@ -72,12 +88,33 @@ namespace bpkg // Create and configure. // - // Run quiet. Use path representation to get canonical trailing slash. - // - run_b (o, - verb_b::quiet, - vars, - "create('" + c.representation () + "'" + mods + ")"); + if (o.existing ()) + { + if (!mods.empty ()) + fail << "module '" << mods[0] << "' specified with --existing|-e"; + + if (!vars.empty ()) + fail << "variable '" << vars[0] << "' specified with --existing|-e"; + } + else + { + // Assemble the build2 create meta-operation parameters. + // + string params ("'" + c.representation () + "'"); + if (!mods.empty ()) + { + params += ','; + for (const string& m: mods) + { + params += ' '; + params += m; + } + } + + // Run quiet. Use path representation to get canonical trailing slash. + // + run_b (o, verb_b::quiet, vars, "create(" + params + ")"); + } // Create .bpkg/ and its subdirectories. // @@ -125,7 +162,10 @@ namespace bpkg if (verb && !o.no_result ()) { c.complete ().normalize (); - text << "created new configuration in " << c; + if (o.existing ()) + text << "initialized existing configuration in " << c; + else + text << "created new configuration in " << c; } return 0; -- cgit v1.1