diff --git a/api/schema/v1.json b/api/schema/v1.json index a5315c086..cb6755e0a 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -816,7 +816,28 @@ ], "properties": { "package": { - "$ref": "#/$defs/PackageManager1Package" + "title": "PackageManager1InstallParametersPacakge", + "type": "object", + "required": [ + "id" + ], + "properties": { + "channel": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "string" + }, + "modules": { + "type": "array", + "items": { + "type": "string" + } + } + } }, "options": { "$ref": "#/$defs/CommonOptions" diff --git a/api/schema/v1.yaml b/api/schema/v1.yaml index 7daeb5e3e..bfef0c237 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -644,7 +644,21 @@ $defs: - options properties: package: - $ref: '#/$defs/PackageManager1Package' + title: PackageManager1InstallParametersPacakge + type: object + required: + - id + properties: + channel: + type: string + id: + type: string + version: + type: string + modules: + type: array + items: + type: string options: $ref: '#/$defs/CommonOptions' PackageManager1PackageTaskResult: diff --git a/libs/api/src/linglong/api/types/v1/Generators.hpp b/libs/api/src/linglong/api/types/v1/Generators.hpp index f75c40f2d..868968386 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -35,10 +35,11 @@ #include "linglong/api/types/v1/PackageManager1SearchParameters.hpp" #include "linglong/api/types/v1/PackageManager1RequestInteractionAdditionalMessage.hpp" #include "linglong/api/types/v1/PackageManager1PackageTaskResult.hpp" +#include "linglong/api/types/v1/PackageManager1Package.hpp" #include "linglong/api/types/v1/PackageManager1ModifyRepoParameters.hpp" #include "linglong/api/types/v1/PackageManager1JobInfo.hpp" #include "linglong/api/types/v1/PackageManager1InstallParameters.hpp" -#include "linglong/api/types/v1/PackageManager1Package.hpp" +#include "linglong/api/types/v1/PackageManager1InstallParametersPacakge.hpp" #include "linglong/api/types/v1/PackageManager1GetRepoInfoResult.hpp" #include "linglong/api/types/v1/PackageManager1GetRepoInfoResultRepoInfo.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" @@ -145,8 +146,8 @@ void to_json(json & j, const PackageManager1GetRepoInfoResultRepoInfo & x); void from_json(const json & j, PackageManager1GetRepoInfoResult & x); void to_json(json & j, const PackageManager1GetRepoInfoResult & x); -void from_json(const json & j, PackageManager1Package & x); -void to_json(json & j, const PackageManager1Package & x); +void from_json(const json & j, PackageManager1InstallParametersPacakge & x); +void to_json(json & j, const PackageManager1InstallParametersPacakge & x); void from_json(const json & j, PackageManager1InstallParameters & x); void to_json(json & j, const PackageManager1InstallParameters & x); @@ -157,6 +158,9 @@ void to_json(json & j, const PackageManager1JobInfo & x); void from_json(const json & j, PackageManager1ModifyRepoParameters & x); void to_json(json & j, const PackageManager1ModifyRepoParameters & x); +void from_json(const json & j, PackageManager1Package & x); +void to_json(json & j, const PackageManager1Package & x); + void from_json(const json & j, PackageManager1PackageTaskResult & x); void to_json(json & j, const PackageManager1PackageTaskResult & x); @@ -673,21 +677,21 @@ j["message"] = x.message; j["type"] = x.type; } -inline void from_json(const json & j, PackageManager1Package& x) { +inline void from_json(const json & j, PackageManager1InstallParametersPacakge& x) { x.channel = get_stack_optional(j, "channel"); x.id = j.at("id").get(); -x.packageManager1PackageModule = get_stack_optional(j, "module"); +x.modules = get_stack_optional>(j, "modules"); x.version = get_stack_optional(j, "version"); } -inline void to_json(json & j, const PackageManager1Package & x) { +inline void to_json(json & j, const PackageManager1InstallParametersPacakge & x) { j = json::object(); if (x.channel) { j["channel"] = x.channel; } j["id"] = x.id; -if (x.packageManager1PackageModule) { -j["module"] = x.packageManager1PackageModule; +if (x.modules) { +j["modules"] = x.modules; } if (x.version) { j["version"] = x.version; @@ -696,7 +700,7 @@ j["version"] = x.version; inline void from_json(const json & j, PackageManager1InstallParameters& x) { x.options = j.at("options").get(); -x.package = j.at("package").get(); +x.package = j.at("package").get(); } inline void to_json(json & j, const PackageManager1InstallParameters & x) { @@ -733,6 +737,27 @@ j["defaultRepo"] = x.defaultRepo; j["repos"] = x.repos; } +inline void from_json(const json & j, PackageManager1Package& x) { +x.channel = get_stack_optional(j, "channel"); +x.id = j.at("id").get(); +x.packageManager1PackageModule = get_stack_optional(j, "module"); +x.version = get_stack_optional(j, "version"); +} + +inline void to_json(json & j, const PackageManager1Package & x) { +j = json::object(); +if (x.channel) { +j["channel"] = x.channel; +} +j["id"] = x.id; +if (x.packageManager1PackageModule) { +j["module"] = x.packageManager1PackageModule; +} +if (x.version) { +j["version"] = x.version; +} +} + inline void from_json(const json & j, PackageManager1PackageTaskResult& x) { x.taskObjectPath = get_stack_optional(j, "taskObjectPath"); x.code = j.at("code").get(); diff --git a/libs/api/src/linglong/api/types/v1/PackageManager1InstallParameters.hpp b/libs/api/src/linglong/api/types/v1/PackageManager1InstallParameters.hpp index f0bfa8eac..84620d476 100644 --- a/libs/api/src/linglong/api/types/v1/PackageManager1InstallParameters.hpp +++ b/libs/api/src/linglong/api/types/v1/PackageManager1InstallParameters.hpp @@ -18,7 +18,7 @@ #include "linglong/api/types/v1/helper.hpp" #include "linglong/api/types/v1/CommonOptions.hpp" -#include "linglong/api/types/v1/PackageManager1Package.hpp" +#include "linglong/api/types/v1/PackageManager1InstallParametersPacakge.hpp" namespace linglong { namespace api { @@ -35,7 +35,7 @@ using nlohmann::json; */ struct PackageManager1InstallParameters { CommonOptions options; -PackageManager1Package package; +PackageManager1InstallParametersPacakge package; }; } } diff --git a/libs/api/src/linglong/api/types/v1/PackageManager1InstallParametersPacakge.hpp b/libs/api/src/linglong/api/types/v1/PackageManager1InstallParametersPacakge.hpp new file mode 100644 index 000000000..546376309 --- /dev/null +++ b/libs/api/src/linglong/api/types/v1/PackageManager1InstallParametersPacakge.hpp @@ -0,0 +1,37 @@ +// This file is generated by tools/codegen.sh +// DO NOT EDIT IT. + +// clang-format off + +// To parse this JSON data, first install +// +// json.hpp https://github.com/nlohmann/json +// +// Then include this file, and then do +// +// PackageManager1InstallParametersPacakge.hpp data = nlohmann::json::parse(jsonString); + +#pragma once + +#include +#include +#include "linglong/api/types/v1/helper.hpp" + +namespace linglong { +namespace api { +namespace types { +namespace v1 { +using nlohmann::json; + +struct PackageManager1InstallParametersPacakge { +std::optional channel; +std::string id; +std::optional> modules; +std::optional version; +}; +} +} +} +} + +// clang-format on diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index c65ee6824..a75c41118 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,84 @@ using namespace linglong::utils::error; +namespace { + +static std::vector getAutoModuleList() noexcept +{ + auto getModuleFromLanguageEnv = [](const std::string &lang) -> std::vector { + if (lang.length() < 2) { + return {}; + } + + if (!std::all_of(lang.begin(), lang.begin() + 2, [](char c) { + return 'a' <= c && c <= 'z'; + })) { + return {}; + } + + std::vector modules; + modules.push_back("lang_" + lang.substr(0, 2)); + + if (lang.length() == 2) { + return modules; + } + + if (lang[2] == '.') { + return modules; + } + + if (lang[2] == '@') { + return modules; + } + + if (lang[2] != '_') { + return {}; + } + + if (lang.length() < 5) { + return {}; + } + + modules.push_back("lang_" + lang.substr(0, 5)); + + if (lang.length() == 5) { + return modules; + } + + if (lang[5] == '.') { + return modules; + } + + if (lang[5] == '@') { + return modules; + } + + return {}; + }; + + auto envs = { + "LANG", "LC_ADDRESS", "LC_ALL", "LC_IDENTIFICATION", + "LC_MEASUREMENT", "LC_MESSAGES", "LC_MONETARY", "LC_NAME", + "LC_NUMERIC", "LC_PAPER", "LC_TELEPHONE", "LC_TIME", + }; + + std::vector result = { "binary" }; + + for (const auto &env : envs) { + auto lang = getenv(env); + if (lang == nullptr) { + continue; + } + auto modules = getModuleFromLanguageEnv(lang); + result.insert(result.end(), modules.begin(), modules.end()); + } + + std::sort(result.begin(), result.end()); + return { result.begin(), std::unique(result.begin(), result.end()) }; +} + +} // namespace + namespace linglong::cli { void Cli::onTaskPropertiesChanged(QString interface, // NOLINT @@ -947,7 +1026,14 @@ int Cli::install() } if (!options.module.empty()) { - params.package.packageManager1PackageModule = options.module; + params.package.modules = { options.module }; + } else { + params.package.modules = getAutoModuleList(); + } + + qDebug() << "Install modules"; + for (const auto &module : *params.package.modules) { + qDebug() << module.c_str(); } auto pendingReply = this->pkgMan.Install(utils::serialize::toQVariantMap(params)); diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 01133bf02..e086e2b9a 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -1092,12 +1092,26 @@ auto PackageManager::Install(const QVariantMap ¶meters) noexcept -> QVariant if (!paras) { return toDBusReply(paras); } + + api::types::v1::PackageManager1Package package; + package.id = paras->package.id; + package.channel = paras->package.channel; + package.version = paras->package.version; + // 解析用户输入 - auto fuzzyRef = fuzzyReferenceFromPackage(paras->package); + auto fuzzyRef = fuzzyReferenceFromPackage(package); if (!fuzzyRef) { return toDBusReply(fuzzyRef); } - auto curModule = paras->package.packageManager1PackageModule.value_or("binary"); + + std::string curModule = "binary"; + + if (paras->package.modules && paras->package.modules->size() == 1) { + // Manually install single module + curModule = paras->package.modules->front(); + } + + auto modules = paras->package.modules.value_or(std::vector{ curModule }); // 安装module if (curModule != "binary") { @@ -1207,6 +1221,7 @@ auto PackageManager::Install(const QVariantMap ¶meters) noexcept -> QVariant ? std::make_optional(std::move(localRef).value()) : std::nullopt, curModule, + modules, skipInteraction = paras->options.skipInteraction, msgType, additionalMessage](PackageTask &taskRef) { @@ -1236,11 +1251,11 @@ auto PackageManager::Install(const QVariantMap ¶meters) noexcept -> QVariant if (isTaskDone(taskRef.subState())) { return; } - auto modules = std::vector{ curModule }; - if (localRef.has_value()) { - modules = this->repo.getModuleList(*localRef); - } - this->Install(taskRef, remoteRef, localRef, modules); + + this->Install(taskRef, + remoteRef, + localRef, + localRef.has_value() ? this->repo.getModuleList(*localRef) : modules); }; auto taskRet = tasks.addNewTask({ refSpec }, std::move(installer), connection());