aboutsummaryrefslogtreecommitdiff
path: root/libbutl/b.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbutl/b.cxx')
-rw-r--r--libbutl/b.cxx186
1 files changed, 109 insertions, 77 deletions
diff --git a/libbutl/b.cxx b/libbutl/b.cxx
index e1caa4c..0b4472f 100644
--- a/libbutl/b.cxx
+++ b/libbutl/b.cxx
@@ -1,58 +1,19 @@
// file : libbutl/b.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#ifndef __cpp_modules_ts
-#include <libbutl/b.mxx>
-#endif
-
-// C includes.
+#include <libbutl/b.hxx>
+#include <ios> // ios::failure
#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
-#include <string>
-#include <vector>
-#include <cstddef>
-#include <cstdint>
-#include <stdexcept>
-#include <functional>
-
-#include <ios> // ios::failure
-#include <utility> // move()
+#include <utility> // move()
#include <sstream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-module butl.b;
-
-// Only imports additional to interface.
-#ifdef __clang__
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.url;
-import butl.path;
-import butl.process;
-import butl.optional;
-import butl.project_name;
-import butl.standard_version;
-#endif
-
-import butl.utility; // next_word(), eof(), etc
-import butl.path_io;
-import butl.fdstream;
-import butl.process_io; // operator<<(ostream, process_path)
-import butl.small_vector;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/path-io.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/process-io.mxx>
-#include <libbutl/small-vector.mxx>
-#endif
+#include <algorithm>
+
+#include <libbutl/utility.hxx> // next_word(), eof(), etc
+#include <libbutl/path-io.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/process-io.hxx> // operator<<(ostream, process_path)
+#include <libbutl/small-vector.hxx>
using namespace std;
@@ -71,15 +32,30 @@ namespace butl
throw runtime_error ("invalid " + d);
}
- b_project_info
- b_info (const dir_path& project,
- bool ext_mods,
+ void
+ b_info (std::vector<b_project_info>& r,
+ const vector<dir_path>& projects,
+ b_info_flags fl,
uint16_t verb,
const function<b_callback>& cmd_callback,
const path& program,
const dir_path& search_fallback,
const vector<string>& ops)
{
+ // Bail out if the project list is empty.
+ //
+ if (projects.empty ())
+ return;
+
+ // Reserve enough space in the result and save its original size.
+ //
+ size_t rn (r.size ());
+ {
+ size_t n (rn + projects.size ());
+ if (r.capacity () < n)
+ r.reserve (n);
+ }
+
try
{
process_path pp (
@@ -105,6 +81,23 @@ namespace butl
else
vops.push_back ("-q");
+ string spec ("info(");
+
+ // Note that quoting is essential here.
+ //
+ for (size_t i (0); i != projects.size(); ++i)
+ {
+ if (i != 0)
+ spec += ' ';
+
+ spec += '\'' + projects[i].representation () + '\'';
+ }
+
+ if ((fl & b_info_flags::subprojects) == b_info_flags::none)
+ spec += ",no_subprojects";
+
+ spec += ')';
+
pr = process_start_callback (
cmd_callback ? cmd_callback : [] (const char* const*, size_t) {},
0 /* stdin */,
@@ -112,10 +105,12 @@ namespace butl
2 /* stderr */,
pp,
vops,
- ext_mods ? nullptr : "--no-external-modules",
+ ((fl & b_info_flags::ext_mods) == b_info_flags::none
+ ? "--no-external-modules"
+ : nullptr),
"-s",
ops,
- "info:", "'" + project.representation () + "'");
+ spec);
pipe.out.close ();
ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit);
@@ -145,31 +140,52 @@ namespace butl
}
};
- b_project_info r;
- for (string l; !eof (getline (is, l)); )
+ b_project_info pi;
+ auto add_project = [&r, &pi] ()
{
- if (l.compare (0, 9, "project: ") == 0)
- {
- string v (l, 9);
- if (!v.empty ())
- r.project = parse_name (move (v), "project");
- }
- else if (l.compare (0, 9, "version: ") == 0)
+ // Parse version string to standard version if the project loaded
+ // the version module.
+ //
+ const auto& ms (pi.modules);
+ if (find (ms.begin (), ms.end (), "version") != ms.end ())
{
- string v (l, 9);
- if (!v.empty ())
try
{
- r.version = standard_version (v, standard_version::allow_stub);
+ pi.version = standard_version (pi.version_string,
+ standard_version::allow_stub);
}
catch (const invalid_argument& e)
{
- bad_value ("version '" + v + "': " + e.what ());
+ bad_value ("version '" + pi.version_string + "': " + e.what ());
}
}
+
+ // Add the project info and prepare for the next project info
+ // parsing.
+ //
+ r.push_back (move (pi));
+ pi = b_project_info ();
+ };
+
+ for (string l; !eof (getline (is, l)); )
+ {
+ if (l.empty ())
+ {
+ add_project ();
+ }
+ else if (l.compare (0, 9, "project: ") == 0)
+ {
+ string v (l, 9);
+ if (!v.empty ())
+ pi.project = parse_name (move (v), "project");
+ }
+ else if (l.compare (0, 9, "version: ") == 0)
+ {
+ pi.version_string = string (l, 9);
+ }
else if (l.compare (0, 9, "summary: ") == 0)
{
- r.summary = string (l, 9);
+ pi.summary = string (l, 9);
}
else if (l.compare (0, 5, "url: ") == 0)
{
@@ -177,7 +193,7 @@ namespace butl
if (!v.empty ())
try
{
- r.url = url (v);
+ pi.url = url (v);
}
catch (const invalid_argument& e)
{
@@ -186,17 +202,17 @@ namespace butl
}
else if (l.compare (0, 10, "src_root: ") == 0)
{
- r.src_root = parse_dir (string (l, 10), "src_root");
+ pi.src_root = parse_dir (string (l, 10), "src_root");
}
else if (l.compare (0, 10, "out_root: ") == 0)
{
- r.out_root = parse_dir (string (l, 10), "out_root");
+ pi.out_root = parse_dir (string (l, 10), "out_root");
}
else if (l.compare (0, 14, "amalgamation: ") == 0)
{
string v (l, 14);
if (!v.empty ())
- r.amalgamation = parse_dir (move (v), "amalgamation");
+ pi.amalgamation = parse_dir (move (v), "amalgamation");
}
else if (l.compare (0, 13, "subprojects: ") == 0)
{
@@ -214,7 +230,7 @@ namespace butl
if (p != 0)
sn = parse_name (string (s, 0, p), "subproject");
- r.subprojects.push_back (
+ pi.subprojects.push_back (
b_project_info::subproject {move (sn),
parse_dir (string (s, p + 1),
"subproject")});
@@ -224,20 +240,36 @@ namespace butl
{
string v (l, 12);
for (size_t b (0), e (0); next_word (v, b, e); )
- r.operations.push_back (string (v, b, e - b));
+ pi.operations.push_back (string (v, b, e - b));
}
else if (l.compare (0, 17, "meta-operations: ") == 0)
{
string v (l, 17);
for (size_t b (0), e (0); next_word (v, b, e); )
- r.meta_operations.push_back (string (v, b, e - b));
+ pi.meta_operations.push_back (string (v, b, e - b));
+ }
+ else if (l.compare (0, 9, "modules: ") == 0)
+ {
+ string v (l, 9);
+ for (size_t b (0), e (0); next_word (v, b, e); )
+ pi.modules.push_back (string (v, b, e - b));
}
}
is.close (); // Detect errors.
if (pr.wait ())
- return r;
+ {
+ add_project (); // Add the remaining project info.
+
+ if (r.size () - rn == projects.size ())
+ return;
+
+ ostringstream os;
+ os << "invalid " << pp << " output: expected information for "
+ << projects.size () << " projects instead of " << r.size () - rn;
+ throw b_error (os.str (), move (pr.exit));
+ }
}
// Note that ios::failure inherits from std::runtime_error, so this
// catch-clause must go last.
@@ -276,7 +308,7 @@ namespace butl
assert (!pr.wait ());
throw b_error (
- string ("process ") + pp.recall_string () + " " + to_string (*pr.exit),
+ string ("process ") + pp.recall_string () + ' ' + to_string (*pr.exit),
move (pr.exit));
}
catch (const process_error& e)