From ec124582acf966db9e6ddb226b53021fe6be591a Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 8 Jun 2023 08:50:10 -0400 Subject: cmProcessTools::RunProcess(): Replace cmsysProcess with cmUVProcessChain And convert the VCS code to std::vector. --- Source/CTest/cmCTestBZR.cxx | 31 +++++------ Source/CTest/cmCTestCVS.cxx | 18 +++--- Source/CTest/cmCTestGIT.cxx | 130 ++++++++++++++++++++++---------------------- Source/CTest/cmCTestHG.cxx | 35 +++++------- Source/CTest/cmCTestP4.cxx | 66 +++++++++------------- Source/CTest/cmCTestP4.h | 2 +- Source/CTest/cmCTestSVN.cxx | 36 +++++------- Source/CTest/cmCTestSVN.h | 2 +- Source/CTest/cmCTestVC.cxx | 45 +++++++-------- Source/CTest/cmCTestVC.h | 9 +-- Source/cmProcessTools.cxx | 82 +++++++++++++++++----------- Source/cmProcessTools.h | 8 ++- Source/cmcmd.cxx | 33 ++++------- 13 files changed, 233 insertions(+), 264 deletions(-) diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index 246e811..36df344 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -135,14 +135,14 @@ private: std::string cmCTestBZR::LoadInfo() { // Run "bzr info" to get the repository info from the work tree. - const char* bzr = this->CommandLineTool.c_str(); - const char* bzr_info[] = { bzr, "info", nullptr }; + std::string bzr = this->CommandLineTool; + std::vector bzr_info = { bzr, "info" }; InfoParser iout(this, "info-out> "); OutputLogger ierr(this->Log, "info-err> "); this->RunChild(bzr_info, &iout, &ierr); // Run "bzr revno" to get the repository revision number from the work tree. - const char* bzr_revno[] = { bzr, "revno", nullptr }; + std::vector bzr_revno = { bzr, "revno" }; std::string rev; RevnoParser rout(this, "revno-out> ", rev); OutputLogger rerr(this->Log, "revno-err> "); @@ -372,22 +372,18 @@ bool cmCTestBZR::UpdateImpl() // TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY) // Use "bzr pull" to update the working tree. - std::vector bzr_update; - bzr_update.push_back(this->CommandLineTool.c_str()); + std::vector bzr_update; + bzr_update.push_back(this->CommandLineTool); bzr_update.push_back("pull"); - for (std::string const& arg : args) { - bzr_update.push_back(arg.c_str()); - } - - bzr_update.push_back(this->URL.c_str()); + cm::append(bzr_update, args); - bzr_update.push_back(nullptr); + bzr_update.push_back(this->URL); // For some reason bzr uses stderr to display the update status. OutputLogger out(this->Log, "pull-out> "); UpdateParser err(this, "pull-err> "); - return this->RunUpdateCommand(bzr_update.data(), &out, &err); + return this->RunUpdateCommand(bzr_update, &out, &err); } bool cmCTestBZR::LoadRevisions() @@ -408,10 +404,9 @@ bool cmCTestBZR::LoadRevisions() } // Run "bzr log" to get all global revisions of interest. - const char* bzr = this->CommandLineTool.c_str(); - const char* bzr_log[] = { - bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(), nullptr - }; + std::string bzr = this->CommandLineTool; + std::vector bzr_log = { bzr, "log", "-v", "-r", + revs, "--xml", this->URL }; { LogParser out(this, "log-out> "); OutputLogger err(this->Log, "log-err> "); @@ -467,8 +462,8 @@ private: bool cmCTestBZR::LoadModifications() { // Run "bzr status" which reports local modifications. - const char* bzr = this->CommandLineTool.c_str(); - const char* bzr_status[] = { bzr, "status", "-SV", nullptr }; + std::string bzr = this->CommandLineTool; + std::vector bzr_status = { bzr, "status", "-SV" }; StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(bzr_status, &out, &err); diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 95e898c..ef95b25 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -5,6 +5,7 @@ #include #include +#include #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -89,18 +90,15 @@ bool cmCTestCVS::UpdateImpl() } // Run "cvs update" to update the work tree. - std::vector cvs_update; - cvs_update.push_back(this->CommandLineTool.c_str()); + std::vector cvs_update; + cvs_update.push_back(this->CommandLineTool); cvs_update.push_back("-z3"); cvs_update.push_back("update"); - for (std::string const& arg : args) { - cvs_update.push_back(arg.c_str()); - } - cvs_update.push_back(nullptr); + cm::append(cvs_update, args); UpdateParser out(this, "up-out> "); UpdateParser err(this, "up-err> "); - return this->RunUpdateCommand(cvs_update.data(), &out, &err); + return this->RunUpdateCommand(cvs_update, &out, &err); } class cmCTestCVS::LogParser : public cmCTestVC::LineParser @@ -221,10 +219,8 @@ void cmCTestCVS::LoadRevisions(std::string const& file, const char* branchFlag, cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush); // Run "cvs log" to get revisions of this file on this branch. - const char* cvs = this->CommandLineTool.c_str(); - const char* cvs_log[] = { - cvs, "log", "-N", branchFlag, file.c_str(), nullptr - }; + std::string cvs = this->CommandLineTool; + std::vector cvs_log = { cvs, "log", "-N", branchFlag, file }; LogParser out(this, "log-out> ", revisions); OutputLogger err(this->Log, "log-err> "); diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 5f8cb74..ca8659e 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -9,8 +9,9 @@ #include #include +#include + #include "cmsys/FStream.hxx" -#include "cmsys/Process.h" #include "cmCTest.h" #include "cmCTestVC.h" @@ -18,6 +19,7 @@ #include "cmProcessOutput.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmUVProcessChain.h" #include "cmValue.h" static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major, @@ -58,9 +60,9 @@ private: std::string cmCTestGIT::GetWorkingRevision() { // Run plumbing "git rev-list" to get work tree revision. - const char* git = this->CommandLineTool.c_str(); - const char* git_rev_list[] = { git, "rev-list", "-n", "1", - "HEAD", "--", nullptr }; + std::string git = this->CommandLineTool; + std::vector git_rev_list = { git, "rev-list", "-n", + "1", "HEAD", "--" }; std::string rev; OneLineParser out(this, "rl-out> ", rev); OutputLogger err(this->Log, "rl-err> "); @@ -92,13 +94,13 @@ std::string cmCTestGIT::FindGitDir() std::string git_dir; // Run "git rev-parse --git-dir" to locate the real .git directory. - const char* git = this->CommandLineTool.c_str(); - char const* git_rev_parse[] = { git, "rev-parse", "--git-dir", nullptr }; + std::string git = this->CommandLineTool; + std::vector git_rev_parse = { git, "rev-parse", "--git-dir" }; std::string git_dir_line; OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line); OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); - if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr, - cmProcessOutput::UTF8)) { + if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, + std::string{}, cmProcessOutput::UTF8)) { git_dir = git_dir_line; } if (git_dir.empty()) { @@ -117,11 +119,10 @@ std::string cmCTestGIT::FindGitDir() std::string cygpath_exe = cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe"); if (cmSystemTools::FileExists(cygpath_exe)) { - char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(), - 0 }; + std::vector cygpath = { cygpath_exe, "-w", git_dir }; OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line); OutputLogger cygpath_err(this->Log, "cygpath-err> "); - if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, nullptr, + if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, std::string{}, cmProcessOutput::UTF8)) { git_dir = git_dir_line; } @@ -136,12 +137,12 @@ std::string cmCTestGIT::FindTopDir() std::string top_dir = this->SourceDirectory; // Run "git rev-parse --show-cdup" to locate the top of the tree. - const char* git = this->CommandLineTool.c_str(); - char const* git_rev_parse[] = { git, "rev-parse", "--show-cdup", nullptr }; + std::string git = this->CommandLineTool; + std::vector git_rev_parse = { git, "rev-parse", "--show-cdup" }; std::string cdup; OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup); OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); - if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr, + if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, "", cmProcessOutput::UTF8) && !cdup.empty()) { top_dir += "/"; @@ -153,10 +154,10 @@ std::string cmCTestGIT::FindTopDir() bool cmCTestGIT::UpdateByFetchAndReset() { - const char* git = this->CommandLineTool.c_str(); + std::string git = this->CommandLineTool; // Use "git fetch" to get remote commits. - std::vector git_fetch; + std::vector git_fetch; git_fetch.push_back(git); git_fetch.push_back("fetch"); @@ -166,17 +167,12 @@ bool cmCTestGIT::UpdateByFetchAndReset() opts = this->CTest->GetCTestConfiguration("GITUpdateOptions"); } std::vector args = cmSystemTools::ParseArguments(opts); - for (std::string const& arg : args) { - git_fetch.push_back(arg.c_str()); - } - - // Sentinel argument. - git_fetch.push_back(nullptr); + cm::append(git_fetch, args); // Fetch upstream refs. OutputLogger fetch_out(this->Log, "fetch-out> "); OutputLogger fetch_err(this->Log, "fetch-err> "); - if (!this->RunUpdateCommand(git_fetch.data(), &fetch_out, &fetch_err)) { + if (!this->RunUpdateCommand(git_fetch, &fetch_out, &fetch_err)) { return false; } @@ -207,25 +203,22 @@ bool cmCTestGIT::UpdateByFetchAndReset() } // Reset the local branch to point at that tracked from upstream. - char const* git_reset[] = { git, "reset", "--hard", sha1.c_str(), nullptr }; + std::vector git_reset = { git, "reset", "--hard", sha1 }; OutputLogger reset_out(this->Log, "reset-out> "); OutputLogger reset_err(this->Log, "reset-err> "); - return this->RunChild(&git_reset[0], &reset_out, &reset_err); + return this->RunChild(git_reset, &reset_out, &reset_err); } bool cmCTestGIT::UpdateByCustom(std::string const& custom) { cmList git_custom_command{ custom, cmList::EmptyElements::Yes }; - std::vector git_custom; - git_custom.reserve(git_custom_command.size() + 1); - for (std::string const& i : git_custom_command) { - git_custom.push_back(i.c_str()); - } - git_custom.push_back(nullptr); + std::vector git_custom; + git_custom.reserve(git_custom_command.size()); + cm::append(git_custom, git_custom_command); OutputLogger custom_out(this->Log, "custom-out> "); OutputLogger custom_err(this->Log, "custom-err> "); - return this->RunUpdateCommand(git_custom.data(), &custom_out, &custom_err); + return this->RunUpdateCommand(git_custom, &custom_out, &custom_err); } bool cmCTestGIT::UpdateInternal() @@ -244,13 +237,14 @@ bool cmCTestGIT::UpdateImpl() } std::string top_dir = this->FindTopDir(); - const char* git = this->CommandLineTool.c_str(); - const char* recursive = "--recursive"; - const char* sync_recursive = "--recursive"; + std::string git = this->CommandLineTool; + std::string recursive = "--recursive"; + std::string sync_recursive = "--recursive"; // Git < 1.6.5 did not support submodule --recursive + bool support_recursive = true; if (this->GetGitVersion() < cmCTestGITVersion(1, 6, 5, 0)) { - recursive = nullptr; + support_recursive = false; // No need to require >= 1.6.5 if there are no submodules. if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) { this->Log << "Git < 1.6.5 cannot update submodules recursively\n"; @@ -258,8 +252,9 @@ bool cmCTestGIT::UpdateImpl() } // Git < 1.8.1 did not support sync --recursive + bool support_sync_recursive = true; if (this->GetGitVersion() < cmCTestGITVersion(1, 8, 1, 0)) { - sync_recursive = nullptr; + support_sync_recursive = false; // No need to require >= 1.8.1 if there are no submodules. if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) { this->Log << "Git < 1.8.1 cannot synchronize submodules recursively\n"; @@ -274,35 +269,39 @@ bool cmCTestGIT::UpdateImpl() std::string init_submodules = this->CTest->GetCTestConfiguration("GITInitSubmodules"); if (cmIsOn(init_submodules)) { - char const* git_submodule_init[] = { git, "submodule", "init", nullptr }; + std::vector git_submodule_init = { git, "submodule", "init" }; ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err, - top_dir.c_str()); + top_dir); if (!ret) { return false; } } - char const* git_submodule_sync[] = { git, "submodule", "sync", - sync_recursive, nullptr }; + std::vector git_submodule_sync = { git, "submodule", "sync" }; + if (support_sync_recursive) { + git_submodule_sync.push_back(sync_recursive); + } ret = this->RunChild(git_submodule_sync, &submodule_out, &submodule_err, - top_dir.c_str()); + top_dir); if (!ret) { return false; } - char const* git_submodule[] = { git, "submodule", "update", recursive, - nullptr }; + std::vector git_submodule = { git, "submodule", "update" }; + if (support_recursive) { + git_submodule.push_back(recursive); + } return this->RunChild(git_submodule, &submodule_out, &submodule_err, - top_dir.c_str()); + top_dir); } unsigned int cmCTestGIT::GetGitVersion() { if (!this->CurrentGitVersion) { - const char* git = this->CommandLineTool.c_str(); - char const* git_version[] = { git, "--version", nullptr }; + std::string git = this->CommandLineTool; + std::vector git_version = { git, "--version" }; std::string version; OneLineParser version_out(this, "version-out> ", version); OutputLogger version_err(this->Log, "version-err> "); @@ -605,50 +604,49 @@ bool cmCTestGIT::LoadRevisions() { // Use 'git rev-list ... | git diff-tree ...' to get revisions. std::string range = this->OldRevision + ".." + this->NewRevision; - const char* git = this->CommandLineTool.c_str(); - const char* git_rev_list[] = { git, "rev-list", "--reverse", - range.c_str(), "--", nullptr }; - const char* git_diff_tree[] = { - git, "diff-tree", "--stdin", "--always", "-z", - "-r", "--pretty=raw", "--encoding=utf-8", nullptr + std::string git = this->CommandLineTool; + std::vector git_rev_list = { git, "rev-list", "--reverse", + range, "--" }; + std::vector git_diff_tree = { + git, "diff-tree", "--stdin", "--always", + "-z", "-r", "--pretty=raw", "--encoding=utf-8" }; this->Log << cmCTestGIT::ComputeCommandLine(git_rev_list) << " | " << cmCTestGIT::ComputeCommandLine(git_diff_tree) << "\n"; - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_AddCommand(cp, git_rev_list); - cmsysProcess_AddCommand(cp, git_diff_tree); - cmsysProcess_SetWorkingDirectory(cp, this->SourceDirectory.c_str()); + cmUVProcessChainBuilder builder; + builder.AddCommand(git_rev_list) + .AddCommand(git_diff_tree) + .SetWorkingDirectory(this->SourceDirectory); CommitParser out(this, "dt-out> "); OutputLogger err(this->Log, "dt-err> "); - cmCTestGIT::RunProcess(cp, &out, &err, cmProcessOutput::UTF8); + cmCTestGIT::RunProcess(builder, &out, &err, cmProcessOutput::UTF8); // Send one extra zero-byte to terminate the last record. out.Process("", 1); - cmsysProcess_Delete(cp); return true; } bool cmCTestGIT::LoadModifications() { - const char* git = this->CommandLineTool.c_str(); + std::string git = this->CommandLineTool; // Use 'git update-index' to refresh the index w.r.t. the work tree. - const char* git_update_index[] = { git, "update-index", "--refresh", - nullptr }; + std::vector git_update_index = { git, "update-index", + "--refresh" }; OutputLogger ui_out(this->Log, "ui-out> "); OutputLogger ui_err(this->Log, "ui-err> "); - this->RunChild(git_update_index, &ui_out, &ui_err, nullptr, + this->RunChild(git_update_index, &ui_out, &ui_err, "", cmProcessOutput::UTF8); // Use 'git diff-index' to get modified files. - const char* git_diff_index[] = { git, "diff-index", "-z", - "HEAD", "--", nullptr }; + std::vector git_diff_index = { git, "diff-index", "-z", "HEAD", + "--" }; DiffParser out(this, "di-out> "); OutputLogger err(this->Log, "di-err> "); - this->RunChild(git_diff_index, &out, &err, nullptr, cmProcessOutput::UTF8); + this->RunChild(git_diff_index, &out, &err, "", cmProcessOutput::UTF8); for (Change const& c : out.Changes) { this->DoModification(PathModified, c.Path); diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 02837ba..e1a945d 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -95,8 +95,8 @@ private: std::string cmCTestHG::GetWorkingRevision() { // Run plumbing "hg identify" to get work tree revision. - const char* hg = this->CommandLineTool.c_str(); - const char* hg_identify[] = { hg, "identify", "-i", nullptr }; + std::string hg = this->CommandLineTool; + std::vector hg_identify = { hg, "identify", "-i" }; std::string rev; IdentifyParser out(this, "rev-out> ", rev); OutputLogger err(this->Log, "rev-err> "); @@ -127,16 +127,16 @@ bool cmCTestHG::UpdateImpl() { // Use "hg pull" followed by "hg update" to update the working tree. { - const char* hg = this->CommandLineTool.c_str(); - const char* hg_pull[] = { hg, "pull", "-v", nullptr }; + std::string hg = this->CommandLineTool; + std::vector hg_pull = { hg, "pull", "-v" }; OutputLogger out(this->Log, "pull-out> "); OutputLogger err(this->Log, "pull-err> "); - this->RunChild(&hg_pull[0], &out, &err); + this->RunChild(hg_pull, &out, &err); } // TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY) - std::vector hg_update; + std::vector hg_update; hg_update.push_back(this->CommandLineTool.c_str()); hg_update.push_back("update"); hg_update.push_back("-v"); @@ -147,16 +147,11 @@ bool cmCTestHG::UpdateImpl() opts = this->CTest->GetCTestConfiguration("HGUpdateOptions"); } std::vector args = cmSystemTools::ParseArguments(opts); - for (std::string const& arg : args) { - hg_update.push_back(arg.c_str()); - } - - // Sentinel argument. - hg_update.push_back(nullptr); + cm::append(hg_update, args); OutputLogger out(this->Log, "update-out> "); OutputLogger err(this->Log, "update-err> "); - return this->RunUpdateCommand(hg_update.data(), &out, &err); + return this->RunUpdateCommand(hg_update, &out, &err); } class cmCTestHG::LogParser @@ -277,8 +272,8 @@ bool cmCTestHG::LoadRevisions() // the project has spaces in the path. Also, they may not have // proper XML escapes. std::string range = this->OldRevision + ":" + this->NewRevision; - const char* hg = this->CommandLineTool.c_str(); - const char* hgXMLTemplate = "CommandLineTool; + std::string hgXMLTemplate = "\n" " {author|person}\n" " {author|email}\n" @@ -288,10 +283,8 @@ bool cmCTestHG::LoadRevisions() " {file_adds}\n" " {file_dels}\n" "\n"; - const char* hg_log[] = { - hg, "log", "--removed", "-r", range.c_str(), - "--template", hgXMLTemplate, nullptr - }; + std::vector hg_log = { hg, "log", "--removed", "-r", + range, "--template", hgXMLTemplate }; LogParser out(this, "log-out> "); out.Process("\n" @@ -305,8 +298,8 @@ bool cmCTestHG::LoadRevisions() bool cmCTestHG::LoadModifications() { // Use 'hg status' to get modified files. - const char* hg = this->CommandLineTool.c_str(); - const char* hg_status[] = { hg, "status", nullptr }; + std::string hg = this->CommandLineTool; + std::vector hg_status = { hg, "status" }; StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(hg_status, &out, &err); diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 0e002b9..5d71b84 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -149,17 +149,16 @@ cmCTestP4::User cmCTestP4::GetUserData(const std::string& username) auto it = this->Users.find(username); if (it == this->Users.end()) { - std::vector p4_users; + std::vector p4_users; this->SetP4Options(p4_users); p4_users.push_back("users"); p4_users.push_back("-m"); p4_users.push_back("1"); - p4_users.push_back(username.c_str()); - p4_users.push_back(nullptr); + p4_users.push_back(username); UserParser out(this, "users-out> "); OutputLogger err(this->Log, "users-err> "); - this->RunChild(p4_users.data(), &out, &err); + this->RunChild(p4_users, &out, &err); // The user should now be added to the map. Search again. it = this->Users.find(username); @@ -303,10 +302,10 @@ private: } }; -void cmCTestP4::SetP4Options(std::vector& CommandOptions) +void cmCTestP4::SetP4Options(std::vector& CommandOptions) { if (this->P4Options.empty()) { - const char* p4 = this->CommandLineTool.c_str(); + std::string p4 = this->CommandLineTool; this->P4Options.emplace_back(p4); // The CTEST_P4_CLIENT variable sets the P4 client used when issuing @@ -328,15 +327,12 @@ void cmCTestP4::SetP4Options(std::vector& CommandOptions) cm::append(this->P4Options, cmSystemTools::ParseArguments(opts)); } - CommandOptions.clear(); - for (std::string const& o : this->P4Options) { - CommandOptions.push_back(o.c_str()); - } + CommandOptions = this->P4Options; } std::string cmCTestP4::GetWorkingRevision() { - std::vector p4_identify; + std::vector p4_identify; this->SetP4Options(p4_identify); p4_identify.push_back("changes"); @@ -345,14 +341,13 @@ std::string cmCTestP4::GetWorkingRevision() p4_identify.push_back("-t"); std::string source = this->SourceDirectory + "/...#have"; - p4_identify.push_back(source.c_str()); - p4_identify.push_back(nullptr); + p4_identify.push_back(source); std::string rev; IdentifyParser out(this, "p4_changes-out> ", rev); OutputLogger err(this->Log, "p4_changes-err> "); - bool result = this->RunChild(p4_identify.data(), &out, &err); + bool result = this->RunChild(p4_identify, &out, &err); // If there was a problem contacting the server return "" if (!result) { @@ -388,7 +383,7 @@ bool cmCTestP4::NoteNewRevision() bool cmCTestP4::LoadRevisions() { - std::vector p4_changes; + std::vector p4_changes; this->SetP4Options(p4_changes); // Use 'p4 changes ...@old,new' to get a list of changelists @@ -409,38 +404,36 @@ bool cmCTestP4::LoadRevisions() .append(this->NewRevision); p4_changes.push_back("changes"); - p4_changes.push_back(range.c_str()); - p4_changes.push_back(nullptr); + p4_changes.push_back(range); ChangesParser out(this, "p4_changes-out> "); OutputLogger err(this->Log, "p4_changes-err> "); this->ChangeLists.clear(); - this->RunChild(p4_changes.data(), &out, &err); + this->RunChild(p4_changes, &out, &err); if (this->ChangeLists.empty()) { return true; } // p4 describe -s ...@1111111,2222222 - std::vector p4_describe; + std::vector p4_describe; for (std::string const& i : cmReverseRange(this->ChangeLists)) { this->SetP4Options(p4_describe); p4_describe.push_back("describe"); p4_describe.push_back("-s"); - p4_describe.push_back(i.c_str()); - p4_describe.push_back(nullptr); + p4_describe.push_back(i); DescribeParser outDescribe(this, "p4_describe-out> "); OutputLogger errDescribe(this->Log, "p4_describe-err> "); - this->RunChild(p4_describe.data(), &outDescribe, &errDescribe); + this->RunChild(p4_describe, &outDescribe, &errDescribe); } return true; } bool cmCTestP4::LoadModifications() { - std::vector p4_diff; + std::vector p4_diff; this->SetP4Options(p4_diff); p4_diff.push_back("diff"); @@ -448,12 +441,11 @@ bool cmCTestP4::LoadModifications() // Ideally we would use -Od but not all clients support it p4_diff.push_back("-dn"); std::string source = this->SourceDirectory + "/..."; - p4_diff.push_back(source.c_str()); - p4_diff.push_back(nullptr); + p4_diff.push_back(source); DiffParser out(this, "p4_diff-out> "); OutputLogger err(this->Log, "p4_diff-err> "); - this->RunChild(p4_diff.data(), &out, &err); + this->RunChild(p4_diff, &out, &err); return true; } @@ -461,17 +453,14 @@ bool cmCTestP4::UpdateCustom(const std::string& custom) { cmList p4_custom_command{ custom, cmList::EmptyElements::Yes }; - std::vector p4_custom; - p4_custom.reserve(p4_custom_command.size() + 1); - for (std::string const& i : p4_custom_command) { - p4_custom.push_back(i.c_str()); - } - p4_custom.push_back(nullptr); + std::vector p4_custom; + p4_custom.reserve(p4_custom_command.size()); + cm::append(p4_custom, p4_custom_command); OutputLogger custom_out(this->Log, "p4_customsync-out> "); OutputLogger custom_err(this->Log, "p4_customsync-err> "); - return this->RunUpdateCommand(p4_custom.data(), &custom_out, &custom_err); + return this->RunUpdateCommand(p4_custom, &custom_out, &custom_err); } bool cmCTestP4::UpdateImpl() @@ -488,7 +477,7 @@ bool cmCTestP4::UpdateImpl() return false; } - std::vector p4_sync; + std::vector p4_sync; this->SetP4Options(p4_sync); p4_sync.push_back("sync"); @@ -499,9 +488,7 @@ bool cmCTestP4::UpdateImpl() opts = this->CTest->GetCTestConfiguration("P4UpdateOptions"); } std::vector args = cmSystemTools::ParseArguments(opts); - for (std::string const& arg : args) { - p4_sync.push_back(arg.c_str()); - } + cm::append(p4_sync, args); std::string source = this->SourceDirectory + "/..."; @@ -515,11 +502,10 @@ bool cmCTestP4::UpdateImpl() source.append("@\"").append(date).append("\""); } - p4_sync.push_back(source.c_str()); - p4_sync.push_back(nullptr); + p4_sync.push_back(source); OutputLogger out(this->Log, "p4_sync-out> "); OutputLogger err(this->Log, "p4_sync-err> "); - return this->RunUpdateCommand(p4_sync.data(), &out, &err); + return this->RunUpdateCommand(p4_sync, &out, &err); } diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h index 1889520..827caa1 100644 --- a/Source/CTest/cmCTestP4.h +++ b/Source/CTest/cmCTestP4.h @@ -39,7 +39,7 @@ private: std::vector P4Options; User GetUserData(const std::string& username); - void SetP4Options(std::vector& options); + void SetP4Options(std::vector& options); std::string GetWorkingRevision(); bool NoteOldRevision() override; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 91a1177..14bc510 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -33,7 +33,7 @@ cmCTestSVN::~cmCTestSVN() = default; void cmCTestSVN::CleanupImpl() { - std::vector svn_cleanup; + std::vector svn_cleanup; svn_cleanup.push_back("cleanup"); OutputLogger out(this->Log, "cleanup-out> "); OutputLogger err(this->Log, "cleanup-err> "); @@ -88,9 +88,9 @@ static bool cmCTestSVNPathStarts(std::string const& p1, std::string const& p2) std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo) { // Run "svn info" to get the repository info from the work tree. - std::vector svn_info; + std::vector svn_info; svn_info.push_back("info"); - svn_info.push_back(svninfo.LocalPath.c_str()); + svn_info.push_back(svninfo.LocalPath); std::string rev; InfoParser out(this, "info-out> ", rev, svninfo); OutputLogger err(this->Log, "info-err> "); @@ -251,26 +251,24 @@ bool cmCTestSVN::UpdateImpl() args.push_back("-r{" + this->GetNightlyTime() + " +0000}"); } - std::vector svn_update; + std::vector svn_update; svn_update.push_back("update"); - for (std::string const& arg : args) { - svn_update.push_back(arg.c_str()); - } + cm::append(svn_update, args); UpdateParser out(this, "up-out> "); OutputLogger err(this->Log, "up-err> "); return this->RunSVNCommand(svn_update, &out, &err); } -bool cmCTestSVN::RunSVNCommand(std::vector const& parameters, +bool cmCTestSVN::RunSVNCommand(std::vector const& parameters, OutputParser* out, OutputParser* err) { if (parameters.empty()) { return false; } - std::vector args; - args.push_back(this->CommandLineTool.c_str()); + std::vector args; + args.push_back(this->CommandLineTool); cm::append(args, parameters); args.push_back("--non-interactive"); @@ -278,16 +276,12 @@ bool cmCTestSVN::RunSVNCommand(std::vector const& parameters, std::vector parsedUserOptions = cmSystemTools::ParseArguments(userOptions); - for (std::string const& opt : parsedUserOptions) { - args.push_back(opt.c_str()); - } - - args.push_back(nullptr); + cm::append(args, parsedUserOptions); - if (strcmp(parameters[0], "update") == 0) { - return this->RunUpdateCommand(args.data(), out, err); + if (parameters[0] == "update") { + return this->RunUpdateCommand(args, out, err); } - return this->RunChild(args.data(), out, err); + return this->RunChild(args, out, err); } class cmCTestSVN::LogParser @@ -393,7 +387,7 @@ bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo) } // Run "svn log" to get all global revisions of interest. - std::vector svn_log; + std::vector svn_log; svn_log.push_back("log"); svn_log.push_back("--xml"); svn_log.push_back("-v"); @@ -472,7 +466,7 @@ private: bool cmCTestSVN::LoadModifications() { // Run "svn status" which reports local modifications. - std::vector svn_status; + std::vector svn_status; svn_status.push_back("status"); StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); @@ -534,7 +528,7 @@ bool cmCTestSVN::LoadRepositories() this->RootInfo = &(this->Repositories.back()); // Run "svn status" to get the list of external repositories - std::vector svn_status; + std::vector svn_status; svn_status.push_back("status"); ExternalParser out(this, "external-out> "); OutputLogger err(this->Log, "external-err> "); diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index 370d176..1485dc0 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -33,7 +33,7 @@ private: bool NoteNewRevision() override; bool UpdateImpl() override; - bool RunSVNCommand(std::vector const& parameters, + bool RunSVNCommand(std::vector const& parameters, OutputParser* out, OutputParser* err); // Information about an SVN repository (root repository or external) diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 609ccba..cbbb5a5 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -7,10 +7,9 @@ #include #include -#include "cmsys/Process.h" - #include "cmCTest.h" #include "cmSystemTools.h" +#include "cmUVProcessChain.h" #include "cmValue.h" #include "cmXMLWriter.h" @@ -55,18 +54,12 @@ bool cmCTestVC::InitialCheckout(const std::string& command) // Construct the initial checkout command line. std::vector args = cmSystemTools::ParseArguments(command); - std::vector vc_co; - vc_co.reserve(args.size() + 1); - for (std::string const& arg : args) { - vc_co.push_back(arg.c_str()); - } - vc_co.push_back(nullptr); // Run the initial checkout command and log its output. this->Log << "--- Begin Initial Checkout ---\n"; OutputLogger out(this->Log, "co-out> "); OutputLogger err(this->Log, "co-err> "); - bool result = this->RunChild(vc_co.data(), &out, &err, parent.c_str()); + bool result = this->RunChild(args, &out, &err, parent); this->Log << "--- End Initial Checkout ---\n"; if (!result) { cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -75,35 +68,35 @@ bool cmCTestVC::InitialCheckout(const std::string& command) return result; } -bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out, - OutputParser* err, const char* workDir, - Encoding encoding) +bool cmCTestVC::RunChild(const std::vector& cmd, + OutputParser* out, OutputParser* err, + std::string workDir, Encoding encoding) { this->Log << cmCTestVC::ComputeCommandLine(cmd) << "\n"; - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_SetCommand(cp, cmd); - workDir = workDir ? workDir : this->SourceDirectory.c_str(); - cmsysProcess_SetWorkingDirectory(cp, workDir); - cmCTestVC::RunProcess(cp, out, err, encoding); - int result = cmsysProcess_GetExitValue(cp); - cmsysProcess_Delete(cp); - return result == 0; + cmUVProcessChainBuilder builder; + if (workDir.empty()) { + workDir = this->SourceDirectory; + } + builder.AddCommand(cmd).SetWorkingDirectory(workDir); + auto status = cmCTestVC::RunProcess(builder, out, err, encoding); + return status.front().SpawnResult == 0 && status.front().ExitStatus == 0; } -std::string cmCTestVC::ComputeCommandLine(char const* const* cmd) +std::string cmCTestVC::ComputeCommandLine(const std::vector& cmd) { std::ostringstream line; const char* sep = ""; - for (const char* const* arg = cmd; *arg; ++arg) { - line << sep << "\"" << *arg << "\""; + for (auto const& arg : cmd) { + line << sep << "\"" << arg << "\""; sep = " "; } return line.str(); } -bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out, - OutputParser* err, Encoding encoding) +bool cmCTestVC::RunUpdateCommand(const std::vector& cmd, + OutputParser* out, OutputParser* err, + Encoding encoding) { // Report the command line. this->UpdateCommandLine = this->ComputeCommandLine(cmd); @@ -113,7 +106,7 @@ bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out, } // Run the command. - return this->RunChild(cmd, out, err, nullptr, encoding); + return this->RunChild(cmd, out, err, "", encoding); } std::string cmCTestVC::GetNightlyTime() diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 7b03d10..dd5456d 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -6,6 +6,7 @@ #include #include +#include #include "cmProcessOutput.h" #include "cmProcessTools.h" @@ -108,15 +109,15 @@ protected: }; /** Convert a list of arguments to a human-readable command line. */ - static std::string ComputeCommandLine(char const* const* cmd); + static std::string ComputeCommandLine(const std::vector& cmd); /** Run a command line and send output to given parsers. */ - bool RunChild(char const* const* cmd, OutputParser* out, OutputParser* err, - const char* workDir = nullptr, + bool RunChild(const std::vector& cmd, OutputParser* out, + OutputParser* err, std::string workDir = {}, Encoding encoding = cmProcessOutput::Auto); /** Run VC update command line and send output to given parsers. */ - bool RunUpdateCommand(char const* const* cmd, OutputParser* out, + bool RunUpdateCommand(const std::vector& cmd, OutputParser* out, OutputParser* err = nullptr, Encoding encoding = cmProcessOutput::Auto); diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index 9e7854b..1dd1dce 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -2,48 +2,68 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmProcessTools.h" +#include +#include #include -#include "cmsys/Process.h" +#include #include "cmProcessOutput.h" +#include "cmUVHandlePtr.h" +#include "cmUVStream.h" -void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, - OutputParser* err, Encoding encoding) +std::vector cmProcessTools::RunProcess( + cmUVProcessChainBuilder& builder, OutputParser* out, OutputParser* err, + Encoding encoding) { - cmsysProcess_Execute(cp); - char* data = nullptr; - int length = 0; - int p; cmProcessOutput processOutput(encoding); + + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR); + + auto chain = builder.Start(); + std::string strdata; - while ((out || err) && - (p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { - if (out && p == cmsysProcess_Pipe_STDOUT) { - processOutput.DecodeText(data, length, strdata, 1); - if (!out->Process(strdata.c_str(), static_cast(strdata.size()))) { - out = nullptr; + cm::uv_pipe_ptr outputPipe; + outputPipe.init(chain.GetLoop(), 0); + uv_pipe_open(outputPipe, chain.OutputStream()); + auto outputHandle = cmUVStreamRead( + outputPipe, + [&out, &processOutput, &strdata](std::vector data) { + if (out) { + processOutput.DecodeText(data.data(), data.size(), strdata, 1); + if (!out->Process(strdata.c_str(), static_cast(strdata.size()))) { + out = nullptr; + } } - } else if (err && p == cmsysProcess_Pipe_STDERR) { - processOutput.DecodeText(data, length, strdata, 2); - if (!err->Process(strdata.c_str(), static_cast(strdata.size()))) { - err = nullptr; + }, + [&out]() { out = nullptr; }); + cm::uv_pipe_ptr errorPipe; + errorPipe.init(chain.GetLoop(), 0); + uv_pipe_open(errorPipe, chain.ErrorStream()); + auto errorHandle = cmUVStreamRead( + errorPipe, + [&err, &processOutput, &strdata](std::vector data) { + if (err) { + processOutput.DecodeText(data.data(), data.size(), strdata, 2); + if (!err->Process(strdata.c_str(), static_cast(strdata.size()))) { + err = nullptr; + } } - } + }, + [&err]() { err = nullptr; }); + while (out || err || !chain.Finished()) { + uv_run(&chain.GetLoop(), UV_RUN_ONCE); } - if (out) { - processOutput.DecodeText(std::string(), strdata, 1); - if (!strdata.empty()) { - out->Process(strdata.c_str(), static_cast(strdata.size())); - } - } - if (err) { - processOutput.DecodeText(std::string(), strdata, 2); - if (!strdata.empty()) { - err->Process(strdata.c_str(), static_cast(strdata.size())); - } - } - cmsysProcess_WaitForExit(cp, nullptr); + + std::vector result; + auto status = chain.GetStatus(); + std::transform( + status.begin(), status.end(), std::back_inserter(result), + [](const cmUVProcessChain::Status* s) -> cmUVProcessChain::Status { + return *s; + }); + return result; } cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR) diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index 74ec5e0..2bdabea 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -7,8 +7,10 @@ #include #include #include +#include #include "cmProcessOutput.h" +#include "cmUVProcessChain.h" /** \class cmProcessTools * \brief Helper classes for process output parsing @@ -81,7 +83,7 @@ public: }; /** Run a process and send output to given parsers. */ - static void RunProcess(struct cmsysProcess_s* cp, OutputParser* out, - OutputParser* err = nullptr, - Encoding encoding = cmProcessOutput::Auto); + static std::vector RunProcess( + cmUVProcessChainBuilder& builder, OutputParser* out, + OutputParser* err = nullptr, Encoding encoding = cmProcessOutput::Auto); }; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 2ac9d8e..1263bb2 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -28,6 +28,7 @@ #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTransformDepfile.h" +#include "cmUVHandlePtr.h" #include "cmUVProcessChain.h" #include "cmUVStream.h" #include "cmUtils.hxx" @@ -295,14 +296,8 @@ int CLCompileAndDependencies(const std::vector& args) } } - std::unique_ptr cp( - cmsysProcess_New(), cmsysProcess_Delete); - std::vector argv(command.size() + 1); - std::transform(command.begin(), command.end(), argv.begin(), - [](std::string const& s) { return s.c_str(); }); - argv.back() = nullptr; - cmsysProcess_SetCommand(cp.get(), argv.data()); - cmsysProcess_SetWorkingDirectory(cp.get(), currentBinaryDir.c_str()); + cmUVProcessChainBuilder builder; + builder.AddCommand(command).SetWorkingDirectory(currentBinaryDir); cmsys::ofstream fout(depFile.c_str()); if (!fout) { @@ -313,22 +308,18 @@ int CLCompileAndDependencies(const std::vector& args) CLOutputLogger errLogger(std::cerr); // Start the process. - cmProcessTools::RunProcess(cp.get(), &includeParser, &errLogger); + auto result = + cmProcessTools::RunProcess(builder, &includeParser, &errLogger); + auto const& subStatus = result.front(); int status = 0; // handle status of process - switch (cmsysProcess_GetState(cp.get())) { - case cmsysProcess_State_Exited: - status = cmsysProcess_GetExitValue(cp.get()); - break; - case cmsysProcess_State_Exception: - status = 1; - break; - case cmsysProcess_State_Error: - status = 2; - break; - default: - break; + if (subStatus.SpawnResult != 0) { + status = 2; + } else if (subStatus.TermSignal != 0) { + status = 1; + } else { + status = subStatus.ExitStatus; } if (status != 0) { -- cgit v0.12