Skip to content

Commit

Permalink
[vcpkg] Add a different way to use CommandBuilder, support InWorkingD…
Browse files Browse the repository at this point in the history
…irectory (#15583)

* [vcpkg] Add stuff to the system.process API

* CmdLineBuilder - add rvalue overloads
* Add InWorkingDirectory support

* remove `&&` outside of system.process.cpp

* minor CR

* move the non-InWorkingDirectory functions into the header as inline

* Update toolsrc/include/vcpkg/base/system.process.h

Co-authored-by: Billy O'Neal <bion@microsoft.com>

* fix CmdLineBuilder name

* moar bugfixin

* fix native() location

Co-authored-by: Billy O'Neal <bion@microsoft.com>
  • Loading branch information
strega-nil and BillyONeal committed Jan 12, 2021
1 parent 331f877 commit 94b9db9
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 86 deletions.
76 changes: 62 additions & 14 deletions toolsrc/include/vcpkg/base/system.process.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,30 @@ namespace vcpkg::System

struct CmdLineBuilder
{
CmdLineBuilder& path_arg(const fs::path& p) { return string_arg(fs::u8string(p)); }
CmdLineBuilder& string_arg(StringView s);
CmdLineBuilder& ampersand()
CmdLineBuilder() = default;
explicit CmdLineBuilder(const fs::path& p) { path_arg(p); }
explicit CmdLineBuilder(StringView s) { string_arg(s); }
explicit CmdLineBuilder(const std::string& s) { string_arg(s); }
explicit CmdLineBuilder(const char* s) { string_arg({s, ::strlen(s)}); }

CmdLineBuilder& path_arg(const fs::path& p) & { return string_arg(fs::u8string(p)); }
CmdLineBuilder& string_arg(StringView s) &;
CmdLineBuilder& raw_arg(StringView s) &
{
buf.push_back('&');
buf.push_back('&');
buf.push_back(' ');
buf.append(s.data(), s.size());
return *this;
}
std::string extract() noexcept { return std::move(buf); }

operator ZStringView() const { return buf; }
CmdLineBuilder&& path_arg(const fs::path& p) && { return std::move(path_arg(p)); }
CmdLineBuilder&& string_arg(StringView s) && { return std::move(string_arg(s)); };
CmdLineBuilder&& raw_arg(StringView s) && { return std::move(raw_arg(s)); }

std::string&& extract() && { return std::move(buf); }
operator StringView() noexcept { return buf; }
StringView command_line() const { return buf; }

void clear() { buf.clear(); }

private:
std::string buf;
Expand All @@ -61,24 +74,59 @@ namespace vcpkg::System
Environment get_modified_clean_environment(const std::unordered_map<std::string, std::string>& extra_env,
const std::string& prepend_to_path = {});

int cmd_execute(const ZStringView cmd_line, const Environment& env = {});
int cmd_execute_clean(const ZStringView cmd_line);
struct InWorkingDirectory
{
const fs::path& working_directory;
};

int cmd_execute(StringView cmd_line, InWorkingDirectory wd, const Environment& env = {});
inline int cmd_execute(StringView cmd_line, const Environment& env = {})
{
return cmd_execute(cmd_line, InWorkingDirectory{fs::path()}, env);
}

int cmd_execute_clean(StringView cmd_line, InWorkingDirectory wd);
inline int cmd_execute_clean(StringView cmd_line)
{
return cmd_execute_clean(cmd_line, InWorkingDirectory{fs::path()});
}

#if defined(_WIN32)
Environment cmd_execute_modify_env(const ZStringView cmd_line, const Environment& env = {});
Environment cmd_execute_modify_env(StringView cmd_line, const Environment& env = {});

void cmd_execute_background(const StringView cmd_line);
#endif

ExitCodeAndOutput cmd_execute_and_capture_output(const ZStringView cmd_line, const Environment& env = {});
ExitCodeAndOutput cmd_execute_and_capture_output(StringView cmd_line,
InWorkingDirectory wd,
const Environment& env = {});
inline ExitCodeAndOutput cmd_execute_and_capture_output(StringView cmd_line, const Environment& env = {})
{
return cmd_execute_and_capture_output(cmd_line, InWorkingDirectory{fs::path()}, env);
}

int cmd_execute_and_stream_lines(const ZStringView cmd_line,
std::function<void(const std::string&)> per_line_cb,
int cmd_execute_and_stream_lines(StringView cmd_line,
InWorkingDirectory wd,
std::function<void(StringView)> per_line_cb,
const Environment& env = {});
inline int cmd_execute_and_stream_lines(StringView cmd_line,
std::function<void(StringView)> per_line_cb,
const Environment& env = {})
{
return cmd_execute_and_stream_lines(cmd_line, InWorkingDirectory{fs::path()}, std::move(per_line_cb), env);
}

int cmd_execute_and_stream_data(const ZStringView cmd_line,
int cmd_execute_and_stream_data(StringView cmd_line,
InWorkingDirectory wd,
std::function<void(StringView)> data_cb,
const Environment& env = {});
inline int cmd_execute_and_stream_data(StringView cmd_line,
std::function<void(StringView)> data_cb,
const Environment& env = {})
{
return cmd_execute_and_stream_data(cmd_line, InWorkingDirectory{fs::path()}, std::move(data_cb), env);
}

void register_console_ctrl_handler();
#if defined(_WIN32)
void initialize_global_job_object();
Expand Down
8 changes: 5 additions & 3 deletions toolsrc/src/vcpkg-test/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@ TEST_CASE ("cmdlinebuilder", "[system]")
cmd.string_arg("hello world!");
cmd.string_arg("|");
cmd.string_arg(";");
REQUIRE(cmd.extract() == "relative/path.exe abc \"hello world!\" \"|\" \";\"");
REQUIRE(cmd.command_line() == "relative/path.exe abc \"hello world!\" \"|\" \";\"");

cmd.clear();

cmd.path_arg(fs::u8path("trailing\\slash\\"));
cmd.string_arg("inner\"quotes");
#ifdef _WIN32
REQUIRE(cmd.extract() == "\"trailing\\slash\\\\\" \"inner\\\"quotes\"");
REQUIRE(cmd.command_line() == "\"trailing\\slash\\\\\" \"inner\\\"quotes\"");
#else
REQUIRE(cmd.extract() == "\"trailing\\\\slash\\\\\" \"inner\\\"quotes\"");
REQUIRE(cmd.command_line() == "\"trailing\\\\slash\\\\\" \"inner\\\"quotes\"");
#endif
}
8 changes: 4 additions & 4 deletions toolsrc/src/vcpkg/archives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ namespace vcpkg::Archives
#else
if (ext == ".gz" && ext.extension() != ".tar")
{
const auto code = System::cmd_execute(
Strings::format(R"(cd '%s' && tar xzf '%s')", fs::u8string(to_path_partial), fs::u8string(archive)));
const auto code = System::cmd_execute(System::CmdLineBuilder{"tar"}.string_arg("xzf").path_arg(archive),
System::InWorkingDirectory{to_path_partial});
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", fs::u8string(archive));
}
else if (ext == ".zip")
{
const auto code = System::cmd_execute(
Strings::format(R"(cd '%s' && unzip -qqo '%s')", fs::u8string(to_path_partial), fs::u8string(archive)));
const auto code = System::cmd_execute(System::CmdLineBuilder{"unzip"}.string_arg("-qqo").path_arg(archive),
System::InWorkingDirectory{to_path_partial});
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "unzip failed while extracting %s", fs::u8string(archive));
}
else
Expand Down
6 changes: 3 additions & 3 deletions toolsrc/src/vcpkg/base/downloads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ namespace vcpkg::Downloads
{
cmd.string_arg(url);
}
auto res = System::cmd_execute_and_stream_lines(cmd, [out](const std::string& line) {
auto res = System::cmd_execute_and_stream_lines(cmd, [out](StringView line) {
if (Strings::starts_with(line, guid_marker))
{
out->push_back(std::strtol(line.data() + guid_marker.size(), nullptr, 10));
Expand Down Expand Up @@ -269,7 +269,7 @@ namespace vcpkg::Downloads
{
cmd.string_arg(url.first).string_arg("-o").path_arg(url.second);
}
auto res = System::cmd_execute_and_stream_lines(cmd, [out](const std::string& line) {
auto res = System::cmd_execute_and_stream_lines(cmd, [out](StringView line) {
if (Strings::starts_with(line, guid_marker))
{
out->push_back(std::strtol(line.data() + guid_marker.size(), nullptr, 10));
Expand Down Expand Up @@ -306,7 +306,7 @@ namespace vcpkg::Downloads
cmd.string_arg("-H").string_arg("x-ms-version: 2020-04-08");
cmd.string_arg("-H").string_arg("x-ms-blob-type: BlockBlob");
int code = 0;
auto res = System::cmd_execute_and_stream_lines(cmd, [&code](const std::string& line) {
auto res = System::cmd_execute_and_stream_lines(cmd, [&code](StringView line) {
if (Strings::starts_with(line, guid_marker))
{
code = std::strtol(line.data() + guid_marker.size(), nullptr, 10);
Expand Down
Loading

0 comments on commit 94b9db9

Please sign in to comment.