diff --git a/toolsrc/include/vcpkg/base/system.process.h b/toolsrc/include/vcpkg/base/system.process.h index 3b60630bb2..1c62fa2858 100644 --- a/toolsrc/include/vcpkg/base/system.process.h +++ b/toolsrc/include/vcpkg/base/system.process.h @@ -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; @@ -61,24 +74,59 @@ namespace vcpkg::System Environment get_modified_clean_environment(const std::unordered_map& 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 per_line_cb, + int cmd_execute_and_stream_lines(StringView cmd_line, + InWorkingDirectory wd, + std::function per_line_cb, const Environment& env = {}); + inline int cmd_execute_and_stream_lines(StringView cmd_line, + std::function 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 data_cb, const Environment& env = {}); + inline int cmd_execute_and_stream_data(StringView cmd_line, + std::function 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(); diff --git a/toolsrc/src/vcpkg-test/system.cpp b/toolsrc/src/vcpkg-test/system.cpp index e7f8aca8ff..7ebc621f0e 100644 --- a/toolsrc/src/vcpkg-test/system.cpp +++ b/toolsrc/src/vcpkg-test/system.cpp @@ -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 } diff --git a/toolsrc/src/vcpkg/archives.cpp b/toolsrc/src/vcpkg/archives.cpp index 0faf756ad3..33132f892c 100644 --- a/toolsrc/src/vcpkg/archives.cpp +++ b/toolsrc/src/vcpkg/archives.cpp @@ -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 diff --git a/toolsrc/src/vcpkg/base/downloads.cpp b/toolsrc/src/vcpkg/base/downloads.cpp index 50c4c2a0a6..e5b91f61cd 100644 --- a/toolsrc/src/vcpkg/base/downloads.cpp +++ b/toolsrc/src/vcpkg/base/downloads.cpp @@ -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)); @@ -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)); @@ -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); diff --git a/toolsrc/src/vcpkg/base/system.process.cpp b/toolsrc/src/vcpkg/base/system.process.cpp index d4410e28ab..ff608ea0e5 100644 --- a/toolsrc/src/vcpkg/base/system.process.cpp +++ b/toolsrc/src/vcpkg/base/system.process.cpp @@ -195,10 +195,10 @@ namespace vcpkg cmd.string_arg(var.s); } cmd.string_arg("-P").path_arg(cmake_script); - return cmd.extract(); + return std::move(cmd).extract(); } - System::CmdLineBuilder& System::CmdLineBuilder::string_arg(StringView s) + System::CmdLineBuilder& System::CmdLineBuilder::string_arg(StringView s) & { if (!buf.empty()) buf.push_back(' '); if (Strings::find_first_of(s, " \t\n\r\"\\,;&`^|'") != s.end()) @@ -384,7 +384,10 @@ namespace vcpkg return clean_env; } - int System::cmd_execute_clean(const ZStringView cmd_line) { return cmd_execute(cmd_line, get_clean_environment()); } + int System::cmd_execute_clean(StringView cmd_line, InWorkingDirectory wd) + { + return cmd_execute(cmd_line, wd, get_clean_environment()); + } #if defined(_WIN32) struct ProcessInfo @@ -435,7 +438,8 @@ namespace vcpkg /// If non-null, an environment block to use for the new process. If null, the /// new process will inherit the current environment. - static ExpectedT windows_create_process(const StringView cmd_line, + static ExpectedT windows_create_process(StringView cmd_line, + InWorkingDirectory wd, const Environment& env, DWORD dwCreationFlags, STARTUPINFOW& startup_info) noexcept @@ -446,6 +450,14 @@ namespace vcpkg // Flush stdout before launching external process fflush(nullptr); + std::wstring working_directory; + if (!wd.working_directory.empty()) + { + // this only fails if we can't get the current working directory of vcpkg, and we assume that we have that, + // so it's fine anyways + working_directory = Files::get_real_filesystem().absolute(VCPKG_LINE_INFO, wd.working_directory).native(); + } + VCPKG_MSVC_WARNING(suppress : 6335) // Leaking process information handle 'process_info.proc_info.hProcess' // /analyze can't tell that we transferred ownership here bool succeeded = @@ -458,7 +470,7 @@ namespace vcpkg env.m_env_data.empty() ? nullptr : const_cast(static_cast(env.m_env_data.data())), - nullptr, + working_directory.empty() ? nullptr : working_directory.data(), &startup_info, &process_info.proc_info); @@ -468,7 +480,8 @@ namespace vcpkg return GetLastError(); } - static ExpectedT windows_create_windowless_process(const StringView cmd_line, + static ExpectedT windows_create_windowless_process(StringView cmd_line, + InWorkingDirectory wd, const Environment& env, DWORD dwCreationFlags) noexcept { @@ -478,7 +491,7 @@ namespace vcpkg startup_info.dwFlags = STARTF_USESHOWWINDOW; startup_info.wShowWindow = SW_HIDE; - return windows_create_process(cmd_line, env, dwCreationFlags, startup_info); + return windows_create_process(cmd_line, wd, env, dwCreationFlags, startup_info); } struct ProcessInfoAndPipes @@ -506,7 +519,8 @@ namespace vcpkg } }; - static ExpectedT windows_create_process_redirect(const StringView cmd_line, + static ExpectedT windows_create_process_redirect(StringView cmd_line, + InWorkingDirectory wd, const Environment& env, DWORD dwCreationFlags) noexcept { @@ -533,7 +547,7 @@ namespace vcpkg if (!SetHandleInformation(ret.child_stdin, HANDLE_FLAG_INHERIT, 0)) Checks::exit_fail(VCPKG_LINE_INFO); startup_info.hStdError = startup_info.hStdOutput; - auto maybe_proc_info = windows_create_process(cmd_line, env, dwCreationFlags, startup_info); + auto maybe_proc_info = windows_create_process(cmd_line, wd, env, dwCreationFlags, startup_info); CloseHandle(startup_info.hStdInput); CloseHandle(startup_info.hStdOutput); @@ -555,8 +569,11 @@ namespace vcpkg { auto timer = Chrono::ElapsedTimer::create_started(); - auto process_info = windows_create_windowless_process( - cmd_line, {}, CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB); + auto process_info = + windows_create_windowless_process(cmd_line, + InWorkingDirectory{fs::path()}, + {}, + CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB); if (!process_info.get()) { Debug::print("cmd_execute_background() failed with error code ", process_info.error(), "\n"); @@ -565,7 +582,7 @@ namespace vcpkg Debug::print("cmd_execute_background() took ", static_cast(timer.microseconds()), " us\n"); } - Environment System::cmd_execute_modify_env(const ZStringView cmd_line, const Environment& env) + Environment System::cmd_execute_modify_env(StringView cmd_line, const Environment& env) { static StringLiteral magic_string = "cdARN4xjKueKScMy9C6H"; @@ -600,13 +617,13 @@ namespace vcpkg } #endif - int System::cmd_execute(const ZStringView cmd_line, const Environment& env) + int System::cmd_execute(StringView cmd_line, System::InWorkingDirectory wd, const Environment& env) { auto timer = Chrono::ElapsedTimer::create_started(); #if defined(_WIN32) using vcpkg::g_ctrl_c_state; g_ctrl_c_state.transition_to_spawn_process(); - auto proc_info = windows_create_windowless_process(cmd_line, env, 0); + auto proc_info = windows_create_windowless_process(cmd_line, wd, env, 0); auto long_exit_code = [&]() -> unsigned long { if (auto p = proc_info.get()) return p->wait(); @@ -621,24 +638,36 @@ namespace vcpkg "cmd_execute() returned ", exit_code, " after ", static_cast(timer.microseconds()), " us\n"); #else (void)env; - Debug::print("system(", cmd_line, ")\n"); + std::string real_command_line; + if (wd.working_directory.empty()) + { + real_command_line.assign(cmd_line.begin(), cmd_line.end()); + } + else + { + real_command_line = + System::CmdLineBuilder("cd").path_arg(wd.working_directory).raw_arg("&&").raw_arg(cmd_line).extract(); + } + Debug::print("system(", real_command_line, ")\n"); fflush(nullptr); - int exit_code = system(cmd_line.c_str()); + int exit_code = system(real_command_line.c_str()); Debug::print( "system() returned ", exit_code, " after ", static_cast(timer.microseconds()), " us\n"); #endif return exit_code; } - int System::cmd_execute_and_stream_lines(const ZStringView cmd_line, - std::function per_line_cb, + int System::cmd_execute_and_stream_lines(StringView cmd_line, + System::InWorkingDirectory wd, + std::function per_line_cb, const Environment& env) { std::string buf; auto rc = cmd_execute_and_stream_data( cmd_line, + wd, [&](StringView sv) { auto prev_size = buf.size(); Strings::append(buf, sv); @@ -658,7 +687,8 @@ namespace vcpkg return rc; } - int System::cmd_execute_and_stream_data(const ZStringView cmd_line, + int System::cmd_execute_and_stream_data(StringView cmd_line, + System::InWorkingDirectory wd, std::function data_cb, const Environment& env) { @@ -668,7 +698,7 @@ namespace vcpkg using vcpkg::g_ctrl_c_state; g_ctrl_c_state.transition_to_spawn_process(); - auto maybe_proc_info = windows_create_process_redirect(cmd_line, env, 0); + auto maybe_proc_info = windows_create_process_redirect(cmd_line, wd, env, 0); auto exit_code = [&]() -> unsigned long { if (auto p = maybe_proc_info.get()) return p->wait_and_stream_output(data_cb); @@ -678,7 +708,20 @@ namespace vcpkg g_ctrl_c_state.transition_from_spawn_process(); #else (void)env; - const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line); + std::string actual_cmd_line; + if (wd.working_directory.empty()) + { + actual_cmd_line = Strings::format(R"(%s 2>&1)", cmd_line); + } + else + { + actual_cmd_line = System::CmdLineBuilder("cd") + .path_arg(wd.working_directory) + .raw_arg("&&") + .raw_arg(cmd_line) + .raw_arg("2>&1") + .extract(); + } Debug::print("popen(", actual_cmd_line, ")\n"); // Flush stdout before launching external process @@ -711,11 +754,13 @@ namespace vcpkg return exit_code; } - ExitCodeAndOutput System::cmd_execute_and_capture_output(const ZStringView cmd_line, const Environment& env) + ExitCodeAndOutput System::cmd_execute_and_capture_output(StringView cmd_line, + System::InWorkingDirectory wd, + const Environment& env) { std::string output; auto rc = cmd_execute_and_stream_data( - cmd_line, [&](StringView sv) { Strings::append(output, sv); }, env); + cmd_line, wd, [&](StringView sv) { Strings::append(output, sv); }, env); return {rc, std::move(output)}; } diff --git a/toolsrc/src/vcpkg/binarycaching.cpp b/toolsrc/src/vcpkg/binarycaching.cpp index cf4888e1be..4592760ecb 100644 --- a/toolsrc/src/vcpkg/binarycaching.cpp +++ b/toolsrc/src/vcpkg/binarycaching.cpp @@ -96,13 +96,19 @@ namespace #if defined(_WIN32) auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP); - System::cmd_execute_and_capture_output( - Strings::format( - R"("%s" a "%s" "%s\*")", fs::u8string(seven_zip_exe), fs::u8string(destination), fs::u8string(source)), - System::get_clean_environment()); + System::cmd_execute_and_capture_output(System::CmdLineBuilder{seven_zip_exe} + .string_arg("a") + .path_arg(destination) + .path_arg(source / fs::u8path("*")), + System::get_clean_environment()); #else - System::cmd_execute_clean( - Strings::format(R"(cd '%s' && zip --quiet -y -r '%s' *)", fs::u8string(source), fs::u8string(destination))); + System::cmd_execute_clean(System::CmdLineBuilder{"zip"} + .string_arg("--quiet") + .string_arg("-y") + .string_arg("-r") + .path_arg(destination) + .string_arg("*"), + System::InWorkingDirectory{source}); #endif } @@ -414,7 +420,7 @@ namespace { } - int run_nuget_commandline(const std::string& cmdline) + int run_nuget_commandline(StringView cmdline) { if (m_interactive) { @@ -444,7 +450,7 @@ namespace } else if (res.output.find("for example \"-ApiKey AzureDevOps\"") != std::string::npos) { - auto res2 = System::cmd_execute_and_capture_output(cmdline + " -ApiKey AzureDevOps"); + auto res2 = System::cmd_execute_and_capture_output(Strings::concat(cmdline, " -ApiKey AzureDevOps")); if (Debug::g_debugging) { System::print2(res2.output); @@ -538,7 +544,7 @@ namespace cmdline.string_arg("-NonInteractive"); } - cmdlines.push_back(cmdline.extract()); + cmdlines.push_back(std::move(cmdline).extract()); } for (auto&& cfg : m_read_configs) { @@ -568,7 +574,7 @@ namespace cmdline.string_arg("-NonInteractive"); } - cmdlines.push_back(cmdline.extract()); + cmdlines.push_back(std::move(cmdline).extract()); } const size_t current_restored = m_restored.size(); @@ -647,7 +653,7 @@ namespace .string_arg("-ForceEnglishOutput"); if (!m_interactive) cmdline.string_arg("-NonInteractive"); - auto pack_rc = run_nuget_commandline(cmdline.extract()); + auto pack_rc = run_nuget_commandline(cmdline); if (pack_rc != 0) { @@ -676,7 +682,7 @@ namespace System::print2("Uploading binaries for ", spec, " to NuGet source ", write_src, ".\n"); - auto rc = run_nuget_commandline(cmd.extract()); + auto rc = run_nuget_commandline(cmd); if (rc != 0) { System::print2(System::Color::error, @@ -705,7 +711,7 @@ namespace System::print2( "Uploading binaries for ", spec, " using NuGet config ", fs::u8string(write_cfg), ".\n"); - auto rc = run_nuget_commandline(cmd.extract()); + auto rc = run_nuget_commandline(cmd); if (rc != 0) { diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index eb2a338b26..52385c2792 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -565,7 +565,7 @@ namespace vcpkg::Build CompilerInfo compiler_info; System::cmd_execute_and_stream_lines( command, - [&](const std::string& s) { + [&](StringView s) { static const StringLiteral s_hash_marker = "#COMPILER_HASH#"; if (Strings::starts_with(s, s_hash_marker)) { diff --git a/toolsrc/src/vcpkg/commands.porthistory.cpp b/toolsrc/src/vcpkg/commands.porthistory.cpp index 894b46b6eb..e6a7cd5dfe 100644 --- a/toolsrc/src/vcpkg/commands.porthistory.cpp +++ b/toolsrc/src/vcpkg/commands.porthistory.cpp @@ -30,7 +30,7 @@ namespace vcpkg::Commands::PortHistory const System::ExitCodeAndOutput run_git_command_inner(const VcpkgPaths& paths, const fs::path& dot_git_directory, const fs::path& working_directory, - const std::string& cmd) + StringView cmd) { const fs::path& git_exe = paths.get_tool_exe(Tools::GIT); @@ -38,13 +38,13 @@ namespace vcpkg::Commands::PortHistory builder.path_arg(git_exe) .string_arg(Strings::concat("--git-dir=", fs::u8string(dot_git_directory))) .string_arg(Strings::concat("--work-tree=", fs::u8string(working_directory))); - const std::string full_cmd = Strings::concat(builder.extract(), " ", cmd); + const std::string full_cmd = Strings::concat(std::move(builder).extract(), " ", cmd); const auto output = System::cmd_execute_and_capture_output(full_cmd); return output; } - const System::ExitCodeAndOutput run_git_command(const VcpkgPaths& paths, const std::string& cmd) + const System::ExitCodeAndOutput run_git_command(const VcpkgPaths& paths, StringView cmd) { const fs::path& work_dir = paths.root; const fs::path dot_git_dir = paths.root / ".git"; @@ -125,7 +125,7 @@ namespace vcpkg::Commands::PortHistory builder.string_arg("--left-only"); builder.string_arg("--"); // Begin pathspec builder.string_arg(Strings::format("ports/%s/.", port_name)); - const auto output = run_git_command(paths, builder.extract()); + const auto output = run_git_command(paths, builder); auto commits = Util::fmap( Strings::split(output.output, '\n'), [](const std::string& line) -> auto { diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp index b5c36ff870..de09efaff5 100644 --- a/toolsrc/src/vcpkg/export.cpp +++ b/toolsrc/src/vcpkg/export.cpp @@ -173,8 +173,7 @@ namespace vcpkg::Export .path_arg(output_dir) .string_arg("-NoDefaultExcludes"); - const int exit_code = - System::cmd_execute_and_capture_output(cmd.extract(), System::get_clean_environment()).exit_code; + const int exit_code = System::cmd_execute_and_capture_output(cmd, System::get_clean_environment()).exit_code; Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed"); const fs::path output_path = output_dir / (nuget_id + "." + nuget_version + ".nupkg"); @@ -225,8 +224,6 @@ namespace vcpkg::Export const fs::path exported_archive_path = (output_dir / exported_archive_filename); System::CmdLineBuilder cmd; - cmd.string_arg("cd").path_arg(raw_exported_dir.parent_path()); - cmd.ampersand(); cmd.path_arg(cmake_exe) .string_arg("-E") .string_arg("tar") @@ -236,14 +233,8 @@ namespace vcpkg::Export .string_arg("--") .path_arg(raw_exported_dir); - auto cmdline = cmd.extract(); -#ifdef WIN32 - // Invoke through `cmd` to support `&&` - cmdline.insert(0, "cmd /c \""); - cmdline.push_back('"'); -#endif - - const int exit_code = System::cmd_execute_clean(cmdline); + const int exit_code = + System::cmd_execute_clean(cmd, System::InWorkingDirectory{raw_exported_dir.parent_path()}); Checks::check_exit( VCPKG_LINE_INFO, exit_code == 0, "Error: %s creation failed", exported_archive_path.generic_string()); return exported_archive_path; diff --git a/toolsrc/src/vcpkg/export.prefab.cpp b/toolsrc/src/vcpkg/export.prefab.cpp index 38d4568a8c..3fb4d17306 100644 --- a/toolsrc/src/vcpkg/export.prefab.cpp +++ b/toolsrc/src/vcpkg/export.prefab.cpp @@ -212,7 +212,8 @@ namespace vcpkg::Export::Prefab System::get_clean_environment()); #else System::cmd_execute_clean( - Strings::format(R"(cd '%s' && zip --quiet -r '%s' *)", fs::u8string(source), fs::u8string(destination))); + System::CmdLineBuilder{"zip"}.string_arg("--quiet").string_arg("-r").path_arg(destination).string_arg("*"), + System::InWorkingDirectory{source}); #endif } diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index 0153ff65df..fd5abea4b0 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -491,7 +491,7 @@ namespace vcpkg::Metrics builder.path_arg(temp_folder_path_exe); builder.string_arg("x-upload-metrics"); builder.path_arg(vcpkg_metrics_txt_path); - System::cmd_execute_background(builder.extract()); + System::cmd_execute_background(builder); #else auto escaped_path = Strings::escape_string(fs::u8string(vcpkg_metrics_txt_path), '\'', '\\'); const std::string cmd_line = Strings::format( diff --git a/toolsrc/src/vcpkg/tools.cpp b/toolsrc/src/vcpkg/tools.cpp index 54b73c93f7..bdf2bdf6b7 100644 --- a/toolsrc/src/vcpkg/tools.cpp +++ b/toolsrc/src/vcpkg/tools.cpp @@ -359,7 +359,7 @@ CMake suite maintained and supported by Kitware (kitware.com/cmake). (void)paths; #endif cmd.path_arg(path_to_exe); - auto rc = System::cmd_execute_and_capture_output(cmd.extract()); + auto rc = System::cmd_execute_and_capture_output(cmd); if (rc.exit_code != 0) { #ifndef _WIN32 diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 27b7cfe028..407a14fd63 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -504,7 +504,7 @@ If you wish to silence this error and use classic mode, you can: .string_arg("--no-hardlinks") .path_arg(local_repo) .path_arg(dot_git_dir); - const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder.extract()); + const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder); Checks::check_exit(VCPKG_LINE_INFO, clone_output.exit_code == 0, "Failed to clone temporary vcpkg instance.\n%s\n", @@ -516,7 +516,7 @@ If you wish to silence this error and use classic mode, you can: .string_arg(commit_sha) .string_arg("--") .path_arg(subpath); - const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder.extract()); + const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder); Checks::check_exit(VCPKG_LINE_INFO, checkout_output.exit_code == 0, "Error: Failed to checkout %s:%s\n%s\n", @@ -552,7 +552,7 @@ If you wish to silence this error and use classic mode, you can: System::CmdLineBuilder showcmd = git_cmd_builder(*this, dot_git_dir, dot_git_dir).string_arg("show").string_arg(treeish); - auto output = System::cmd_execute_and_capture_output(showcmd.extract()); + auto output = System::cmd_execute_and_capture_output(showcmd); if (output.exit_code == 0) { return {std::move(output.output), expected_left_tag}; @@ -631,7 +631,7 @@ If you wish to silence this error and use classic mode, you can: .string_arg("--no-hardlinks") .path_arg(local_repo) .path_arg(dot_git_dir); - const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder.extract()); + const auto clone_output = System::cmd_execute_and_capture_output(clone_cmd_builder); Checks::check_exit(VCPKG_LINE_INFO, clone_output.exit_code == 0, "Failed to clone temporary vcpkg instance.\n%s\n", @@ -641,7 +641,7 @@ If you wish to silence this error and use classic mode, you can: { System::CmdLineBuilder fetch_cmd_builder = git_cmd_builder(paths, dot_git_dir, work_tree).string_arg("fetch"); - const auto fetch_output = System::cmd_execute_and_capture_output(fetch_cmd_builder.extract()); + const auto fetch_output = System::cmd_execute_and_capture_output(fetch_cmd_builder); Checks::check_exit(VCPKG_LINE_INFO, fetch_output.exit_code == 0, "Failed to update refs on temporary vcpkg repository.\n%s\n", @@ -658,7 +658,7 @@ If you wish to silence this error and use classic mode, you can: .string_arg("checkout") .string_arg(git_object) .string_arg("."); - const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder.extract()); + const auto checkout_output = System::cmd_execute_and_capture_output(checkout_cmd_builder); Checks::check_exit(VCPKG_LINE_INFO, checkout_output.exit_code == 0, "Failed to checkout %s", git_object); const auto& containing_folder = destination.parent_path();