winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 7d7b3a9869b59e06a7b4abf6f6dddf7211b7f0c7
parent 8d1cd0740bf5a020618e2e39e965d70258908e8b
Author: Ryan <69221034+ryfu-msft@users.noreply.github.com>
Date:   Wed, 24 Jul 2024 16:25:35 -0400

Pull in latest SFSClient (#4670)


Diffstat:
Msrc/SfsClient/readme.md | 4++--
Msrc/SfsClient/sfs-client/.github/dependabot.yml | 4++++
Msrc/SfsClient/sfs-client/cgmanifest.json | 6+++---
Msrc/SfsClient/sfs-client/client/tests/functional/details/CurlConnectionTests.cpp | 16++++++++--------
Msrc/SfsClient/sfs-client/client/tests/util/TestHelper.cpp | 6+++---
Msrc/SfsClient/sfs-client/samples/integration-do-client/IntegrationDOClient.cpp | 3++-
Msrc/SfsClient/sfs-client/samples/tool/SFSClientTool.cpp | 127++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/SfsClient/sfs-client/scripts/pip.requirements.txt | 2+-
Msrc/SfsClient/sfs-client/vcpkg.json | 2+-
9 files changed, 124 insertions(+), 46 deletions(-)

diff --git a/src/SfsClient/readme.md b/src/SfsClient/readme.md @@ -1,9 +1,9 @@ ## SfsClient -Do not change code under the sfs-client directory; it contains sfs-client source code from commit [ff315ec](https://github.com/microsoft/sfs-client/commits/ff315ec). +Do not change code under the sfs-client directory; it contains sfs-client source code from commit [6ab78af](https://github.com/microsoft/sfs-client/commits/6ab78af). It is created using git subtree command: ``` - git subtree add --prefix=src/SfsClient/sfs-client https://github.com/microsoft/sfs-client.git cf18b357f43aa9bbaba7d8b3b3774b39140aa00f --squash + git subtree add --prefix=src/SfsClient/sfs-client https://github.com/microsoft/sfs-client.git 6ab78af61bc859461ea8298786d87f24b49e3ec2 --squash ``` ### Update diff --git a/src/SfsClient/sfs-client/.github/dependabot.yml b/src/SfsClient/sfs-client/.github/dependabot.yml @@ -17,3 +17,7 @@ updates: directory: "/" schedule: interval: "weekly" + ignore: + # Ignore patch updates for all pip dependencies + - dependency-name: "*" + update-types: ["version-update:semver-patch"] diff --git a/src/SfsClient/sfs-client/cgmanifest.json b/src/SfsClient/sfs-client/cgmanifest.json @@ -37,7 +37,7 @@ "type": "git", "git": { "repositoryUrl": "https://github.com/curl/curl", - "commitHash": "d755a5f7c009dd63a61b2c745180d8ba937cbfeb" + "commitHash": "fd567d4f06857f4fc8e2f64ea727b1318f76ad33" } }, "developmentDependency": false @@ -56,7 +56,7 @@ "type": "git", "git": { "repositoryUrl": "https://github.com/curl/curl", - "commitHash": "d755a5f7c009dd63a61b2c745180d8ba937cbfeb" + "commitHash": "fd567d4f06857f4fc8e2f64ea727b1318f76ad33" } } ] @@ -75,7 +75,7 @@ "type": "git", "git": { "repositoryUrl": "https://github.com/curl/curl", - "commitHash": "d755a5f7c009dd63a61b2c745180d8ba937cbfeb" + "commitHash": "fd567d4f06857f4fc8e2f64ea727b1318f76ad33" } } ] diff --git a/src/SfsClient/sfs-client/client/tests/functional/details/CurlConnectionTests.cpp b/src/SfsClient/sfs-client/client/tests/functional/details/CurlConnectionTests.cpp @@ -45,15 +45,15 @@ class CurlConnectionTimeout : public CurlConnection std::string Get(const std::string& url) override { - // Timeout within 100ms - curl_easy_setopt(m_handle, CURLOPT_TIMEOUT_MS, 100L); + // Timeout within 1ms + curl_easy_setopt(m_handle, CURLOPT_TIMEOUT_MS, 1L); return CurlConnection::Get(url); } std::string Post(const std::string& url, const std::string& data) override { - // Timeout within 100ms - curl_easy_setopt(m_handle, CURLOPT_TIMEOUT_MS, 100L); + // Timeout within 1ms + curl_easy_setopt(m_handle, CURLOPT_TIMEOUT_MS, 1L); return CurlConnection::Post(url, data); } }; @@ -316,11 +316,11 @@ TEST("Testing a response over the limit fails the operation") json body = {{{"TargetingAttributes", {}}, {"Product", largeProductName}}}; REQUIRE_NOTHROW(connection->Post(url, body.dump())); - // Over limit fails + // Going over the limit fails with a message like "client returned ERROR on write of 16384 bytes" body[0]["Product"] = overLimitProductName; - REQUIRE_THROWS_CODE_MSG(connection->Post(url, body.dump()), - ConnectionUnexpectedError, - "Failure writing output to destination"); + REQUIRE_THROWS_CODE_MSG_MATCHES(connection->Post(url, body.dump()), + ConnectionUnexpectedError, + Catch::Matchers::ContainsSubstring("client returned ERROR on write of")); } TEST("Testing MS-CV is sent to server") diff --git a/src/SfsClient/sfs-client/client/tests/util/TestHelper.cpp b/src/SfsClient/sfs-client/client/tests/util/TestHelper.cpp @@ -43,7 +43,7 @@ std::string TimestampToString(std::chrono::time_point<std::chrono::system_clock> void SFS::test::LogCallbackToTest(const SFS::LogData& logData) { std::lock_guard guard(s_logMutex); - UNSCOPED_INFO("Log: " << TimestampToString(logData.time) << " [" << ToString(logData.severity) << "]" << " " - << std::filesystem::path(logData.file).filename().string() << ":" << logData.line << " " - << logData.message); + UNSCOPED_INFO("Log: " << TimestampToString(logData.time) << " [" << ToString(logData.severity) << "]" + << " " << std::filesystem::path(logData.file).filename().string() << ":" << logData.line + << " " << logData.message); } diff --git a/src/SfsClient/sfs-client/samples/integration-do-client/IntegrationDOClient.cpp b/src/SfsClient/sfs-client/samples/integration-do-client/IntegrationDOClient.cpp @@ -171,7 +171,8 @@ std::string TimestampToString(std::chrono::time_point<std::chrono::system_clock> void LoggingCallback(const SFS::LogData& logData) { std::cout << c_darkGreyStart << "Log: " << TimestampToString(logData.time) << " [" << ToString(logData.severity) - << "]" << " " << std::filesystem::path(logData.file).filename().string() << ":" << logData.line << " " + << "]" + << " " << std::filesystem::path(logData.file).filename().string() << ":" << logData.line << " " << logData.message << c_colorEnd << std::endl; } diff --git a/src/SfsClient/sfs-client/samples/tool/SFSClientTool.cpp b/src/SfsClient/sfs-client/samples/tool/SFSClientTool.cpp @@ -5,6 +5,7 @@ #include <exception> #include <filesystem> +#include <fstream> #include <iomanip> #include <iostream> #include <sstream> @@ -30,6 +31,7 @@ void DisplayUsage() << "Options:" << std::endl << " -h, --help\t\t\tDisplay this help message" << std::endl << " -v, --version\t\t\tDisplay the library version" << std::endl + << " -o, --outputFile <path>\t\tWhen specified, the JSON output is saved to this file" << std::endl << " --isApp\t\t\tIndicates the specific product is an App" << std::endl << " --instanceId <id>\t\tA custom SFS instance ID" << std::endl << " --namespace <ns>\t\tA custom SFS namespace" << std::endl @@ -87,6 +89,12 @@ struct Settings std::string instanceId; std::string nameSpace; std::string customUrl; + std::string outputFile; + + bool ShouldOutputToFile() const + { + return !outputFile.empty(); + } }; void ParseArguments(const std::vector<std::string_view>& args, Settings& settings) @@ -126,6 +134,11 @@ void ParseArguments(const std::vector<std::string_view>& args, Settings& setting { settings.displayVersion = true; } + else if (matchArg(args[i], "-o", "--outputFile")) + { + validateArg(i, "outputFile", settings.outputFile); + settings.outputFile = args[++i]; + } else if (matchLongArg(args[i], "--isApp")) { settings.isApp = true; @@ -197,16 +210,8 @@ constexpr std::string_view ToString(Architecture type) return ""; } -void DisplayResults(const std::vector<Content>& contents) +json ContentsToJson(const std::vector<Content>& contents) { - if (contents.empty()) - { - PrintError("No results found"); - return; - } - - PrintLog("Content found:"); - json out = json::array(); for (const auto& content : contents) { @@ -233,7 +238,7 @@ void DisplayResults(const std::vector<Content>& contents) out.push_back(j); } - PrintLog(out.dump(2 /*indent*/)); + return out; } json AppFileToJson(const AppFile& file) @@ -265,16 +270,8 @@ json AppFileToJson(const AppFile& file) return fileJson; } -void DisplayResults(const std::vector<AppContent>& contents) +json AppContentsToJson(const std::vector<AppContent>& contents) { - if (contents.empty()) - { - std::cout << "No results found." << std::endl; - return; - } - - PrintLog("Content found:"); - json out = json::array(); for (const auto& content : contents) { @@ -309,7 +306,50 @@ void DisplayResults(const std::vector<AppContent>& contents) out.push_back(j); } - PrintLog(out.dump(2 /*indent*/)); + return out; +} + +void DisplayResults(const json& results) +{ + if (results.empty()) + { + return; + } + + PrintLog("Content found:"); + PrintLog(results.dump(2 /*indent*/)); +} + +Result JSONToFile(const json& results, const std::string& filename) +{ + if (results.empty()) + { + return Result::Unexpected; + } + + const std::filesystem::path filepath = std::filesystem::absolute(filename); + try + { + std::filesystem::create_directories(filepath.parent_path()); + } + catch (const std::exception& e) + { + PrintError("Failed to create parent directories for filepath: " + filepath.string() + ". Error: " + e.what()); + return Result::Unexpected; + } + + std::ofstream file(filepath, std::ios::out | std::ios::trunc); + if (!file.is_open()) + { + PrintError("Failed to open file for writing: " + filename); + return Result::Unexpected; + } + + file << results.dump(2 /*indent*/); + + PrintLog("Content found. Saved to file " + filepath.string()); + + return Result::Success; } void LogResult(const SFS::Result& result) @@ -348,7 +388,8 @@ std::string TimestampToString(std::chrono::time_point<std::chrono::system_clock> void LoggingCallback(const SFS::LogData& logData) { std::cout << c_darkGreyStart << "Log: " << TimestampToString(logData.time) << " [" << ToString(logData.severity) - << "]" << " " << std::filesystem::path(logData.file).filename().string() << ":" << logData.line << " " + << "]" + << " " << std::filesystem::path(logData.file).filename().string() << ":" << logData.line << " " << logData.message << c_colorEnd << std::endl; } @@ -365,11 +406,12 @@ bool SetEnv(const std::string& varName, const std::string& value) #endif } -Result GetLatestDownloadInfo(const SFSClient& sfsClient, const Settings& settings) +Result GetLatestDownloadInfo(const SFSClient& sfsClient, const Settings& settings, json& out) { PrintLog("Getting latest download info for product: " + settings.product); RequestParams params; params.productRequests = {{settings.product, {}}}; + if (settings.isApp) { std::vector<AppContent> appContents; @@ -381,14 +423,12 @@ Result GetLatestDownloadInfo(const SFSClient& sfsClient, const Settings& setting return result.GetCode(); } - // Display results - DisplayResults(appContents); + out = AppContentsToJson(appContents); } else { std::vector<Content> contents; auto result = sfsClient.GetLatestDownloadInfo(params, contents); - if (!result) { PrintError("Failed to get latest download info."); @@ -396,8 +436,33 @@ Result GetLatestDownloadInfo(const SFSClient& sfsClient, const Settings& setting return result.GetCode(); } - // Display results + out = ContentsToJson(contents); + } + + if (out.empty()) + { + PrintError("No results found."); + return Result::Unexpected; + } + + return Result::Success; +} + +Result HandleJSONContents(const Settings& settings, const json& contents) +{ + if (settings.ShouldOutputToFile()) + { + auto result = JSONToFile(contents, settings.outputFile); + if (!result) + { + PrintError("Failed to save to file."); + return result.GetCode(); + } + } + else + { DisplayResults(contents); + return Result::Success; } return Result::Success; @@ -464,7 +529,15 @@ int main(int argc, char* argv[]) } // Perform operations using SFSClient - result = GetLatestDownloadInfo(*sfsClient, settings); + json contents; + result = GetLatestDownloadInfo(*sfsClient, settings, contents); + if (!result) + { + LogResult(result); + return result.GetCode(); + } + + result = HandleJSONContents(settings, contents); if (!result) { LogResult(result); diff --git a/src/SfsClient/sfs-client/scripts/pip.requirements.txt b/src/SfsClient/sfs-client/scripts/pip.requirements.txt @@ -1,2 +1,2 @@ -clang-format==18.1.4 +clang-format==18.1.5 cmake-format==0.6.13 \ No newline at end of file diff --git a/src/SfsClient/sfs-client/vcpkg.json b/src/SfsClient/sfs-client/vcpkg.json @@ -44,7 +44,7 @@ }, { "name": "curl", - "version": "8.4.0" + "version": "8.8.0" }, { "name": "nlohmann-json",