From 5249e615439db701e8b8db83d271b2751063f290 Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 15 May 2025 15:09:52 +0800 Subject: [PATCH 001/366] fix: ll-cli failed to start app Improve error handling for filesystem existence checks. --- .../oci-cfg-generators/20_devices.cpp | 9 +++++- .../oci-cfg-generators/40_host_ipc.cpp | 29 +++++++++++++++++-- .../linglong/oci-cfg-generators/90_legacy.cpp | 11 +++++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp index 998dd7295..aee503957 100755 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp @@ -29,7 +29,14 @@ bool Devices::generate(ocppi::runtime::config::types::Config &config) const noex auto mounts = config.mounts.value_or(std::vector{}); auto bindIfExist = [&mounts](std::string_view source, std::string_view destination) mutable { - if (!std::filesystem::exists(source)) { + std::error_code ec; + if (!std::filesystem::exists(source, ec)) { + if (ec) { + std::cerr << "Failed to check existence of " << source << ": " << ec.message() + << std::endl; + return; + } + return; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp index 2f64c4873..fb1c55924 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp @@ -50,7 +50,15 @@ bool HostIPC::generate(ocppi::runtime::config::types::Config &config) const noex auto env = process.env.value_or(std::vector{}); auto bindIfExist = [&mounts](std::string_view source, std::string_view destination) mutable { - if (!std::filesystem::exists(source)) { + std::error_code ec; + + if (!std::filesystem::exists(source, ec)) { + if (ec) { + std::cerr << "Failed to check existence of " << source << ": " << ec.message() + << std::endl; + return; + } + return; } @@ -93,7 +101,14 @@ bool HostIPC::generate(ocppi::runtime::config::types::Config &config) const noex } auto socketPath = std::filesystem::path(systemBus.substr(suffix.size())); - if (!std::filesystem::exists(socketPath)) { + std::error_code ec; + if (!std::filesystem::exists(socketPath, ec)) { + if (ec) { + std::cerr << "Failed to check existence of " << socketPath << ": " << ec.message() + << std::endl; + return; + } + std::cerr << "D-Bus session bus socket not found at " << socketPath << std::endl; return; } @@ -164,11 +179,19 @@ bool HostIPC::generate(ocppi::runtime::config::types::Config &config) const noex } auto socketPath = std::filesystem::path(hostXDGRuntimeDir) / waylandDisplayEnv; - if (!std::filesystem::exists(socketPath)) { + std::error_code ec; + if (!std::filesystem::exists(socketPath, ec)) { + if (ec) { + std::cerr << "Failed to check existence of " << socketPath << ": " + << ec.message() << std::endl; + return; + } + std::cerr << "Wayland display socket not found at " << socketPath << "." << std::endl; return; } + mounts.emplace_back(ocppi::runtime::config::types::Mount{ .destination = cognitiveXDGRuntimeDir / waylandDisplayEnv, .options = string_list{ "rbind" }, diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp index 7b52aa015..24e020e64 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp @@ -65,8 +65,15 @@ bool Legacy::generate(ocppi::runtime::config::types::Config &config) const noexc { "/etc/resolvconf", "/etc/resolvconf" }, }; + std::error_code ec; for (const auto [source, destination] : roMountMap) { - if (!std::filesystem::exists(source)) { + if (!std::filesystem::exists(source, ec)) { + if (ec) { + std::cerr << "Failed to check existence of " << source << ": " << ec.message() + << std::endl; + continue; + } + std::cerr << source << " not exists on host." << std::endl; continue; } @@ -144,7 +151,7 @@ bool Legacy::generate(ocppi::runtime::config::types::Config &config) const noexc env.push_back("XDG_DATA_DIRS=" + shareDir.string()); } - std::error_code ec; + ec.clear(); // mount for dtk if (std::filesystem::exists("/usr/share/deepin/distribution.info", ec)) { mounts.push_back(ocppi::runtime::config::types::Mount{ From fa65a7be3c14b0a0af1a7a10c0f16c7d10cc1e6d Mon Sep 17 00:00:00 2001 From: dengbo Date: Wed, 14 May 2025 17:13:09 +0800 Subject: [PATCH 002/366] fix: layer file can not install in uos v20 Do not support lzma compressor in uos v20. --- apps/ll-builder/src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index eaf7223fa..e174fdd52 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -282,10 +282,10 @@ int handleExport(linglong::builder::Builder &builder, const ExportCommandOptions if (options.layerMode) { qInfo() << "Exporting as layer file..."; - // layer 默认使用lzma有更高压缩率 + // layer 默认使用lz4, 保持和之前版本的兼容 if (exportOpts.compressor.empty()) { - qInfo() << "Compressor not specified, defaulting to lzma for layer export."; - exportOpts.compressor = "lzma"; + qInfo() << "Compressor not specified, defaulting to lz4 for layer export."; + exportOpts.compressor = "lz4"; } auto result = builder.exportLayer(exportOpts); @@ -789,7 +789,7 @@ You can report bugs to the linyaps team under this project: https://github.com/O buildExport ->add_option("-z, --compressor", exportOpts.exportSpecificOptions.compressor, - "supported compressors are: lz4(uab default), lzam(layer default), zstd") + "supported compressors are: lz4(default), lzma, zstd") ->type_name("X"); auto *iconOpt = buildExport From 642f64365ec6f2e7bea4280471a761b257d6d774 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Thu, 15 May 2025 20:19:23 +0800 Subject: [PATCH 003/366] fix: returns only if creating directories failed std::filesystem::creat_directories does not treated this as an error Signed-off-by: ComixHe --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 4a310eff8..52e47209b 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -717,8 +717,11 @@ utils::error::Result OSTreeRepo::ensureEmptyLayerDir(const std::string &co } if (!std::filesystem::create_directories(dir, ec)) { - return LINGLONG_ERR( - QString{ "failed to create layer dir %1: %2" }.arg(dir.c_str(), ec.message().c_str())); + if (ec) { + return LINGLONG_ERR( + QString{ "failed to create layer dir %1: %2" }.arg(dir.c_str(), + ec.message().c_str())); + } } return QDir{ dir.c_str() }; From 49c6660326ec1f76b67ce753039cd300a1e636b8 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 16 May 2025 11:23:49 +0800 Subject: [PATCH 004/366] feat: add extension schema Signed-off-by: reddevillg --- api/schema/v1.json | 83 +++++++++++++++++++ api/schema/v1.yaml | 55 ++++++++++++ .../api/types/v1/BuilderProjectPackage.hpp | 12 +++ .../linglong/api/types/v1/ExtensionDefine.hpp | 49 +++++++++++ .../linglong/api/types/v1/ExtensionImpl.hpp | 41 +++++++++ .../src/linglong/api/types/v1/Generators.hpp | 68 +++++++++++++++ .../linglong/api/types/v1/LinglongAPIV1.hpp | 4 + .../linglong/api/types/v1/PackageInfoV2.hpp | 7 ++ 8 files changed, 319 insertions(+) create mode 100644 libs/api/src/linglong/api/types/v1/ExtensionDefine.hpp create mode 100644 libs/api/src/linglong/api/types/v1/ExtensionImpl.hpp diff --git a/api/schema/v1.json b/api/schema/v1.json index a4faabb24..784e645c1 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -348,6 +348,24 @@ "channel": { "type": "string", "description": "channel of package" + }, + "extension_of": { + "type": "string", + "description": "extension of whom" + }, + "libs": { + "description": "extra ld search path", + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "description": "Predefined environment variables when the extension is applied", + "type": "object", + "additionalProperties": { + "type": "string" + } } } }, @@ -711,6 +729,16 @@ "compatible_version": { "type": "string", "description": "record linyaps package is compatible with linyaps component version" + }, + "extensions": { + "type": "array", + "description": "description of extension", + "items": { + "$ref": "#/$defs/ExtensionDefine" + } + }, + "ext_impl": { + "$ref": "#/$defs/ExtensionImpl" } } }, @@ -1285,6 +1313,55 @@ } } } + }, + "ExtensionDefine": { + "type": "object", + "required": [ + "name", + "version", + "directory" + ], + "properties": { + "name": { + "description": "extension name", + "type": "string" + }, + "version": { + "description": "extension version", + "type": "string" + }, + "directory": { + "description": "where extension to be mount", + "type": "string" + }, + "allow_env": { + "description": "the environment variables allow extension to modify", + "type": "object", + "additionalProperties": { + "description": "default environment variable", + "type": "string" + } + } + } + }, + "ExtensionImpl": { + "type": "object", + "properties": { + "libs": { + "description": "extra ld search path", + "type": "array", + "items": { + "type": "string" + } + }, + "env": { + "description": "environment variables to set when extension effects", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } } }, "type": "object", @@ -1417,6 +1494,12 @@ }, "ExportDirs": { "$ref": "#/$defs/ExportDirs" + }, + "ExtensionDefine": { + "$ref": "#/$defs/ExtensionDefine" + }, + "ExtensionImpl": { + "$ref": "#/$defs/ExtensionImpl" } } } diff --git a/api/schema/v1.yaml b/api/schema/v1.yaml index 2f73efda8..4176077aa 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -292,6 +292,19 @@ $defs: channel: type: string description: channel of package + extension_of: + type: string + description: extension of whom + libs: + description: extra ld search path + type: array + items: + type: string + env: + description: Predefined environment variables when the extension is applied + type: object + additionalProperties: + type: string permissions: $ref: '#/$defs/ApplicationConfigurationPermissions' runtime: @@ -563,6 +576,13 @@ $defs: compatible_version: type: string description: record linyaps package is compatible with linyaps component version + extensions: + type: array + description: description of extension + items: + $ref: '#/$defs/ExtensionDefine' + ext_impl: + $ref: '#/$defs/ExtensionImpl' PackageInfo: title: PackageInfo description: this is the each item output of ll-cli list --json @@ -986,6 +1006,41 @@ $defs: items: type: string description: path to export + ExtensionDefine: + type: object + required: + - name + - version + - directory + properties: + name: + description: extension name + type: string + version: + description: extension version + type: string + directory: + description: where extension to be mount + type: string + allow_env: + description: the environment variables allow extension to modify + type: object + additionalProperties: + description: default environment variable + type: string + ExtensionImpl: + type: object + properties: + libs: + description: extra ld search path + type: array + items: + type: string + env: + description: environment variables to set when extension effects + type: object + additionalProperties: + type: string type: object properties: # NOTE: "properties" is auto generated by referring all types is $defs diff --git a/libs/api/src/linglong/api/types/v1/BuilderProjectPackage.hpp b/libs/api/src/linglong/api/types/v1/BuilderProjectPackage.hpp index af2f93bdc..0a52e784c 100644 --- a/libs/api/src/linglong/api/types/v1/BuilderProjectPackage.hpp +++ b/libs/api/src/linglong/api/types/v1/BuilderProjectPackage.hpp @@ -44,6 +44,14 @@ std::optional channel; */ std::string description; /** +* Predefined environment variables when the extension is applied +*/ +std::optional> env; +/** +* extension of whom +*/ +std::optional extensionOf; +/** * id of package */ std::string id; @@ -52,6 +60,10 @@ std::string id; */ std::string kind; /** +* extra ld search path +*/ +std::optional> libs; +/** * name of package */ std::string name; diff --git a/libs/api/src/linglong/api/types/v1/ExtensionDefine.hpp b/libs/api/src/linglong/api/types/v1/ExtensionDefine.hpp new file mode 100644 index 000000000..94611b099 --- /dev/null +++ b/libs/api/src/linglong/api/types/v1/ExtensionDefine.hpp @@ -0,0 +1,49 @@ +// 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 +// +// ExtensionDefine.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 ExtensionDefine { +/** +* the environment variables allow extension to modify +*/ +std::optional> allowEnv; +/** +* where extension to be mount +*/ +std::string directory; +/** +* extension name +*/ +std::string name; +/** +* extension version +*/ +std::string version; +}; +} +} +} +} + +// clang-format on diff --git a/libs/api/src/linglong/api/types/v1/ExtensionImpl.hpp b/libs/api/src/linglong/api/types/v1/ExtensionImpl.hpp new file mode 100644 index 000000000..f37ed88d4 --- /dev/null +++ b/libs/api/src/linglong/api/types/v1/ExtensionImpl.hpp @@ -0,0 +1,41 @@ +// 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 +// +// ExtensionImpl.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 ExtensionImpl { +/** +* environment variables to set when extension effects +*/ +std::optional> env; +/** +* extra ld search path +*/ +std::optional> libs; +}; +} +} +} +} + +// clang-format on diff --git a/libs/api/src/linglong/api/types/v1/Generators.hpp b/libs/api/src/linglong/api/types/v1/Generators.hpp index 02de99c59..51c7afb83 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -53,6 +53,8 @@ #include "linglong/api/types/v1/InteractionReply.hpp" #include "linglong/api/types/v1/InteractionMessageType.hpp" #include "linglong/api/types/v1/InspectResult.hpp" +#include "linglong/api/types/v1/ExtensionImpl.hpp" +#include "linglong/api/types/v1/ExtensionDefine.hpp" #include "linglong/api/types/v1/ExportDirs.hpp" #include "linglong/api/types/v1/DialogMessage.hpp" #include "linglong/api/types/v1/DialogHandShakePayload.hpp" @@ -138,6 +140,12 @@ void to_json(json & j, const DialogMessage & x); void from_json(const json & j, ExportDirs & x); void to_json(json & j, const ExportDirs & x); +void from_json(const json & j, ExtensionDefine & x); +void to_json(json & j, const ExtensionDefine & x); + +void from_json(const json & j, ExtensionImpl & x); +void to_json(json & j, const ExtensionImpl & x); + void from_json(const json & j, InspectResult & x); void to_json(json & j, const InspectResult & x); @@ -386,8 +394,11 @@ inline void from_json(const json & j, BuilderProjectPackage& x) { x.architecture = get_stack_optional(j, "architecture"); x.channel = get_stack_optional(j, "channel"); x.description = j.at("description").get(); +x.env = get_stack_optional>(j, "env"); +x.extensionOf = get_stack_optional(j, "extension_of"); x.id = j.at("id").get(); x.kind = j.at("kind").get(); +x.libs = get_stack_optional>(j, "libs"); x.name = j.at("name").get(); x.version = j.at("version").get(); } @@ -401,8 +412,17 @@ if (x.channel) { j["channel"] = x.channel; } j["description"] = x.description; +if (x.env) { +j["env"] = x.env; +} +if (x.extensionOf) { +j["extension_of"] = x.extensionOf; +} j["id"] = x.id; j["kind"] = x.kind; +if (x.libs) { +j["libs"] = x.libs; +} j["name"] = x.name; j["version"] = x.version; } @@ -570,6 +590,38 @@ j = json::object(); j["export-paths"] = x.exportPaths; } +inline void from_json(const json & j, ExtensionDefine& x) { +x.allowEnv = get_stack_optional>(j, "allow_env"); +x.directory = j.at("directory").get(); +x.name = j.at("name").get(); +x.version = j.at("version").get(); +} + +inline void to_json(json & j, const ExtensionDefine & x) { +j = json::object(); +if (x.allowEnv) { +j["allow_env"] = x.allowEnv; +} +j["directory"] = x.directory; +j["name"] = x.name; +j["version"] = x.version; +} + +inline void from_json(const json & j, ExtensionImpl& x) { +x.env = get_stack_optional>(j, "env"); +x.libs = get_stack_optional>(j, "libs"); +} + +inline void to_json(json & j, const ExtensionImpl & x) { +j = json::object(); +if (x.env) { +j["env"] = x.env; +} +if (x.libs) { +j["libs"] = x.libs; +} +} + inline void from_json(const json & j, InspectResult& x) { x.appID = get_stack_optional(j, "appID"); } @@ -685,6 +737,8 @@ x.channel = j.at("channel").get(); x.command = get_stack_optional>(j, "command"); x.compatibleVersion = get_stack_optional(j, "compatible_version"); x.description = get_stack_optional(j, "description"); +x.extImpl = get_stack_optional(j, "ext_impl"); +x.extensions = get_stack_optional>(j, "extensions"); x.id = j.at("id").get(); x.kind = j.at("kind").get(); x.packageInfoV2Module = j.at("module").get(); @@ -711,6 +765,12 @@ j["compatible_version"] = x.compatibleVersion; if (x.description) { j["description"] = x.description; } +if (x.extImpl) { +j["ext_impl"] = x.extImpl; +} +if (x.extensions) { +j["extensions"] = x.extensions; +} j["id"] = x.id; j["kind"] = x.kind; j["module"] = x.packageInfoV2Module; @@ -1100,6 +1160,8 @@ x.containerProcessStateInfo = get_stack_optional(j, " x.dialogHandShakePayload = get_stack_optional(j, "DialogHandShakePayload"); x.dialogMessage = get_stack_optional(j, "DialogMessage"); x.exportDirs = get_stack_optional(j, "ExportDirs"); +x.extensionDefine = get_stack_optional(j, "ExtensionDefine"); +x.extensionImpl = get_stack_optional(j, "ExtensionImpl"); x.inspectResult = get_stack_optional(j, "InspectResult"); x.interactionMessageType = get_stack_optional(j, "InteractionMessageType"); x.interactionReply = get_stack_optional(j, "InteractionReply"); @@ -1171,6 +1233,12 @@ j["DialogMessage"] = x.dialogMessage; if (x.exportDirs) { j["ExportDirs"] = x.exportDirs; } +if (x.extensionDefine) { +j["ExtensionDefine"] = x.extensionDefine; +} +if (x.extensionImpl) { +j["ExtensionImpl"] = x.extensionImpl; +} if (x.inspectResult) { j["InspectResult"] = x.inspectResult; } diff --git a/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp b/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp index f6f45da66..c5b26384c 100644 --- a/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp +++ b/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp @@ -29,6 +29,8 @@ #include "linglong/api/types/v1/DialogHandShakePayload.hpp" #include "linglong/api/types/v1/DialogMessage.hpp" #include "linglong/api/types/v1/ExportDirs.hpp" +#include "linglong/api/types/v1/ExtensionDefine.hpp" +#include "linglong/api/types/v1/ExtensionImpl.hpp" #include "linglong/api/types/v1/InspectResult.hpp" #include "linglong/api/types/v1/InteractionReply.hpp" #include "linglong/api/types/v1/InteractionRequest.hpp" @@ -96,6 +98,8 @@ std::optional containerProcessStateInfo; std::optional dialogHandShakePayload; std::optional dialogMessage; std::optional exportDirs; +std::optional extensionDefine; +std::optional extensionImpl; std::optional inspectResult; std::optional interactionMessageType; std::optional interactionReply; diff --git a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp index 9ae8e1d68..780e947ad 100644 --- a/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp +++ b/libs/api/src/linglong/api/types/v1/PackageInfoV2.hpp @@ -17,6 +17,8 @@ #include #include "linglong/api/types/v1/helper.hpp" +#include "linglong/api/types/v1/ExtensionImpl.hpp" +#include "linglong/api/types/v1/ExtensionDefine.hpp" #include "linglong/api/types/v1/ApplicationConfigurationPermissions.hpp" namespace linglong { @@ -61,6 +63,11 @@ std::optional compatibleVersion; * description of package info */ std::optional description; +std::optional extImpl; +/** +* description of extension +*/ +std::optional> extensions; /** * id of package info */ From 6ee4e1f45d9591cbf580dd4e4f678cd8aedcbe25 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 16 May 2025 13:20:12 +0800 Subject: [PATCH 005/366] feat: add extension interface Signed-off-by: reddevillg --- libs/linglong/CMakeLists.txt | 1 + .../src/linglong/extension/extension.cpp | 60 +++++++++++++++++++ .../src/linglong/extension/extension.h | 49 +++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 libs/linglong/src/linglong/extension/extension.cpp create mode 100644 libs/linglong/src/linglong/extension/extension.h diff --git a/libs/linglong/CMakeLists.txt b/libs/linglong/CMakeLists.txt index 362d813e9..3adf40359 100644 --- a/libs/linglong/CMakeLists.txt +++ b/libs/linglong/CMakeLists.txt @@ -35,6 +35,7 @@ pfl_add_library( src/linglong/cli/printer.h src/linglong/cli/terminal_notifier.cpp src/linglong/cli/terminal_notifier.h + src/linglong/extension/extension.cpp src/linglong/package/architecture.cpp src/linglong/package/architecture.h src/linglong/package/fallback_version.cpp diff --git a/libs/linglong/src/linglong/extension/extension.cpp b/libs/linglong/src/linglong/extension/extension.cpp new file mode 100644 index 000000000..79ef3806f --- /dev/null +++ b/libs/linglong/src/linglong/extension/extension.cpp @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "extension.h" + +#include +#include + +namespace linglong::extension { + +ExtensionIf::~ExtensionIf() { } + +ExtensionIf *ExtensionFactory::makeExtension(const std::string &name) +{ + if (name == ExtensionImplNVIDIADisplayDriver::name) { + return new ExtensionImplNVIDIADisplayDriver(); + } + + return NULL; +} + +std::string ExtensionImplNVIDIADisplayDriver::name = "org.deepin.driver.display.nvidia"; + +ExtensionImplNVIDIADisplayDriver::ExtensionImplNVIDIADisplayDriver() +{ + driverName = hostDriverEnable(); +} + +bool ExtensionImplNVIDIADisplayDriver::shouldEnable(std::string &extensionName) +{ + if (extensionName != name) { + return false; + } + + if (!driverName.empty()) { + extensionName = name + "." + driverName; + return true; + } + + return false; +} + +std::string ExtensionImplNVIDIADisplayDriver::hostDriverEnable() +{ + std::string version; + + std::ifstream versionFile("/sys/module/nvidia/version"); + if (versionFile) { + versionFile >> version; + + std::replace(version.begin(), version.end(), '.', '-'); + } + + return version; +} + +} // namespace linglong::extension diff --git a/libs/linglong/src/linglong/extension/extension.h b/libs/linglong/src/linglong/extension/extension.h new file mode 100644 index 000000000..305419eb6 --- /dev/null +++ b/libs/linglong/src/linglong/extension/extension.h @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#pragma once + +#include + +namespace linglong::extension { + +class ExtensionIf +{ +public: + ExtensionIf() { }; + virtual ~ExtensionIf() = 0; + + virtual bool shouldDownload(std::string &) { return false; } + + virtual bool shouldEnable(std::string &) { return false; } + + virtual bool shouldPrune(std::string &) { return false; } +}; + +class ExtensionFactory +{ +public: + static ExtensionIf *makeExtension(const std::string &name); +}; + +class ExtensionImplNVIDIADisplayDriver : public ExtensionIf +{ +public: + ExtensionImplNVIDIADisplayDriver(); + + ~ExtensionImplNVIDIADisplayDriver() override { } + + bool shouldEnable(std::string &extensionName) override; + + static std::string name; + +private: + std::string hostDriverEnable(); + + std::string driverName; +}; + +} // namespace linglong::extension From 62a34749ec1f90e0e9df73dda9a71ebe7ca299e6 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 16 May 2025 16:27:23 +0800 Subject: [PATCH 006/366] feat: support build extension Introduce RunContext to unify runtime layer resolution, requiring changes across the builder, CLI, and PM. Signed-off-by: reddevillg --- libs/linglong/CMakeLists.txt | 2 + .../src/linglong/builder/linglong_builder.cpp | 604 ++++++------------ .../src/linglong/builder/linglong_builder.h | 9 +- libs/linglong/src/linglong/cli/cli.cpp | 163 +---- .../src/linglong/package/reference.cpp | 32 + .../linglong/src/linglong/package/reference.h | 3 + .../package_manager/package_manager.cpp | 163 +---- .../src/linglong/repo/ostree_repo.cpp | 8 +- libs/linglong/src/linglong/repo/ostree_repo.h | 4 +- .../src/linglong/runtime/container.cpp | 9 +- .../src/linglong/runtime/container_builder.h | 2 +- .../src/linglong/runtime/run_context.cpp | 509 +++++++++++++++ .../src/linglong/runtime/run_context.h | 99 +++ .../container_cfg_builder.cpp | 60 +- .../container_cfg_builder.h | 15 +- 15 files changed, 959 insertions(+), 723 deletions(-) create mode 100644 libs/linglong/src/linglong/runtime/run_context.cpp create mode 100644 libs/linglong/src/linglong/runtime/run_context.h diff --git a/libs/linglong/CMakeLists.txt b/libs/linglong/CMakeLists.txt index 3adf40359..43a8e8f28 100644 --- a/libs/linglong/CMakeLists.txt +++ b/libs/linglong/CMakeLists.txt @@ -79,6 +79,8 @@ pfl_add_library( src/linglong/runtime/container_builder.h src/linglong/runtime/container.cpp src/linglong/runtime/container.h + src/linglong/runtime/run_context.cpp + src/linglong/runtime/run_context.h TESTS ll-tests COMPILE_FEATURES diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 65b1f742b..c0a00ba8b 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -142,31 +142,7 @@ currentReference(const api::types::v1::BuilderProject &project) { LINGLONG_TRACE("get current project reference"); - auto version = package::Version::parse(QString::fromStdString(project.package.version)); - if (!version) { - return LINGLONG_ERR(version); - } - - auto architecture = package::Architecture::currentCPUArchitecture(); - if (project.package.architecture) { - architecture = package::Architecture::parse(*project.package.architecture); - } - if (!architecture) { - return LINGLONG_ERR(architecture); - } - std::string channel = "main"; - if (project.package.channel.has_value()) { - channel = *project.package.channel; - } - auto ref = package::Reference::create(QString::fromStdString(channel), - QString::fromStdString(project.package.id), - *version, - *architecture); - if (!ref) { - return LINGLONG_ERR(ref); - } - - return ref; + return package::Reference::fromBuilderProject(project); } utils::error::Result @@ -447,6 +423,7 @@ Builder::Builder(const api::types::v1::BuilderProject &project, , project(project) , containerBuilder(containerBuilder) , cfg(cfg) + , buildContext(repo) { } @@ -498,13 +475,15 @@ utils::error::Result Builder::buildStagePrepare() noexcept "See https://wikipedia.org/wiki/Reverse_domain_name_notation"; } - if (this->project.package.kind != "runtime") { + if (this->project.package.kind == "app") { if (project.command.value_or(std::vector{}).empty()) { return LINGLONG_ERR("command field is required, please specify!"); } - installPrefix = QString::fromStdString("/opt/apps/" + this->project.package.id + "/files"); - } else { + installPrefix = "/opt/apps/" + this->project.package.id + "/files"; + } else if (this->project.package.kind == "runtime") { installPrefix = "/runtime"; + } else if (this->project.package.kind == "extension") { + installPrefix = "/opt/extensions/" + this->project.package.id; } if (!QFileInfo::exists(LINGLONG_BUILDER_HELPER)) { @@ -634,14 +613,15 @@ utils::error::Result Builder::buildStagePullDependency() noexcept .toStdString(), 2); - auto ref = clearDependency(this->project.base, !this->buildOptions.skipPullDepend, false); - if (!ref) { - return LINGLONG_ERR("base dependency error", ref); + auto baseRef = clearDependency(this->project.base, !this->buildOptions.skipPullDepend, false); + if (!baseRef) { + return LINGLONG_ERR("base dependency error", baseRef); } - baseRef = std::move(ref).value(); + std::optional runtimeRef; if (this->project.runtime) { - ref = clearDependency(*this->project.runtime, !this->buildOptions.skipPullDepend, false); + auto ref = + clearDependency(*this->project.runtime, !this->buildOptions.skipPullDepend, false); if (!ref) { return LINGLONG_ERR("runtime dependency error", ref); } @@ -705,36 +685,6 @@ utils::error::Result Builder::buildStagePullDependency() noexcept return LINGLONG_ERR("failed to merge modules", ret); } - auto layerDir = this->repo.getMergedModuleDir(*baseRef, false); - if (!layerDir) { - return LINGLONG_ERR("failed to get merged base layer", layerDir); - } - baseLayerDir = *layerDir; - - if (runtimeRef) { - layerDir = this->repo.getMergedModuleDir(*runtimeRef, false); - if (!layerDir) { - return LINGLONG_ERR("failed to get merged runtime layer", layerDir); - } - - auto layerItem = this->repo.getLayerItem(*runtimeRef); - if (!layerItem) { - return LINGLONG_ERR("failed to get runtime layer item", layerItem); - } - - auto ref = clearDependency(layerItem->info.base, false, false); - if (!ref || *ref != *baseRef) { - return LINGLONG_ERR( - QString{ "Base is not compatible with runtime. \n" - "- Current base: %1\n" - "- Current runtime: %2\n" - "- Base required by runtime: %3" } - .arg(baseRef->toString(), runtimeRef->toString(), layerItem->info.base.c_str())); - } - - runtimeLayerDir = *layerDir; - } - return LINGLONG_OK; } @@ -768,36 +718,29 @@ utils::error::Result Builder::processBuildDepends() noexcept printMessage("[Processing buildext.apt.buildDepends]"); - auto containerID = runtime::genContainerID(*projectRef); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR("failed to get bundle directory", bundle); - } - linglong::generator::ContainerCfgBuilder cfgBuilder; - cfgBuilder.setAppId(this->project.package.id) + auto fillRes = buildContext.fillContextCfg(cfgBuilder); + if (!fillRes) { + return LINGLONG_ERR(fillRes); + } + cfgBuilder + .setAppId(this->project.package.id) + // overwrite base overlay directory .setBasePath(baseOverlay->mergedDirPath().toStdString(), false) - .setBundlePath(*bundle) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() .bindHostStatics() - .setExtraMounts(std::vector{ - ocppi::runtime::config::types::Mount{ .destination = "/project", - .options = { { "rbind", "ro" } }, - .source = - this->workingDir.absolutePath().toStdString(), - .type = "bind" }, - }) + .addExtraMount(ocppi::runtime::config::types::Mount{ + .destination = "/project", + .options = { { "rbind", "ro" } }, + .source = this->workingDir.absolutePath().toStdString(), + .type = "bind" }) .forwordDefaultEnv(); - if (this->project.package.kind != "runtime") { - cfgBuilder.setAppPath(buildOutput.path().toStdString(), false); - if (runtimeLayerDir) { - cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); - } - } else { - cfgBuilder.setRuntimePath(buildOutput.path().toStdString(), false); + // overwrite runtime overlay directory + if (cfgBuilder.getRuntimePath()) { + cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); } if (!cfgBuilder.build()) { @@ -805,7 +748,9 @@ utils::error::Result Builder::processBuildDepends() noexcept return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } - auto container = this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + auto container = + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(buildContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -840,23 +785,36 @@ utils::error::Result Builder::buildStagePreBuild() noexcept QString overlayPrefix("linglong/overlay"); + auto res = buildContext.resolve(this->project, buildOutput.absolutePath().toStdString()); + if (!res) { + return LINGLONG_ERR(res); + } + + auto baseLayerPath = buildContext.getBaseLayerPath(); + if (!baseLayerPath) { + return LINGLONG_ERR(baseLayerPath); + } // prepare overlayfs - baseOverlay = makeOverlay(baseLayerDir->absoluteFilePath("files"), + baseOverlay = makeOverlay(QString::fromStdString(*baseLayerPath / "files"), this->workingDir.absoluteFilePath(overlayPrefix + "/build_base")); if (!baseOverlay) { return LINGLONG_ERR("failed to mount build base overlayfs"); } - if (runtimeLayerDir) { + if (buildContext.hasRuntime()) { + auto runtimeLayerPath = buildContext.getRuntimeLayerPath(); + if (!runtimeLayerPath) { + return LINGLONG_ERR(runtimeLayerPath); + } runtimeOverlay = - makeOverlay(runtimeLayerDir->absoluteFilePath("files"), + makeOverlay(QString::fromStdString(*runtimeLayerPath / "files"), this->workingDir.absoluteFilePath(overlayPrefix + "/build_runtime")); if (!runtimeOverlay) { return LINGLONG_ERR("failed to mount build runtime overlayfs"); } } - auto res = processBuildDepends(); + res = processBuildDepends(); if (!res) { return LINGLONG_ERR("failed to process buildext", res); } @@ -893,53 +851,17 @@ utils::error::Result Builder::buildStageBuild(const QStringList &args) noe return LINGLONG_ERR("make path " + appCache.absolutePath() + ": failed."); } - // write ld.so.conf - QFile ldsoconf{ appCache.absoluteFilePath("ld.so.conf") }; - if (!ldsoconf.open(QIODevice::WriteOnly)) { - return LINGLONG_ERR(ldsoconf); - } - QString ldRawConf = R"(/runtime/lib -/runtime/lib/@triplet@ -include /runtime/etc/ld.so.conf -/opt/apps/@id@/files/lib -/opt/apps/@id@/files/lib/@triplet@ -include /opt/apps/@id@/files/etc/ld.so.conf)"; - ldRawConf.replace("@id@", QString::fromStdString(this->project.package.id)); - ldRawConf.replace("@triplet@", projectRef->arch.getTriplet()); - ldsoconf.write(ldRawConf.toUtf8()); - // must be closed here, this conf will be used later. - ldsoconf.close(); - - auto containerID = runtime::genContainerID(*projectRef); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR("failed to get bundle directory", bundle); - } - linglong::generator::ContainerCfgBuilder cfgBuilder; + res = buildContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(this->project.package.id) .setBasePath(baseOverlay->mergedDirPath().toStdString(), false) - .setBundlePath(*bundle) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() .bindHostStatics() - .setExtraMounts(std::vector{ - ocppi::runtime::config::types::Mount{ .destination = LINGLONG_BUILDER_HELPER, - .options = { { "rbind", "ro" } }, - .source = LINGLONG_BUILDER_HELPER, - .type = "bind" }, - ocppi::runtime::config::types::Mount{ .destination = "/project", - .options = { { "rbind", "rw" } }, - .source = - this->workingDir.absolutePath().toStdString(), - .type = "bind" }, - ocppi::runtime::config::types::Mount{ - .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", - .options = { { "rbind", "ro" } }, - .source = appCache.absoluteFilePath("ld.so.conf").toStdString(), - .type = "bind" }, - }) .setStartContainerHooks( std::vector{ ocppi::runtime::config::types::Hook{ .path = "/sbin/ldconfig", @@ -954,21 +876,46 @@ include /opt/apps/@id@/files/etc/ld.so.conf)"; cfgBuilder.isolateNetWork(); } - if (this->project.package.kind != "runtime") { - cfgBuilder.setAppPath(buildOutput.path().toStdString(), false); - if (runtimeLayerDir) { - cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); - } - } else { - cfgBuilder.setRuntimePath(buildOutput.path().toStdString(), false); + if (cfgBuilder.getRuntimePath()) { + cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); } + // write ld.so.conf + QString ldConfPath = appCache.absoluteFilePath("ld.so.conf"); + std::string triplet = projectRef->arch.getTriplet().toStdString(); + std::string ldRawConf = cfgBuilder.ldConf(triplet); + + QFile ldsoconf{ ldConfPath }; + if (!ldsoconf.open(QIODevice::WriteOnly)) { + return LINGLONG_ERR(ldsoconf); + } + ldsoconf.write(ldRawConf.c_str()); + // must be closed here, this conf will be used later. + ldsoconf.close(); + + cfgBuilder.addExtraMounts(std::vector{ + ocppi::runtime::config::types::Mount{ .destination = LINGLONG_BUILDER_HELPER, + .options = { { "rbind", "ro" } }, + .source = LINGLONG_BUILDER_HELPER, + .type = "bind" }, + ocppi::runtime::config::types::Mount{ .destination = "/project", + .options = { { "rbind", "rw" } }, + .source = this->workingDir.absolutePath().toStdString(), + .type = "bind" }, + ocppi::runtime::config::types::Mount{ .destination = + "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", + .options = { { "rbind", "ro" } }, + .source = ldConfPath.toStdString(), + .type = "bind" } }); + if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } - auto container = this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + auto container = + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(buildContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -983,8 +930,8 @@ include /opt/apps/@id@/files/etc/ld.so.conf)"; process.args = std::move(arguments); process.cwd = "/project"; process.env = { { - "PREFIX=" + installPrefix.toStdString(), - "TRIPLET=" + projectRef->arch.getTriplet().toStdString(), + "PREFIX=" + installPrefix, + "TRIPLET=" + triplet, } }; process.noNewPrivileges = true; process.terminal = true; @@ -1022,51 +969,49 @@ utils::error::Result Builder::buildStagePreCommit() noexcept QDir(this->workingDir.absoluteFilePath(overlayPrefix + "prepare_runtime")).removeRecursively(); // prepare overlay - baseOverlay = makeOverlay(baseLayerDir->absoluteFilePath("files"), + auto baseLayerPath = buildContext.getBaseLayerPath(); + if (!baseLayerPath) { + return LINGLONG_ERR(baseLayerPath); + } + baseOverlay = makeOverlay(QString::fromStdString(*baseLayerPath / "files"), this->workingDir.absoluteFilePath(overlayPrefix + "/prepare_base")); if (!baseOverlay) { return LINGLONG_ERR("failed to mount prepare base overlayfs"); } - if (runtimeLayerDir) { + if (buildContext.hasRuntime()) { + auto runtimeLayerPath = buildContext.getRuntimeLayerPath(); + if (!runtimeLayerPath) { + return LINGLONG_ERR(runtimeLayerPath); + } runtimeOverlay = - makeOverlay(runtimeLayerDir->absoluteFilePath("files"), + makeOverlay(QString::fromStdString(*runtimeLayerPath / "files"), this->workingDir.absoluteFilePath(overlayPrefix + "/prepare_runtime")); if (!runtimeOverlay) { return LINGLONG_ERR("failed to mount build runtime overlayfs"); } } - auto containerID = runtime::genContainerID(*projectRef); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR("failed to get bundle directory", bundle); - } - linglong::generator::ContainerCfgBuilder cfgBuilder; + auto fillRes = buildContext.fillContextCfg(cfgBuilder); + if (!fillRes) { + return LINGLONG_ERR(fillRes); + } cfgBuilder.setAppId(this->project.package.id) .setBasePath(baseOverlay->mergedDirPath().toStdString(), false) - .setBundlePath(*bundle) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() .bindHostStatics() - .setExtraMounts(std::vector{ - ocppi::runtime::config::types::Mount{ .destination = "/project", - .options = { { "rbind", "rw" } }, - .source = - this->workingDir.absolutePath().toStdString(), - .type = "bind" }, - }) + .addExtraMount(ocppi::runtime::config::types::Mount{ + .destination = "/project", + .options = { { "rbind", "rw" } }, + .source = this->workingDir.absolutePath().toStdString(), + .type = "bind" }) .forwordDefaultEnv(); - if (this->project.package.kind != "runtime") { - cfgBuilder.setAppPath(buildOutput.path().toStdString(), false); - if (runtimeLayerDir) { - cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); - } - } else { - cfgBuilder.setRuntimePath(buildOutput.path().toStdString(), false); + if (cfgBuilder.getRuntimePath()) { + cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); } if (!cfgBuilder.build()) { @@ -1074,7 +1019,9 @@ utils::error::Result Builder::buildStagePreCommit() noexcept return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } - auto container = this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + auto container = + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(buildContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -1093,7 +1040,7 @@ utils::error::Result Builder::buildStagePreCommit() noexcept // 2. merge base and runtime to app, // base prefix is /usr, and runtime prefix is /runtime QList src = { baseOverlay->upperDirPath() + "/usr" }; - if (this->project.package.kind == "app") { + if (this->project.package.kind == "app" || this->project.package.kind == "extension") { src.append(runtimeOverlay->upperDirPath()); } mergeOutput(src, buildOutput, QStringList({ "bin/", "lib/" })); @@ -1103,6 +1050,12 @@ utils::error::Result Builder::buildStagePreCommit() noexcept utils::error::Result Builder::generateAppConf() noexcept { + LINGLONG_TRACE("generate application configure"); + + if (this->project.package.kind != "app") { + return LINGLONG_OK; + } + // generate application's configure file auto scriptFile = QString(LINGLONG_LIBEXEC_DIR) + "/app-conf-generator"; auto useInstalledFile = utils::global::linglongInstalled() && QFile(scriptFile).exists(); @@ -1226,7 +1179,7 @@ utils::error::Result Builder::installFiles() noexcept return LINGLONG_ERR("open file", configFile); } for (auto &line : QString(configFile.readAll()).split('\n')) { - installRules.append(line.replace(installPrefix, "")); + installRules.append(line.replace(installPrefix.c_str(), "")); } // remove empty or duplicate lines installRules.removeAll(""); @@ -1282,7 +1235,7 @@ utils::error::Result Builder::generateEntries() noexcept printMessage(""); - if (this->project.package.kind == "runtime") { + if (this->project.package.kind != "app") { return LINGLONG_OK; } @@ -1381,11 +1334,16 @@ utils::error::Result Builder::commitToLocalRepo() noexcept .version = this->project.package.version, }; - auto fuzzyBase = package::FuzzyReference::parse(QString::fromStdString(this->project.base)); - info.base = baseRef->toString().toStdString(); - if (runtimeRef) { - info.runtime = runtimeRef->toString().toStdString(); + info.base = this->project.base; + if (this->project.runtime) { + info.runtime = this->project.runtime; + } + + if (info.kind == "extension") { + info.extImpl = api::types::v1::ExtensionImpl{ .env = this->project.package.env, + .libs = this->project.package.libs }; } + // 从本地仓库清理旧的ref auto existsModules = this->repo.getModuleList(*projectRef); for (const auto &module : existsModules) { @@ -1831,105 +1789,19 @@ utils::error::Result Builder::run(const QStringList &modules, { LINGLONG_TRACE("run application"); + if (this->project.package.kind != "app") { + return LINGLONG_ERR("only app can run"); + } + auto curRef = currentReference(this->project); if (!curRef) { return LINGLONG_ERR(curRef); } - auto containerID = runtime::genContainerID(*curRef); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR(bundle); - } - - auto baseRef = clearDependency(this->project.base, false, false); - if (!baseRef) { - return LINGLONG_ERR(baseRef); - } - auto baseDir = - debug ? this->repo.getMergedModuleDir(*baseRef) : this->repo.getLayerDir(*baseRef, "binary"); - if (!baseDir) { - return LINGLONG_ERR(baseDir); - } - - utils::error::Result runtimeDir; - if (this->project.runtime) { - auto runtimeRef = clearDependency(this->project.runtime.value(), false, false); - if (!runtimeRef) { - return LINGLONG_ERR(runtimeRef); - } - runtimeDir = debug ? this->repo.getMergedModuleDir(*runtimeRef) - : this->repo.getLayerDir(*runtimeRef, "binary"); - if (!runtimeDir) { - return LINGLONG_ERR(runtimeDir); - } - } - - utils::error::Result curDir; - // mergedDir 会自动在释放时删除临时目录,所以要用变量保留住 - utils::error::Result> mergedDir; - if (modules.size() > 1) { - qDebug() << "create temp merge dir." - << "ref: " << curRef->toString() << "modules: " << modules; - mergedDir = this->repo.getMergedModuleDir(*curRef, modules); - if (!mergedDir.has_value()) { - return LINGLONG_ERR(mergedDir); - } - curDir = **mergedDir; - } else { - curDir = this->repo.getLayerDir(*curRef); - if (!curDir) { - return LINGLONG_ERR(curDir); - } - } - - auto info = curDir->info(); - if (!info) { - return LINGLONG_ERR(info); - } - - if (this->project.package.kind != "app") { - return LINGLONG_ERR("only app can run"); - } - - std::vector applicationMounts{}; - auto bindMount = - [&applicationMounts](const api::types::v1::ApplicationConfigurationPermissionsBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - auto bindInnerMount = - [&applicationMounts, - &bundle](const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bundle->string() + "/rootfs" + bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - - if (info->permissions) { - auto &perm = info->permissions; - if (perm->binds) { - const auto &binds = perm->binds; - std::for_each(binds->cbegin(), binds->cend(), bindMount); - } - - if (perm->innerBinds) { - const auto &innerBinds = perm->innerBinds; - const auto &hostSourceDir = - std::filesystem::path{ curDir->absolutePath().toStdString() }; - std::for_each(innerBinds->cbegin(), innerBinds->cend(), bindInnerMount); - } + runtime::RunContext runContext(this->repo); + auto res = runContext.resolve(*curRef, !debug, modules); + if (!res) { + return LINGLONG_ERR(res); } auto *homeEnv = ::getenv("HOME"); @@ -1938,6 +1810,7 @@ utils::error::Result Builder::run(const QStringList &modules, return LINGLONG_ERR("Couldn't get HOME or USER from env."); } + std::vector applicationMounts{}; if (debug) { std::filesystem::path workdir = this->workingDir.absolutePath().toStdString(); // 生成 host_gdbinit 可使用 gdb --init-command=linglong/host_gdbinit 从宿主机调试 @@ -1994,25 +1867,17 @@ utils::error::Result Builder::run(const QStringList &modules, { // Since ldconfig removes and regenerates the cache file, the cache directory must be // writable. Therefore, we must generate the ld cache in a separate running - auto containerID = runtime::genContainerID(*curRef); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR(bundle); - } - linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(curRef->id.toStdString()) - .setAppPath(curDir->absoluteFilePath("files").toStdString()) - .setBasePath(baseDir->absoluteFilePath("files").toStdString()) .setAppCache(appCache.absolutePath().toStdString(), false) - .setBundlePath(std::move(bundle).value()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .setExtraMounts(applicationMounts); - if (this->project.runtime) { - cfgBuilder.setRuntimePath(runtimeDir->absoluteFilePath("files").toStdString()); - } + .addExtraMounts(applicationMounts); if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); @@ -2020,7 +1885,8 @@ utils::error::Result Builder::run(const QStringList &modules, } auto container = - this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(buildContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -2037,12 +1903,13 @@ utils::error::Result Builder::run(const QStringList &modules, } linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(curRef->id.toStdString()) - .setAppPath(curDir->absoluteFilePath("files").toStdString()) - .setBasePath(baseDir->absoluteFilePath("files").toStdString()) .setAppCache(appCache.absolutePath().toStdString()) .enableLDCache() - .setBundlePath(std::move(bundle).value()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() @@ -2059,11 +1926,8 @@ utils::error::Result Builder::run(const QStringList &modules, .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) .bindIPC() .forwordDefaultEnv() - .setExtraMounts(applicationMounts) + .addExtraMounts(applicationMounts) .enableSelfAdjustingMount(); - if (this->project.runtime) { - cfgBuilder.setRuntimePath(runtimeDir->absoluteFilePath("files").toStdString()); - } #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); #endif @@ -2073,7 +1937,9 @@ utils::error::Result Builder::run(const QStringList &modules, return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } - auto container = this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + auto container = + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(runContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); @@ -2107,39 +1973,10 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, { LINGLONG_TRACE("run with ref " + ref.toString()); - auto appLayerDir = this->repo.getMergedModuleDir(ref); - if (!appLayerDir) { - return LINGLONG_ERR("failed to get layer dir of " + ref.toString()); - } - - auto layerItem = this->repo.getLayerItem(ref); - if (!layerItem) { - return LINGLONG_ERR("failed to get layer item of " + ref.toString()); - } - const auto &info = layerItem->info; - - // only clear ref from local - auto baseRef = clearDependency(info.base, false, false); - if (!baseRef) { - return LINGLONG_ERR("base not exist: " + QString::fromStdString(info.base)); - } - auto baseLayerDir = this->repo.getMergedModuleDir(*baseRef); - if (!baseLayerDir) { - return LINGLONG_ERR(baseLayerDir); - } - - std::optional runtimeLayerDir; - if (info.runtime) { - auto runtimeRef = clearDependency(info.runtime.value(), false, false); - if (!runtimeRef) { - return LINGLONG_ERR("runtime not exist: " - + QString::fromStdString(info.runtime.value())); - } - auto layerDir = this->repo.getMergedModuleDir(*runtimeRef); - if (!layerDir) { - return LINGLONG_ERR(layerDir); - } - runtimeLayerDir = std::move(layerDir).value(); + runtime::RunContext runContext(this->repo); + auto res = runContext.resolve(ref); + if (!res) { + return LINGLONG_ERR(res); } uid = getuid(); @@ -2153,54 +1990,36 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, } { - // write ld.so.conf - QFile ldsoconf{ (appCache / "ld.so.conf").c_str() }; - if (!ldsoconf.open(QIODevice::WriteOnly)) { - return LINGLONG_ERR(ldsoconf); - } - - std::string ldRawConf; - std::string triplet = ref.arch.getTriplet().toStdString(); - auto appendLdConf = [&ldRawConf, &triplet](const std::string &prefix) { - ldRawConf.append(prefix + "/lib\n"); - ldRawConf.append(prefix + "/lib/" + triplet); - ldRawConf.append("\ninclude " + prefix + "/etc/ld.so.conf"); - }; - - if (runtimeLayerDir) { - appendLdConf("/runtime"); - } - appendLdConf("/opt/apps/" + ref.id.toStdString() + "/files"); - - ldsoconf.write(ldRawConf.c_str()); - // must be closed here, this conf will be used later. - ldsoconf.close(); - // generate ld cache - auto containerID = runtime::genContainerID(ref); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR(bundle); - } + std::string ldConfPath = appCache / "ld.so.conf"; linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(ref.id.toStdString()) - .setAppPath(appLayerDir->absoluteFilePath("files").toStdString()) - .setBasePath(baseLayerDir->absoluteFilePath("files").toStdString()) .setAppCache(appCache, false) - .setBundlePath(std::move(bundle).value()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .setExtraMounts( - std::vector{ ocppi::runtime::config::types::Mount{ - .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", - .options = { { "rbind", "ro" } }, - .source = appCache / "ld.so.conf", - .type = "bind" } }); - if (info.runtime) { - cfgBuilder.setRuntimePath(runtimeLayerDir->absoluteFilePath("files").toStdString()); + .addExtraMount(ocppi::runtime::config::types::Mount{ + .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", + .options = { { "rbind", "ro" } }, + .source = ldConfPath, + .type = "bind" }); + + // write ld.so.conf + std::string triplet = ref.arch.getTriplet().toStdString(); + std::string ldRawConf = cfgBuilder.ldConf(triplet); + + QFile ldsoconf{ ldConfPath.c_str() }; + if (!ldsoconf.open(QIODevice::WriteOnly)) { + return LINGLONG_ERR(ldsoconf); } + ldsoconf.write(ldRawConf.c_str()); + // must be closed here, this conf will be used later. + ldsoconf.close(); if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); @@ -2208,7 +2027,8 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, } auto container = - this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(runContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -2224,33 +2044,23 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, } } - auto newContainerID = runtime::genContainerID(ref); - auto bundle = runtime::getBundleDir(newContainerID); - if (!bundle) { - return LINGLONG_ERR(bundle); - } - linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(ref.id.toStdString()) - .setAppPath(appLayerDir->absoluteFilePath("files").toStdString()) - .setBasePath(baseLayerDir->absoluteFilePath("files").toStdString()) - .setBundlePath(std::move(bundle).value()) .setAppCache(appCache) .enableLDCache() .bindDefault() .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) - .setExtraMounts(std::vector{ - ocppi::runtime::config::types::Mount{ .destination = "/project", - .options = { { "rbind", "rw" } }, - .source = - this->workingDir.absolutePath().toStdString(), - .type = "bind" }, - }) + .addExtraMount(ocppi::runtime::config::types::Mount{ + .destination = "/project", + .options = { { "rbind", "rw" } }, + .source = this->workingDir.absolutePath().toStdString(), + .type = "bind" }) .enableSelfAdjustingMount(); - if (info.runtime) { - cfgBuilder.setRuntimePath(runtimeLayerDir->absoluteFilePath("files").toStdString()); - } if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); @@ -2258,7 +2068,8 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, } auto container = - this->containerBuilder.create(cfgBuilder, QString::fromStdString(newContainerID)); + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(runContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -2452,37 +2263,6 @@ void Builder::takeTerminalForeground() } } -void Builder::patchBuildPhaseConfig(ocppi::runtime::config::types::Config &config) -{ - if (config.mounts) { - auto &mounts = config.mounts.value(); - for (auto it = mounts.begin(); it != mounts.end();) { - bool is_ro = false; - std::vector::iterator ro{}; - if (it->options) { - auto &options = it->options.value(); - ro = std::find_if(options.begin(), options.end(), [](std::string &option) { - return option == "ro"; - }); - is_ro = (ro != options.end()); - } - - if (it->destination == "/runtime") { - if (is_ro) { - *ro = "rw"; - } - } else if (it->destination.find(LINGLONG_BUILDER_HELPER) == 0) { - } else if (it->destination == "/etc/ld.so.cache" - || (is_ro && it->source.has_value() - && it->source.value() == it->destination)) { - it = mounts.erase(it); - continue; - } - ++it; - } - } -} - void Builder::mergeOutput(const QList &src, const QDir &dest, const QStringList &targets) { QMap copys; diff --git a/libs/linglong/src/linglong/builder/linglong_builder.h b/libs/linglong/src/linglong/builder/linglong_builder.h index d40390f4e..25dcacd2c 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.h +++ b/libs/linglong/src/linglong/builder/linglong_builder.h @@ -10,6 +10,7 @@ #include "linglong/api/types/v1/BuilderProject.hpp" #include "linglong/repo/ostree_repo.h" #include "linglong/runtime/container_builder.h" +#include "linglong/runtime/run_context.h" #include "linglong/utils/error/error.h" #include "linglong/utils/overlayfs.h" @@ -110,7 +111,6 @@ class Builder auto generateBuildDependsScript() noexcept -> utils::error::Result; auto generateDependsScript() noexcept -> utils::error::Result; void takeTerminalForeground(); - void patchBuildPhaseConfig(ocppi::runtime::config::types::Config &config); void mergeOutput(const QList &src, const QDir &dest, const QStringList &target); void printBasicInfo(); void printRepo(); @@ -128,14 +128,11 @@ class Builder std::optional projectRef; QStringList packageModules; - std::optional baseRef; - std::optional baseLayerDir; - std::optional runtimeRef; - std::optional runtimeLayerDir; std::unique_ptr baseOverlay; std::unique_ptr runtimeOverlay; QDir buildOutput; - QString installPrefix; + std::string installPrefix; + runtime::RunContext buildContext; }; } // namespace linglong::builder diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 777224806..1f6c24c4c 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -26,6 +26,7 @@ #include "linglong/package/layer_file.h" #include "linglong/package/reference.h" #include "linglong/runtime/container_builder.h" +#include "linglong/runtime/run_context.h" #include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" @@ -572,16 +573,15 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) this->printer.printErr(curAppRef.error()); return -1; } - auto appLayerDir = this->repository.getMergedModuleDir(*curAppRef); - if (!appLayerDir) { - this->printer.printErr(appLayerDir.error()); - return -1; + + runtime::RunContext runContext(this->repository); + auto res = runContext.resolve(*curAppRef); + if (!res) { + this->printer.printErr(res.error()); } - // Note: we should use the info.json which from states.json instead of layer dir - const auto &appLayerItem = this->repository.getLayerItem(*curAppRef); + const auto &appLayerItem = runContext.getCachedAppItem(); if (!appLayerItem) { - this->printer.printErr(appLayerItem.error()); return -1; } const auto &info = appLayerItem->info; @@ -591,78 +591,6 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) qWarning() << ret.error().message(); } - std::optional runtimeLayerRef; - std::optional runtimeLayerDir; - if (info.runtime) { - auto runtimeFuzzyRef = - package::FuzzyReference::parse(QString::fromStdString(info.runtime.value())); - if (!runtimeFuzzyRef) { - this->printer.printErr(runtimeFuzzyRef.error()); - return -1; - } - - auto runtimeRefRet = this->repository.clearReference(*runtimeFuzzyRef, - { - .forceRemote = false, - .fallbackToRemote = false, - .semanticMatching = true, - }); - if (!runtimeRefRet) { - this->printer.printErr(runtimeRefRet.error()); - return -1; - } - const auto &runtimeRef = *runtimeRefRet; - - if (!info.uuid.has_value()) { - auto runtimeLayerDirRet = this->repository.getMergedModuleDir(runtimeRef); - if (!runtimeLayerDirRet) { - this->printer.printErr(runtimeLayerDirRet.error()); - return -1; - } - runtimeLayerDir = std::move(runtimeLayerDirRet).value(); - } else { - auto runtimeLayerDirRet = - this->repository.getLayerDir(*runtimeRefRet, "binary", info.uuid); - if (!runtimeLayerDirRet) { - this->printer.printErr(runtimeLayerDirRet.error()); - return -1; - } - runtimeLayerRef = runtimeRefRet->toString().toStdString(); - runtimeLayerDir = std::move(runtimeLayerDirRet).value(); - } - } - - auto baseFuzzyRef = package::FuzzyReference::parse(QString::fromStdString(info.base)); - if (!baseFuzzyRef) { - this->printer.printErr(baseFuzzyRef.error()); - return -1; - } - - auto baseRef = this->repository.clearReference(*baseFuzzyRef, - { - .forceRemote = false, - .fallbackToRemote = false, - .semanticMatching = true, - }); - if (!baseRef) { - this->printer.printErr(LINGLONG_ERRV(baseRef)); - return -1; - } - - utils::error::Result baseLayerDir; - if (!info.uuid.has_value()) { - qDebug() << "getMergedModuleDir base"; - baseLayerDir = this->repository.getMergedModuleDir(*baseRef); - } else { - qDebug() << "getLayerDir base" << info.uuid.value().c_str(); - baseLayerDir = this->repository.getLayerDir(*baseRef, "binary", info.uuid); - } - - if (!baseLayerDir) { - this->printer.printErr(LINGLONG_ERRV(baseLayerDir)); - return -1; - } - auto appCache = this->ensureCache(*curAppRef, *appLayerItem); if (!appCache) { this->printer.printErr(LINGLONG_ERRV(appCache)); @@ -675,21 +603,9 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) } commands = filePathMapping(commands); - auto newContainerID = runtime::genContainerID(*curAppRef); - auto bundle = runtime::getBundleDir(newContainerID); - if (!bundle) { - this->printer.printErr(LINGLONG_ERRV(bundle)); - return -1; - } - // this lambda will dump reference of containerID, app, base and runtime to // /run/linglong/getuid()/getpid() to store these needed infomation - auto dumpContainerInfo = [app = curAppRef->toString().toStdString(), - base = baseRef->toString().toStdString(), - &newContainerID, - &runtimeLayerRef, - uid, - this]() -> bool { + auto dumpContainerInfo = [uid, &runContext, this]() -> bool { LINGLONG_TRACE("dump info") std::error_code ec; auto pidFile = std::filesystem::path{ "/run/linglong" } / std::to_string(uid) @@ -711,12 +627,7 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) this->printer.printErr(LINGLONG_ERRV(msg)); return false; } - stream << nlohmann::json(linglong::api::types::v1::ContainerProcessStateInfo{ - .app = app, - .base = base, - .containerID = newContainerID, - .runtime = runtimeLayerRef, - }); + stream << nlohmann::json(runContext.stateInfo()); stream.close(); return true; @@ -776,47 +687,6 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) return 0; } - std::vector applicationMounts{}; - auto bindMount = - [&applicationMounts](const api::types::v1::ApplicationConfigurationPermissionsBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - - auto bindInnerMount = - [&applicationMounts, - &bundle](const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bundle->string() + "/rootfs" + bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - - if (info.permissions) { - const auto &perm = info.permissions; - if (perm->binds) { - const auto &binds = perm->binds; - std::for_each(binds->cbegin(), binds->cend(), bindMount); - } - - if (perm->innerBinds) { - const auto &innerBinds = perm->innerBinds; - const auto &hostSourceDir = - std::filesystem::path{ appLayerDir->absolutePath().toStdString() }; - std::for_each(innerBinds->cbegin(), innerBinds->cend(), bindInnerMount); - } - } - auto *homeEnv = ::getenv("HOME"); auto *userNameEnv = ::getenv("USER"); if (homeEnv == nullptr || userNameEnv == nullptr) { @@ -825,12 +695,14 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) } linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + this->printer.printErr(res.error()); + return -1; + } cfgBuilder.setAppId(curAppRef->id.toStdString()) - .setAppPath(appLayerDir->absoluteFilePath("files").toStdString()) - .setBasePath(baseLayerDir->absoluteFilePath("files").toStdString()) .setAppCache(*appCache) .enableLDCache() - .setBundlePath(std::move(bundle).value()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() @@ -847,11 +719,7 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) .bindIPC() .forwordDefaultEnv() - .setExtraMounts(applicationMounts) .enableSelfAdjustingMount(); - if (info.runtime) { - cfgBuilder.setRuntimePath(runtimeLayerDir->absoluteFilePath("files").toStdString()); - } #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); #endif @@ -863,7 +731,8 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) } auto container = - this->containerBuilder.create(cfgBuilder, QString::fromStdString(newContainerID)); + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(runContext.getContainerId())); if (!container) { this->printer.printErr(container.error()); diff --git a/libs/linglong/src/linglong/package/reference.cpp b/libs/linglong/src/linglong/package/reference.cpp index 4f938febf..400f82163 100644 --- a/libs/linglong/src/linglong/package/reference.cpp +++ b/libs/linglong/src/linglong/package/reference.cpp @@ -173,4 +173,36 @@ utils::error::Result Reference::fromVariantMap(const QVariantMap &dat return *reference; } +utils::error::Result +Reference::fromBuilderProject(const api::types::v1::BuilderProject &project) noexcept +{ + LINGLONG_TRACE("parse reference from BuilderProject"); + + auto version = package::Version::parse(QString::fromStdString(project.package.version)); + if (!version) { + return LINGLONG_ERR(version); + } + + auto architecture = package::Architecture::currentCPUArchitecture(); + if (project.package.architecture) { + architecture = package::Architecture::parse(*project.package.architecture); + } + if (!architecture) { + return LINGLONG_ERR(architecture); + } + std::string channel = "main"; + if (project.package.channel.has_value()) { + channel = *project.package.channel; + } + auto ref = package::Reference::create(QString::fromStdString(channel), + QString::fromStdString(project.package.id), + *version, + *architecture); + if (!ref) { + return LINGLONG_ERR(ref); + } + + return ref; +} + } // namespace linglong::package diff --git a/libs/linglong/src/linglong/package/reference.h b/libs/linglong/src/linglong/package/reference.h index c796e482c..1353f0721 100644 --- a/libs/linglong/src/linglong/package/reference.h +++ b/libs/linglong/src/linglong/package/reference.h @@ -6,6 +6,7 @@ #pragma once +#include "linglong/api/types/v1/BuilderProject.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" #include "linglong/api/types/v1/Repo.hpp" #include "linglong/package/architecture.h" @@ -28,6 +29,8 @@ class Reference final fromPackageInfo(const api::types::v1::PackageInfoV2 &info) noexcept; static QVariantMap toVariantMap(const Reference &ref) noexcept; static utils::error::Result fromVariantMap(const QVariantMap &data) noexcept; + static utils::error::Result + fromBuilderProject(const api::types::v1::BuilderProject &project) noexcept; QString channel; QString id; diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index b200bf8fd..49a190d1b 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -20,6 +20,7 @@ #include "linglong/package_manager/package_task.h" #include "linglong/repo/config.h" #include "linglong/repo/ostree_repo.h" +#include "linglong/runtime/run_context.h" #include "linglong/utils/command/env.h" #include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" @@ -2183,91 +2184,6 @@ void PackageManager::ReplyInteraction([[maybe_unused]] QDBusObjectPath object_pa Q_EMIT this->ReplyReceived(replies); } -utils::error::Result prepareLayerDir(const repo::OSTreeRepo &repo, - const package::Reference &ref, - package::LayerDir &appLayerDir, - std::optional &runtimeLayerDir, - package::LayerDir &baseLayerDir) -{ - LINGLONG_TRACE("prepare layer dir before running"); - auto appLayerDirRet = repo.getMergedModuleDir(ref); - if (!appLayerDirRet) { - return LINGLONG_ERR(appLayerDirRet); - } - appLayerDir = std::move(appLayerDirRet).value(); - - auto info = appLayerDir.info(); - if (!info) { - return LINGLONG_ERR(info); - } - if (info->runtime) { - auto runtimeFuzzyRef = - package::FuzzyReference::parse(QString::fromStdString(*info->runtime)); - if (!runtimeFuzzyRef) { - return LINGLONG_ERR(runtimeFuzzyRef); - } - - auto runtimeRefRet = repo.clearReference(*runtimeFuzzyRef, - { - .forceRemote = false, - .fallbackToRemote = false, - .semanticMatching = true, - }); - if (!runtimeRefRet) { - return LINGLONG_ERR(runtimeRefRet); - } - auto &runtimeRef = *runtimeRefRet; - - if (!info->uuid.has_value()) { - auto runtimeLayerDirRet = repo.getMergedModuleDir(runtimeRef); - if (!runtimeLayerDirRet) { - return LINGLONG_ERR(runtimeLayerDirRet); - } - runtimeLayerDir = std::make_optional(std::move(runtimeLayerDirRet).value()); - } else { - auto runtimeLayerDirRet = - repo.getLayerDir(*runtimeRefRet, std::string{ "binary" }, info->uuid); - if (!runtimeLayerDirRet) { - return LINGLONG_ERR(runtimeLayerDirRet); - } - runtimeLayerDir = std::make_optional(std::move(runtimeLayerDirRet).value()); - } - } - - auto baseFuzzyRef = package::FuzzyReference::parse(QString::fromStdString(info->base)); - if (!baseFuzzyRef) { - return LINGLONG_ERR(baseFuzzyRef); - } - - auto baseRef = repo.clearReference(*baseFuzzyRef, - { - .forceRemote = false, - .fallbackToRemote = false, - .semanticMatching = true, - }); - if (!baseRef) { - return LINGLONG_ERR(baseRef); - } - - if (!info->uuid.has_value()) { - qDebug() << "getMergedModuleDir base"; - auto baseLayerDirRet = repo.getMergedModuleDir(*baseRef); - if (!baseLayerDirRet) { - return LINGLONG_ERR(baseLayerDirRet); - } - baseLayerDir = std::move(baseLayerDirRet).value(); - } else { - qDebug() << "getLayerDir base" << info->uuid.value().c_str(); - auto baseLayerDirRet = repo.getLayerDir(*baseRef, std::string{ "binary" }, info->uuid); - if (!baseLayerDirRet) { - return LINGLONG_ERR(baseLayerDirRet); - } - baseLayerDir = std::move(baseLayerDirRet).value(); - } - - return LINGLONG_OK; -} - utils::error::Result PackageManager::generateCache(const package::Reference &ref) noexcept { LINGLONG_TRACE("generate cache for " + ref.toString()); @@ -2280,7 +2196,6 @@ utils::error::Result PackageManager::generateCache(const package::Referenc const auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / layerItem->commit; const std::string appCacheDest = "/run/linglong/cache"; const std::string generatorDest = "/run/linglong/generator"; - const std::string ldGenerator = generatorDest + "/ld-cache-generator"; utils::Transaction transaction; @@ -2301,52 +2216,24 @@ utils::error::Result PackageManager::generateCache(const package::Referenc } }); - auto containerID = runtime::genContainerID(ref); - auto bundle = runtime::getBundleDir(containerID); - if (!bundle) { - return LINGLONG_ERR(bundle); + runtime::RunContext runContext(this->repo); + auto res = runContext.resolve(ref); + if (!res) { + return LINGLONG_ERR(res); } - // generate ld config - { - std::ofstream ofs(*bundle / "zz_deepin-linglong-app.ld.so.conf"); - Q_ASSERT(ofs.is_open()); - if (!ofs.is_open()) { - return LINGLONG_ERR("create ld config in bundle directory"); - } - ofs << "include /run/linglong/cache/ld.so.conf" << std::endl; - } - - package::LayerDir appLayerDir; - std::optional runtimeLayerDir; - package::LayerDir baseLayerDir; - - auto ret = prepareLayerDir(this->repo, ref, appLayerDir, runtimeLayerDir, baseLayerDir); - if (!ret) { - return LINGLONG_ERR(ret); - } - - auto putEnvRet = qputenv("LINGLONG_SKIP_HOME_GENERATE", "1"); - if (!putEnvRet) { - qWarning() << "failed to set env LINGLONG_SKIP_HOME_GENERATE"; - } - - auto unsetEnv = utils::finally::finally([] { - auto ret = qunsetenv("LINGLONG_SKIP_HOME_GENERATE"); - if (!ret) { - qWarning() << "failed to unset env LINGLONG_SKIP_HOME_GENERATE"; - } - }); - int64_t uid = getuid(); int64_t gid = getgid(); + std::filesystem::path ldConfPath{ appCache / "ld.so.conf" }; + linglong::generator::ContainerCfgBuilder cfgBuilder; + res = runContext.fillContextCfg(cfgBuilder); + if (!res) { + return LINGLONG_ERR(res); + } cfgBuilder.setAppId(ref.id.toStdString()) - .setAppPath(appLayerDir.absoluteFilePath("files").toStdString()) - .setBasePath(baseLayerDir.absoluteFilePath("files").toStdString()) .setAppCache(appCache, false) - .setBundlePath(*bundle) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() @@ -2354,7 +2241,7 @@ utils::error::Result PackageManager::generateCache(const package::Referenc .bindRun() .bindUserGroup() .forwordDefaultEnv() - .setExtraMounts(std::vector{ + .addExtraMounts(std::vector{ ocppi::runtime::config::types::Mount{ .destination = generatorDest, .options = { { "rbind", "ro" } }, .source = LINGLONG_LIBEXEC_DIR, @@ -2362,24 +2249,32 @@ utils::error::Result PackageManager::generateCache(const package::Referenc ocppi::runtime::config::types::Mount{ .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", .options = { { "rbind", "ro" } }, - .source = *bundle / "zz_deepin-linglong-app.ld.so.conf", + .source = ldConfPath, .type = "bind", } }) .enableSelfAdjustingMount(); - - if (runtimeLayerDir) { - cfgBuilder.setRuntimePath(runtimeLayerDir->absoluteFilePath("files").toStdString()); - } #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); #endif + // generate ld config + { + std::ofstream ofs(ldConfPath); + Q_ASSERT(ofs.is_open()); + if (!ofs.is_open()) { + return LINGLONG_ERR("create ld config in bundle directory"); + } + ofs << cfgBuilder.ldConf(ref.arch.getTriplet().toStdString()) << std::endl; + } + if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } - auto container = this->containerBuilder.create(cfgBuilder, QString::fromStdString(containerID)); + auto container = + this->containerBuilder.create(cfgBuilder, + QString::fromStdString(runContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } @@ -2393,11 +2288,9 @@ utils::error::Result PackageManager::generateCache(const package::Referenc if (!currentArch) { return LINGLONG_ERR(currentArch); } - // Usage: ld-cache-generator [cacheRoot] [id] [gnu_arch_triplet] - // font-cache-generator [cacheRoot] [id] - const auto ldGenerateCmd = ldGenerator + " " + appCacheDest + " " + ref.id.toStdString() + " " - + currentArch->getTriplet().toStdString(); + const auto ldGenerateCmd = "/sbin/ldconfig -C " + appCacheDest + "/ld.so.cache"; #ifdef LINGLONG_FONT_CACHE_GENERATOR + // Usage: font-cache-generator [cacheRoot] [id] const std::string fontGenerateCmd = fontGenerator + " " + appCacheDest + " " + ref.id.toStdString(); process.args = std::vector{ "bash", "-c", ldGenerateCmd + ";" + fontGenerateCmd }; diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 52e47209b..7cf8f51fb 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -2532,7 +2532,7 @@ utils::error::Result OSTreeRepo::getMergedModuleDir( return LINGLONG_ERR("merged doesn't exist"); } -utils::error::Result> OSTreeRepo::getMergedModuleDir( +utils::error::Result OSTreeRepo::getMergedModuleDir( const package::Reference &ref, const QStringList &loadModules) const noexcept { LINGLONG_TRACE("merge modules"); @@ -2588,11 +2588,7 @@ utils::error::Result> OSTreeRepo::getMergedMo return LINGLONG_ERR(QString("ostree_repo_checkout_at %1").arg(mergeTmp), gErr); } } - auto *ptr = new package::LayerDir(mergeTmp); - return std::shared_ptr(ptr, [](package::LayerDir *ptr) { - ptr->removeRecursively(); - delete ptr; - }); + return mergeTmp; } utils::error::Result OSTreeRepo::mergeModules() const noexcept diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index b7c784e0d..337ced2b2 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -130,8 +130,8 @@ class OSTreeRepo : public QObject [[nodiscard]] utils::error::Result getMergedModuleDir(const package::Reference &ref, bool fallbackLayerDir = true) const noexcept; // 将指定的modules合并到临时目录,并返回合并后的layerDir,供打包者调试应用 - // 临时目录会在智能指针释放时删除 - [[nodiscard]] utils::error::Result> + // 临时目录由调用者负责删除 + [[nodiscard]] utils::error::Result getMergedModuleDir(const package::Reference &ref, const QStringList &modules) const noexcept; std::vector getModuleList(const package::Reference &ref) noexcept; [[nodiscard]] utils::error::Result> diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index 3edc6b916..ae4d175a3 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -136,11 +136,8 @@ utils::error::Result Container::run(const ocppi::runtime::config::types::P std::filesystem::path runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation).toStdString(); - // bundle dir is already created in ContainerBuilder::create + // bundle dir should created before container run auto bundle = runtimeDir / "linglong" / this->id.toStdString(); - if (!std::filesystem::create_directories(bundle, ec) && ec) { - return LINGLONG_ERR("make rootfs directory", ec); - } #ifdef LINGLONG_FONT_CACHE_GENERATOR if (!bundle.mkpath("conf.d")) { return LINGLONG_ERR("make conf.d directory"); @@ -164,10 +161,6 @@ utils::error::Result Container::run(const ocppi::runtime::config::types::P return; } - - if (std::filesystem::remove_all(bundle, ec) == static_cast(-1)) { - qCritical() << "failed to remove " << bundle.c_str() << ": " << ec.message().c_str(); - } }); auto curProcess = diff --git a/libs/linglong/src/linglong/runtime/container_builder.h b/libs/linglong/src/linglong/runtime/container_builder.h index e1460c82c..a99506e5c 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -48,7 +48,7 @@ inline utils::error::Result getBundleDir(const std::strin auto bundle = runtimeDir / "linglong" / containerID; std::error_code ec; - if (!std::filesystem::create_directories(bundle, ec)) { + if (!std::filesystem::create_directories(bundle, ec) && ec) { return LINGLONG_ERR(QString("failed to create bundle directory %1: %2") .arg(bundle.c_str(), ec.message().c_str())); } diff --git a/libs/linglong/src/linglong/runtime/run_context.cpp b/libs/linglong/src/linglong/runtime/run_context.cpp new file mode 100644 index 000000000..36b1584d0 --- /dev/null +++ b/libs/linglong/src/linglong/runtime/run_context.cpp @@ -0,0 +1,509 @@ +/* SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "run_context.h" + +#include "linglong/extension/extension.h" +#include "linglong/runtime/container_builder.h" + +namespace linglong::runtime { + +RuntimeLayer::RuntimeLayer(package::Reference ref, RunContext &context) + : reference(ref) + , runContext(context) + , temporary(false) +{ +} + +RuntimeLayer::~RuntimeLayer() +{ + if (temporary && layerDir) { + layerDir->removeRecursively(); + } +} + +utils::error::Result RuntimeLayer::resolveLayer(const QStringList &modules, + const std::optional &subRef) +{ + LINGLONG_TRACE("resolve layer"); + + auto &repo = runContext.get().getRepo(); + utils::error::Result layer(LINGLONG_ERR("null")); + if (modules.isEmpty()) { + layer = repo.getMergedModuleDir(reference); + } else if (modules.size() > 1) { + layer = repo.getMergedModuleDir(reference, modules); + temporary = true; + } else { + layer = repo.getLayerDir(reference, modules[0].toStdString(), subRef); + } + + if (!layer) { + return LINGLONG_ERR("layer doesn't exist: " + reference.toString()); + } + + layerDir = *layer; + return LINGLONG_OK; +} + +utils::error::Result RuntimeLayer::getCachedItem() +{ + LINGLONG_TRACE("get cached item"); + + if (!cachedItem) { + auto &repo = runContext.get().getRepo(); + auto item = repo.getLayerItem(reference); + if (!item) { + return LINGLONG_ERR("no cached item found: " + reference.toString()); + } + cachedItem = std::move(item).value(); + } + + return *cachedItem; +} + +RunContext::~RunContext() +{ + if (!bundle.empty()) { + std::error_code ec; + if (std::filesystem::remove_all(bundle, ec) == static_cast(-1)) { + qWarning() << "failed to remove " << bundle.c_str() << ": " << ec.message().c_str(); + } + } +} + +utils::error::Result RunContext::resolve(const linglong::package::Reference &runnable, + bool depsBinaryOnly, + const QStringList &appModules) +{ + LINGLONG_TRACE("resolve RunContext from runnable " + runnable.toString()); + + containerID = runtime::genContainerID(runnable); + + auto item = repo.getLayerItem(runnable); + if (!item) { + return LINGLONG_ERR("no cached item found: " + runnable.toString()); + } + const auto &info = item->info; + + // only base need resolved + if (info.kind == "base") { + baseLayer = RuntimeLayer(runnable, *this); + return resolveExtension(*baseLayer); + } + + if (info.kind == "app") { + appLayer = RuntimeLayer(runnable, *this); + + if (info.runtime) { + auto runtimeFuzzyRef = + package::FuzzyReference::parse(QString::fromStdString(*info.runtime)); + if (!runtimeFuzzyRef) { + return LINGLONG_ERR(runtimeFuzzyRef); + } + + auto ref = repo.clearReference(*runtimeFuzzyRef, + { + .forceRemote = false, + .fallbackToRemote = false, + .semanticMatching = true, + }); + if (!ref) { + return LINGLONG_ERR("ref doesn't exist " + runtimeFuzzyRef->toString()); + } + runtimeLayer = RuntimeLayer(std::move(ref).value(), *this); + } + } else if (info.kind == "runtime") { + runtimeLayer = RuntimeLayer(runnable, *this); + } else { + return LINGLONG_ERR("kind " + QString::fromStdString(info.kind) + " is not runnable"); + } + + // all kinds of package has base + auto baseFuzzyRef = package::FuzzyReference::parse(QString::fromStdString(info.base)); + if (!baseFuzzyRef) { + return LINGLONG_ERR(baseFuzzyRef); + } + + auto ref = repo.clearReference(*baseFuzzyRef, + { + .forceRemote = false, + .fallbackToRemote = false, + .semanticMatching = true, + }); + if (!ref) { + return LINGLONG_ERR(ref); + } + baseLayer = RuntimeLayer(std::move(ref).value(), *this); + + // resolve runtime extension + if (runtimeLayer) { + resolveExtension(*runtimeLayer); + } + + // resolve base extension + resolveExtension(*baseLayer); + + // all reference are cleard , we can get actual layer directory now + return resolveLayer(depsBinaryOnly, appModules); +} + +utils::error::Result RunContext::resolve(const api::types::v1::BuilderProject &target, + std::filesystem::path buildOutput) +{ + LINGLONG_TRACE("resolve RunContext from builder project " + + QString::fromStdString(target.package.id)); + + auto targetRef = package::Reference::fromBuilderProject(target); + if (!targetRef) { + return LINGLONG_ERR(targetRef); + } + containerID = runtime::genContainerID(*targetRef); + + if (target.package.kind == "extension") { + extensionOutput = buildOutput; + } else if (target.package.kind == "app") { + appOutput = buildOutput; + } else if (target.package.kind == "runtime") { + runtimeOutput = buildOutput; + } else { + return LINGLONG_ERR("can't resolve run context from package kind " + + QString::fromStdString(target.package.kind)); + } + + auto baseFuzzyRef = package::FuzzyReference::parse(QString::fromStdString(target.base)); + if (!baseFuzzyRef) { + return LINGLONG_ERR(baseFuzzyRef); + } + + auto ref = repo.clearReference(*baseFuzzyRef, + { + .forceRemote = false, + .fallbackToRemote = false, + .semanticMatching = true, + }); + if (!ref) { + return LINGLONG_ERR(ref); + } + baseLayer = RuntimeLayer(std::move(ref).value(), *this); + + if (target.runtime) { + auto runtimeFuzzyRef = + package::FuzzyReference::parse(QString::fromStdString(*target.runtime)); + if (!runtimeFuzzyRef) { + return LINGLONG_ERR(runtimeFuzzyRef); + } + + ref = repo.clearReference(*runtimeFuzzyRef, + { + .forceRemote = false, + .fallbackToRemote = false, + .semanticMatching = true, + }); + if (!ref) { + return LINGLONG_ERR("ref doesn't exist " + runtimeFuzzyRef->toString()); + } + runtimeLayer = RuntimeLayer(std::move(ref).value(), *this); + + auto layer = runtimeLayer->getCachedItem(); + if (!layer) { + return LINGLONG_ERR("no cached item found: " + runtimeLayer->getReference().toString()); + } + + auto fuzzyRef = package::FuzzyReference::parse(QString::fromStdString(layer->info.base)); + if (!fuzzyRef) { + return LINGLONG_ERR(fuzzyRef); + } + auto ref = repo.clearReference(*fuzzyRef, + { + .forceRemote = false, + .fallbackToRemote = false, + .semanticMatching = true, + }); + if (!ref || *ref != baseLayer->getReference()) { + return LINGLONG_ERR(QString{ "Base is not compatible with runtime. \n" + "- Current base: %1\n" + "- Current runtime: %2\n" + "- Base required by runtime: %3" } + .arg(baseLayer->getReference().toString(), + runtimeLayer->getReference().toString(), + layer->info.base.c_str())); + } + } + + return resolveLayer(false, {}); +} + +utils::error::Result RunContext::resolveLayer(bool depsBinaryOnly, + const QStringList &appModules) +{ + LINGLONG_TRACE("resolve layers"); + + std::optional subRef; + if (appLayer) { + auto item = appLayer->getCachedItem(); + if (item && item->info.uuid) { + subRef = item->info.uuid; + } + } + + QStringList depsModules; + if (depsBinaryOnly) { + depsModules << "binary"; + } + + if (!baseLayer->resolveLayer(depsModules, subRef)) { + return LINGLONG_ERR("failed to resolve base layer"); + } + + if (appLayer) { + if (!appLayer->resolveLayer(appModules)) { + return LINGLONG_ERR("failed to resolve app layer"); + } + } + + if (runtimeLayer) { + if (!runtimeLayer->resolveLayer(depsModules, subRef)) { + return LINGLONG_ERR("failed to resolve runtime layer"); + } + } + + for (auto &ext : extensionLayers) { + if (!ext.resolveLayer()) { + qWarning() << "ignore failed extension layer"; + continue; + } + } + + return LINGLONG_OK; +} + +utils::error::Result RunContext::resolveExtension(RuntimeLayer &layer) +{ + LINGLONG_TRACE("resolve extension"); + + auto item = layer.getCachedItem(); + if (!item) { + return LINGLONG_ERR("no cached item found: " + layer.getReference().toString()); + } + + const auto &info = item->info; + if (info.extensions) { + for (const auto &extension : *info.extensions) { + qDebug() << "handle extensions: " << QString::fromStdString(extension.name); + qDebug() << "version: " << QString::fromStdString(extension.version); + qDebug() << "directory: " << QString::fromStdString(extension.directory); + if (extension.allowEnv) { + for (const auto &allowEnv : *extension.allowEnv) { + qDebug() << "allowEnv: " << QString::fromStdString(allowEnv.first) << ":" + << QString::fromStdString(allowEnv.second); + } + } + + std::string name = extension.name; + std::shared_ptr ext( + extension::ExtensionFactory::makeExtension(name)); + if (!ext->shouldEnable(name)) { + continue; + } + + auto fuzzyRef = + package::FuzzyReference::create(QString::fromStdString(info.channel), + QString::fromStdString(name), + QString::fromStdString(extension.version), + std::nullopt); + auto ref = repo.clearReference(*fuzzyRef, + { .fallbackToRemote = false, .semanticMatching = true }); + if (!ref) { + // extension is not installed, ignore it + qDebug() << "extension is not installed: " << fuzzyRef->toString(); + continue; + } + extensionLayers.emplace_back(RuntimeLayer(*ref, *this)); + } + } + + return LINGLONG_OK; +} + +utils::error::Result +RunContext::fillContextCfg(linglong::generator::ContainerCfgBuilder &builder) +{ + LINGLONG_TRACE("fill ContainerCfgBuilder with run context"); + + if (!baseLayer) { + return LINGLONG_ERR("run context doesn't resolved"); + } + + auto bundleDir = runtime::getBundleDir(containerID); + if (!bundleDir) { + return LINGLONG_ERR("failed to get bundle dir of " + QString::fromStdString(containerID)); + } + bundle = *bundleDir; + + builder.setBasePath(baseLayer->getLayerDir()->absoluteFilePath("files").toStdString()); + + if (appOutput) { + builder.setAppPath(*appOutput, false); + } else { + if (appLayer) { + builder.setAppPath(appLayer->getLayerDir()->absoluteFilePath("files").toStdString()); + fillExtraAppMounts(builder); + } + } + + if (runtimeOutput) { + builder.setRuntimePath(*runtimeOutput, false); + } else { + if (runtimeLayer) { + builder.setRuntimePath( + runtimeLayer->getLayerDir()->absoluteFilePath("files").toStdString()); + } + } + + std::vector extensionMounts{}; + if (extensionOutput) { + extensionMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = "/opt/extensions/" + targetId, + .gidMappings = {}, + .options = { { "rbind" } }, + .source = extensionOutput, + .type = "bind", + .uidMappings = {}, + }); + } + + for (const auto &ext : extensionLayers) { + std::string name = ext.getReference().id.toStdString(); + if (extensionOutput && name == targetId) { + continue; + } + extensionMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = "/opt/extensions/" + name, + .gidMappings = {}, + .options = { { "rbind", "ro" } }, + .source = ext.getLayerDir()->absoluteFilePath("files").toStdString(), + .type = "bind", + .uidMappings = {}, + }); + } + if (!extensionMounts.empty()) { + builder.setExtensionMounts(extensionMounts); + } + + builder.setBundlePath(bundle); + + return LINGLONG_OK; +} + +utils::error::Result RunContext::fillExtraAppMounts(generator::ContainerCfgBuilder &builder) +{ + LINGLONG_TRACE("fill extra app mounts"); + + auto item = appLayer->getCachedItem(); + if (!item) { + return LINGLONG_ERR(item); + } + const auto &info = item->info; + if (info.permissions) { + std::vector applicationMounts{}; + auto bindMount = [&applicationMounts]( + const api::types::v1::ApplicationConfigurationPermissionsBind &bind) { + applicationMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = bind.destination, + .gidMappings = {}, + .options = { { "rbind" } }, + .source = bind.source, + .type = "bind", + .uidMappings = {}, + }); + }; + + auto bindInnerMount = + [&applicationMounts, + this](const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { + applicationMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = bind.destination, + .gidMappings = {}, + .options = { { "rbind" } }, + .source = bundle.string() + "/rootfs" + bind.source, + .type = "bind", + .uidMappings = {}, + }); + }; + + const auto &perm = info.permissions; + if (perm->binds) { + const auto &binds = perm->binds; + std::for_each(binds->cbegin(), binds->cend(), bindMount); + } + + if (perm->innerBinds) { + const auto &innerBinds = perm->innerBinds; + std::for_each(innerBinds->cbegin(), innerBinds->cend(), bindInnerMount); + } + + builder.addExtraMounts(applicationMounts); + } + + return LINGLONG_OK; +} + +api::types::v1::ContainerProcessStateInfo RunContext::stateInfo() +{ + auto state = linglong::api::types::v1::ContainerProcessStateInfo{ + .containerID = containerID, + }; + + if (baseLayer) { + state.base = baseLayer->getReference().toString().toStdString(); + } + + if (appLayer) { + state.app = appLayer->getReference().toString().toStdString(); + } + + if (runtimeLayer) { + state.runtime = runtimeLayer->getReference().toString().toStdString(); + } + + return state; +} + +utils::error::Result RunContext::getBaseLayerPath() const +{ + LINGLONG_TRACE("get base layer path"); + + if (!baseLayer) { + return LINGLONG_ERR("run context doesn't resolved"); + } + + const auto &layerDir = baseLayer->getLayerDir(); + return std::filesystem::path{ layerDir->absolutePath().toStdString() }; +} + +utils::error::Result RunContext::getRuntimeLayerPath() const +{ + LINGLONG_TRACE("get runtime layer path"); + + if (!runtimeLayer) { + return LINGLONG_ERR("no runtime layer exist"); + } + + const auto &layerDir = runtimeLayer->getLayerDir(); + return std::filesystem::path{ layerDir->absolutePath().toStdString() }; +} + +utils::error::Result RunContext::getCachedAppItem() +{ + LINGLONG_TRACE("get cached app item"); + + if (!appLayer) { + return LINGLONG_ERR("no app layer exist"); + } + + return appLayer->getCachedItem(); +} + +} // namespace linglong::runtime diff --git a/libs/linglong/src/linglong/runtime/run_context.h b/libs/linglong/src/linglong/runtime/run_context.h new file mode 100644 index 000000000..30443b3ab --- /dev/null +++ b/libs/linglong/src/linglong/runtime/run_context.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#pragma once + +#include "linglong/api/types/v1/BuilderProject.hpp" +#include "linglong/api/types/v1/ContainerProcessStateInfo.hpp" +#include "linglong/oci-cfg-generators/container_cfg_builder.h" +#include "linglong/repo/ostree_repo.h" +#include "linglong/utils/error/error.h" + +#include + +namespace linglong::runtime { + +class RunContext; + +class RuntimeLayer +{ +public: + RuntimeLayer(package::Reference ref, RunContext &context); + ~RuntimeLayer(); + + utils::error::Result resolveLayer( + const QStringList &modules = {}, const std::optional &subRef = std::nullopt); + + utils::error::Result getCachedItem(); + + const package::Reference &getReference() const { return reference; } + + const std::optional &getLayerDir() const { return layerDir; } + +private: + package::Reference reference; + std::reference_wrapper runContext; + std::optional layerDir; + std::optional cachedItem; + bool temporary; +}; + +class RunContext +{ +public: + RunContext(repo::OSTreeRepo &r) + : repo(r) + { + } + + ~RunContext(); + + utils::error::Result resolve(const linglong::package::Reference &runnable, + bool depsBinaryOnly = false, + const QStringList &appModules = {}); + utils::error::Result resolve(const api::types::v1::BuilderProject &target, + std::filesystem::path buildOutput); + + utils::error::Result fillContextCfg(generator::ContainerCfgBuilder &builder); + api::types::v1::ContainerProcessStateInfo stateInfo(); + + repo::OSTreeRepo &getRepo() const { return repo; } + + const std::string &getContainerId() const { return containerID; } + + const std::optional &getBaseLayer() const { return baseLayer; } + + const std::optional &getRuntimeLayer() const { return runtimeLayer; } + + utils::error::Result getBaseLayerPath() const; + utils::error::Result getRuntimeLayerPath() const; + + utils::error::Result getCachedAppItem(); + + bool hasRuntime() const { return !!runtimeLayer; } + +private: + utils::error::Result resolveLayer(bool depsBinaryOnly, const QStringList &appModules); + utils::error::Result resolveExtension(RuntimeLayer &layer); + utils::error::Result fillExtraAppMounts(generator::ContainerCfgBuilder &builder); + + repo::OSTreeRepo &repo; + + std::optional baseLayer; + std::optional runtimeLayer; + std::optional appLayer; + std::vector extensionLayers; + + std::string targetId; + std::optional appOutput; + std::optional runtimeOutput; + std::optional extensionOutput; + + std::string containerID; + std::filesystem::path bundle; +}; + +} // namespace linglong::runtime diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 7cb15d2b0..715f43bae 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -397,9 +397,27 @@ ContainerCfgBuilder &ContainerCfgBuilder::enableQuirkVolatile() noexcept return *this; } -ContainerCfgBuilder &ContainerCfgBuilder::setExtraMounts(std::vector extra) noexcept +ContainerCfgBuilder &ContainerCfgBuilder::setExtensionMounts(std::vector extensions) noexcept { - extraMount = extra; + extensionMount = std::move(extensions); + return *this; +} + +ContainerCfgBuilder &ContainerCfgBuilder::addExtraMount(Mount extra) noexcept +{ + if (!extraMount) { + extraMount = std::vector{}; + } + extraMount->emplace_back(std::move(extra)); + return *this; +} + +ContainerCfgBuilder &ContainerCfgBuilder::addExtraMounts(std::vector extra) noexcept +{ + if (!extraMount) { + extraMount = std::vector{}; + } + std::move(extra.begin(), extra.end(), std::back_inserter(*extraMount)); return *this; } @@ -418,6 +436,32 @@ ContainerCfgBuilder &ContainerCfgBuilder::addMask(const std::vector return *this; } +std::string ContainerCfgBuilder::ldConf(const std::string &triplet) +{ + std::string ldRawConf; + auto appendLdConf = [&ldRawConf, &triplet](const std::string &prefix) { + ldRawConf.append(prefix + "/lib\n"); + ldRawConf.append(prefix + "/lib/" + triplet + "\n"); + ldRawConf.append("include " + prefix + "/etc/ld.so.conf\n"); + }; + + if (runtimePath) { + appendLdConf(runtimeMountPoint); + } + + if (appPath) { + appendLdConf(std::filesystem::path{ "/opt/apps" } / appId / "files"); + } + + if (extensionMount) { + for (const auto &extension : *extensionMount) { + appendLdConf(extension.destination); + } + } + + return ldRawConf; +} + bool ContainerCfgBuilder::checkValid() noexcept { if (appId.empty()) { @@ -487,7 +531,7 @@ bool ContainerCfgBuilder::buildMountRuntime() noexcept return false; } - runtimeMount = Mount{ .destination = "/runtime", + runtimeMount = Mount{ .destination = runtimeMountPoint, .options = string_list{ "rbind", runtimePathRo ? "ro" : "rw" }, .source = *runtimePath, .type = "bind" }; @@ -512,7 +556,7 @@ bool ContainerCfgBuilder::buildMountApp() noexcept .options = string_list{ "nodev", "nosuid", "mode=700" }, .source = "tmpfs", .type = "tmpfs" }, - Mount{ .destination = std::filesystem::path("/opt/apps") / appId / "files", + Mount{ .destination = std::filesystem::path{ "/opt/apps" } / appId / "files", .options = string_list{ "rbind", appPathRo ? "ro" : "rw" }, .source = *appPath, .type = "bind" } }; @@ -1086,7 +1130,9 @@ bool ContainerCfgBuilder::buildEnv() noexcept } } - environment["LINGLONG_APPID"] = appId; + if (appPath) { + environment["LINGLONG_APPID"] = appId; + } auto envShFile = *bundlePath / "00env.sh"; std::ofstream ofs(envShFile); @@ -1135,6 +1181,10 @@ bool ContainerCfgBuilder::mergeMount() noexcept std::move(appMount->begin(), appMount->end(), std::back_inserter(mounts)); } + if (extensionMount) { + std::move(extensionMount->begin(), extensionMount->end(), std::back_inserter(mounts)); + } + if (sysMount) { mounts.insert(mounts.end(), std::move(*sysMount)); } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 608c2788a..1724cd6b8 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -82,6 +82,8 @@ class ContainerCfgBuilder return *this; } + std::optional getRuntimePath() { return runtimePath; } + ContainerCfgBuilder &setBasePath(std::filesystem::path path, bool isRo = true) noexcept { basePath = path; @@ -89,6 +91,8 @@ class ContainerCfgBuilder return *this; } + std::optional getBasePath() { return basePath; } + ContainerCfgBuilder &setBundlePath(std::filesystem::path path) noexcept { bundlePath = path; @@ -136,7 +140,10 @@ class ContainerCfgBuilder ContainerCfgBuilder &enableQuirkVolatile() noexcept; - ContainerCfgBuilder &setExtraMounts(std::vector) noexcept; + ContainerCfgBuilder & + setExtensionMounts(std::vector) noexcept; + ContainerCfgBuilder &addExtraMount(ocppi::runtime::config::types::Mount) noexcept; + ContainerCfgBuilder &addExtraMounts(std::vector) noexcept; ContainerCfgBuilder & setStartContainerHooks(std::vector) noexcept; @@ -155,6 +162,8 @@ class ContainerCfgBuilder return *this; } + std::string ldConf(const std::string &triplet); + bool build() noexcept; const ocppi::runtime::config::types::Config &getConfig() const { return config; } @@ -259,6 +268,8 @@ class ContainerCfgBuilder // volatile std::optional> volatileMount; + // extension mounts + std::optional> extensionMount; // extra mounts std::optional> extraMount; @@ -276,6 +287,8 @@ class ContainerCfgBuilder ocppi::runtime::config::types::Config config; Error error_; + + const std::string runtimeMountPoint = "/runtime"; }; }; // namespace linglong::generator From fc16401fa5aa56b625399e1b76282b16a8f8c88b Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 22 May 2025 10:33:35 +0800 Subject: [PATCH 007/366] feat: handle missing refs gracefully in removeOstreeRef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在删除ref时, 如果ostree不存在对应的ref, 不需要报错, 避免因缓存不一致导致无法卸载应用 --- .../src/linglong/repo/ostree_repo.cpp | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 7cf8f51fb..3e925637f 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -600,21 +600,16 @@ OSTreeRepo::removeOstreeRef(const api::types::v1::RepositoryCacheLayersItem &lay FALSE, OstreeRepoResolveRevExtFlags::OSTREE_REPO_RESOLVE_REV_EXT_NONE, &rev, - &gErr) - == FALSE) { - return LINGLONG_ERR(QString{ "couldn't resolve ref %1 on local machine" }.arg( - QString::fromStdString(refspec)), - gErr); - } - - if (ostree_repo_set_ref_immediate(this->ostreeRepo.get(), - layer.repo.c_str(), - ref.c_str(), - nullptr, - nullptr, - &gErr) - == FALSE) { - return LINGLONG_ERR("ostree_repo_set_ref_immediate", gErr); + &gErr)) { + if (ostree_repo_set_ref_immediate(this->ostreeRepo.get(), + layer.repo.c_str(), + ref.c_str(), + nullptr, + nullptr, + &gErr) + == FALSE) { + return LINGLONG_ERR("ostree_repo_set_ref_immediate", gErr); + } } auto ret = this->cache->deleteLayerItem(layer); From d442ea6ba51226307b06f1be4d8b84f3a03ba552 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 19 May 2025 14:16:31 +0800 Subject: [PATCH 008/366] fix: fix export test command Signed-off-by: reddevillg --- tools/test-linglong.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/test-linglong.sh b/tools/test-linglong.sh index 352244ecb..60f1d9261 100755 --- a/tools/test-linglong.sh +++ b/tools/test-linglong.sh @@ -23,14 +23,14 @@ ll-builder export ll-builder run # 测试dbus环境变量没有问题 -ll-builder run --exec export | grep DBUS_SESSION_BUS_ADDRESS -ll-builder run --exec export | grep DBUS_SYSTEM_BUS_ADDRESS +ll-builder run -- bash -c "export" | grep DBUS_SESSION_BUS_ADDRESS +ll-builder run -- bash -c "export" | grep DBUS_SYSTEM_BUS_ADDRESS # 测试session dbus环境变量包含参数时能正常处理 export DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS,test=1 -ll-builder run --exec export | grep DBUS_SESSION_BUS_ADDRESS | grep test=1 +ll-builder run -- bash -c "export" | grep DBUS_SESSION_BUS_ADDRESS | grep test=1 # 测试system dbus环境变量包含参数时能正常处理 export DBUS_SYSTEM_BUS_ADDRESS="unix:path=/var/run/dbus/system_bus_socket,test=2" -ll-builder run --exec export | grep DBUS_SYSTEM_BUS_ADDRESS | grep test=2 +ll-builder run -- bash -c "export" | grep DBUS_SYSTEM_BUS_ADDRESS | grep test=2 #运行并安装uab ll-cli uninstall org.dde.demo || true From 3f19ae56efa8fc6017adf8de10a8be801fe4f3cf Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 22 May 2025 13:49:38 +0800 Subject: [PATCH 009/366] fix: update task ends abnormally when there is an application running Should not terminate the update task when the sub-state is PackageManagerDone. --- libs/linglong/src/linglong/package_manager/package_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 49a190d1b..e1852718a 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -1787,7 +1787,7 @@ auto PackageManager::Update(const QVariantMap ¶meters) noexcept -> QVariantM refSpecs, [this, upgrades = std::move(upgrades)](PackageTask &taskRef) { for (const auto &[reference, newReference] : upgrades) { - if (isTaskDone(taskRef.subState())) { + if (taskRef.subState() == linglong::api::types::v1::SubState::AllDone) { return; } From c32d5d0e7fe0aff8b5854b493afabbd8f826fedc Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 21 May 2025 13:14:31 +0800 Subject: [PATCH 010/366] fix: fix crash when no runtime provided Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index c0a00ba8b..d6c92472f 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1041,7 +1041,9 @@ utils::error::Result Builder::buildStagePreCommit() noexcept // base prefix is /usr, and runtime prefix is /runtime QList src = { baseOverlay->upperDirPath() + "/usr" }; if (this->project.package.kind == "app" || this->project.package.kind == "extension") { - src.append(runtimeOverlay->upperDirPath()); + if (runtimeOverlay) { + src.append(runtimeOverlay->upperDirPath()); + } } mergeOutput(src, buildOutput, QStringList({ "bin/", "lib/" })); From 3c85b1ef531f8d0860ca4b66e5c96e734ed2db21 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Thu, 22 May 2025 19:15:48 +0800 Subject: [PATCH 011/366] refactor: forwardEnv will forward all envs by default fix typo Signed-off-by: ComixHe --- .../src/linglong/builder/linglong_builder.cpp | 8 ++--- libs/linglong/src/linglong/cli/cli.cpp | 2 +- .../package_manager/package_manager.cpp | 2 +- .../container_cfg_builder.cpp | 35 +++++++++++++------ .../container_cfg_builder.h | 11 +++--- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index d6c92472f..01265fea5 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -736,7 +736,7 @@ utils::error::Result Builder::processBuildDepends() noexcept .options = { { "rbind", "ro" } }, .source = this->workingDir.absolutePath().toStdString(), .type = "bind" }) - .forwordDefaultEnv(); + .forwardDefaultEnv(); // overwrite runtime overlay directory if (cfgBuilder.getRuntimePath()) { @@ -866,7 +866,7 @@ utils::error::Result Builder::buildStageBuild(const QStringList &args) noe std::vector{ ocppi::runtime::config::types::Hook{ .path = "/sbin/ldconfig", } }) - .forwordDefaultEnv() + .forwardDefaultEnv() .addMask({ "/project/linglong/output", "/project/linglong/overlay", @@ -1008,7 +1008,7 @@ utils::error::Result Builder::buildStagePreCommit() noexcept .options = { { "rbind", "rw" } }, .source = this->workingDir.absolutePath().toStdString(), .type = "bind" }) - .forwordDefaultEnv(); + .forwardDefaultEnv(); if (cfgBuilder.getRuntimePath()) { cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); @@ -1927,7 +1927,7 @@ utils::error::Result Builder::run(const QStringList &modules, .mapPrivate(std::string("/home/") + userNameEnv + "/.ssh", true) .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) .bindIPC() - .forwordDefaultEnv() + .forwardDefaultEnv() .addExtraMounts(applicationMounts) .enableSelfAdjustingMount(); #ifdef LINGLONG_FONT_CACHE_GENERATOR diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 1f6c24c4c..eae6ef75a 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -718,7 +718,7 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) .mapPrivate(std::string("/home/") + userNameEnv + "/.ssh", true) .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) .bindIPC() - .forwordDefaultEnv() + .forwardDefaultEnv() .enableSelfAdjustingMount(); #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index e1852718a..5aa1e668a 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -2240,7 +2240,7 @@ utils::error::Result PackageManager::generateCache(const package::Referenc .bindCgroup() .bindRun() .bindUserGroup() - .forwordDefaultEnv() + .forwardDefaultEnv() .addExtraMounts(std::vector{ ocppi::runtime::config::types::Mount{ .destination = generatorDest, .options = { { "rbind", "ro" } }, diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 715f43bae..4aa39543d 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -15,6 +15,8 @@ #include #include +extern char **environ; + namespace linglong::generator { using string_list = std::vector; @@ -252,9 +254,9 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindMedia() noexcept return *this; } -ContainerCfgBuilder &ContainerCfgBuilder::forwordDefaultEnv() noexcept +ContainerCfgBuilder &ContainerCfgBuilder::forwardDefaultEnv() noexcept { - return forwordEnv(std::vector{ + return forwardEnv(std::vector{ "DISPLAY", "LANG", "LANGUAGE", @@ -291,9 +293,24 @@ ContainerCfgBuilder &ContainerCfgBuilder::forwordDefaultEnv() noexcept "TERM" }); } -ContainerCfgBuilder &ContainerCfgBuilder::forwordEnv(std::vector envList) noexcept +ContainerCfgBuilder & +ContainerCfgBuilder::forwardEnv(const std::vector &envList) noexcept { - envForword = envList; + if (!envList.empty()) { + for (const auto &env : envList) { + envForward.emplace(env); + } + + return *this; + } + + for (char **env = environ; *env != nullptr; ++env) { + auto str = std::string_view(*env); + auto idx = str.find('='); + if (idx != std::string_view::npos) { + envForward.emplace(str.begin(), str.begin() + idx); + } + } return *this; } @@ -1121,12 +1138,10 @@ bool ContainerCfgBuilder::buildQuirkVolatile() noexcept bool ContainerCfgBuilder::buildEnv() noexcept { - if (envForword) { - for (const auto &key : *envForword) { - auto *value = getenv(key.c_str()); - if (value) { - environment[key] = value; - } + for (const auto &key : envForward) { + auto *value = getenv(key.c_str()); + if (value != nullptr) { + environment.emplace(key, value); } } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 1724cd6b8..6316cb4bd 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -11,7 +11,8 @@ #include "ocppi/runtime/config/types/Mount.hpp" #include -#include +#include +#include namespace linglong::generator { @@ -123,8 +124,8 @@ class ContainerCfgBuilder ContainerCfgBuilder &bindUserGroup() noexcept; ContainerCfgBuilder &bindMedia() noexcept; - ContainerCfgBuilder &forwordDefaultEnv() noexcept; - ContainerCfgBuilder &forwordEnv(std::vector envList) noexcept; + ContainerCfgBuilder &forwardDefaultEnv() noexcept; + ContainerCfgBuilder &forwardEnv(const std::vector &envList = {}) noexcept; ContainerCfgBuilder &bindHostRoot() noexcept; ContainerCfgBuilder &bindHostStatics() noexcept; @@ -250,8 +251,8 @@ class ContainerCfgBuilder std::optional> ldCacheMount; // environment - std::optional> envForword; - std::map environment; + std::unordered_set envForward; + std::unordered_map environment; std::optional envMount; // home dir From e7814c3cd32f33265b9c9f73cc116900b6a9b88d Mon Sep 17 00:00:00 2001 From: ComixHe Date: Thu, 22 May 2025 20:54:53 +0800 Subject: [PATCH 012/366] refactor: add getBundlePath make basePath and bundlePath to be required field Signed-off-by: ComixHe --- .../oci-cfg-generators/container_cfg_builder.cpp | 12 ++++++------ .../oci-cfg-generators/container_cfg_builder.h | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 4aa39543d..59078a382 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -487,13 +487,13 @@ bool ContainerCfgBuilder::checkValid() noexcept return false; } - if (!basePath) { + if (basePath.empty()) { error_.reason = "base path is not set"; error_.code = BUILD_PARAM_ERROR; return false; } - if (!bundlePath) { + if (bundlePath.empty()) { error_.reason = "bundle path is empty"; error_.code = BUILD_PARAM_ERROR; return false; @@ -522,7 +522,7 @@ bool ContainerCfgBuilder::prepare() noexcept auto process = Process{ .args = string_list{ "bash" }, .cwd = "/" }; config.process = std::move(process); - config.root = { .path = *basePath, .readonly = basePathRo }; + config.root = { .path = basePath, .readonly = basePathRo }; return true; } @@ -1149,7 +1149,7 @@ bool ContainerCfgBuilder::buildEnv() noexcept environment["LINGLONG_APPID"] = appId; } - auto envShFile = *bundlePath / "00env.sh"; + auto envShFile = bundlePath / "00env.sh"; std::ofstream ofs(envShFile); if (!ofs.is_open()) { error_.reason = envShFile.string() + " can't be created"; @@ -1371,7 +1371,7 @@ bool ContainerCfgBuilder::shouldFix(int node, std::filesystem::path &fixPath) no } // only bind from layers should fix - if (!(root.rfind(*basePath, 0) == 0 || (runtimePath && root.rfind(*runtimePath, 0) == 0) + if (!(root.rfind(basePath, 0) == 0 || (runtimePath && root.rfind(*runtimePath, 0) == 0) || (appPath && root.rfind(*appPath, 0) == 0))) { return false; } @@ -1589,7 +1589,7 @@ bool ContainerCfgBuilder::selfAdjustingMount() noexcept // Remounting as tmpfs requires an alternate rootfs context to avoid obscuring underlying files, // so adjust root and change root path to bundlePath/rootfs adjustNode(0, config.root->path, ""); - auto rootfs = *bundlePath / "rootfs"; + auto rootfs = bundlePath / "rootfs"; std::error_code ec; if (!std::filesystem::create_directories(rootfs, ec) && ec) { error_.reason = rootfs.string() + " can't be created"; diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 6316cb4bd..929bc0513 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -94,12 +94,14 @@ class ContainerCfgBuilder std::optional getBasePath() { return basePath; } - ContainerCfgBuilder &setBundlePath(std::filesystem::path path) noexcept + ContainerCfgBuilder &setBundlePath(const std::filesystem::path &path) noexcept { bundlePath = path; return *this; } + const std::filesystem::path &getBundlePath() const noexcept { return bundlePath; } + ContainerCfgBuilder &setAppCache(std::filesystem::path path, bool isRo = true) noexcept { appCache = path; @@ -217,8 +219,8 @@ class ContainerCfgBuilder std::string appId; std::optional runtimePath; std::optional appPath; - std::optional basePath; - std::optional bundlePath; + std::filesystem::path basePath; + std::filesystem::path bundlePath; std::optional appCache; bool runtimePathRo = true; From 4056c534f029045009e500dd9f3b47eb09ac4766 Mon Sep 17 00:00:00 2001 From: myml Date: Fri, 23 May 2025 15:25:39 +0800 Subject: [PATCH 013/366] docs: add multi-architecture build guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加架构支持列表 多架构项目结构指导 龙芯新旧世界迁移 --- docs/pages/guide/ll-builder/multiarch.md | 73 ++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 docs/pages/guide/ll-builder/multiarch.md diff --git a/docs/pages/guide/ll-builder/multiarch.md b/docs/pages/guide/ll-builder/multiarch.md new file mode 100644 index 000000000..6d8e44f60 --- /dev/null +++ b/docs/pages/guide/ll-builder/multiarch.md @@ -0,0 +1,73 @@ +# 玲珑多架构构建指南 + +### 支持的架构 + +当前玲珑打包工具支持以下 CPU 架构: + +- x86_64 + +- arm64(aarch64) + +- loong64 + +- loongarch64(龙芯旧世界) + +- sw64(申威) + +- mips64 + +### 构建限制说明 + +不支持跨架构交叉编译:目前只能在对应架构的机器上构建该架构的包 + +### 多架构项目结构建议 + +推荐采用以下目录结构管理多架构构建: + +```txt +项目根目录/ +├── linglong.yaml # x86_64 架构配置文件 +├── arm64/ +│ └── linglong.yaml # arm64 架构配置文件 +├── loong64/ +│ └── linglong.yaml # loong64 架构配置文件 +├── src/ # 共享的源代码 +└── resources/ # 共享的资源文件 +``` + +将源代码、资源文件等放在项目根目录,各架构目录只存放差异化的配置文件 + +### 构建命令示例 + +构建指定架构的包: + +```bash +# 构建 arm64 架构包 +ll-builder -f arm64/linglong.yaml +``` + +```bash +# 构建 loongarch64 架构包 +ll-builder -f loongarch64/linglong.yaml +``` + +### 龙芯 + +龙芯新旧世界的差异可查看 [咱龙了吗](https://areweloongyet.com/docs/old-and-new-worlds/) + +> 可以使用 file 工具方便地检查一个二进制程序属于哪个世界。 假设你想检查 someprogram 这个文件,就执行 file someprogram,如果输出的行含有这些字样: +> interpreter /lib64/ld.so.1, for GNU/Linux 4.15.0 +> 就表明这是一个旧世界程序。 +> 相应地,如果输出的行含有这些字样: +> interpreter /lib64/ld-linux-loongarch-lp64d.so.1, for GNU/Linux 5.19.0 + +介于新旧世界差异不小,在玲珑中新旧世界被分为两个架构,新世界使用更简洁的 loong64 作为架构代号。 + +考虑到市面上还有部分支持龙芯的应用未适配新世界,玲珑制作了可在新世界架构运行的旧世界的 base(org.deepin.foundation/20.0.0) 和 runtime(org.deepin.Runtime/20.0.0.12),用来将支持旧世界的应用迁移到新世界。 + +迁移步骤: + +1. 准备一个新世界架构的机器并安装 deepin 或 uos 系统 +1. 在宿主机安装 `liblol-dkms` 内核模块 `apt install liblol-dkms` +1. 编写一个 linglong.yaml 文件,base 和 runtime 填写上文所属的版本号。 +1. 在 linglong.yaml 里解压旧世界应用的软件包,复制到$PREFIX 目录 From a2f07ca8fc24b9c5386e668f2e8b100846b92169 Mon Sep 17 00:00:00 2001 From: dengbo Date: Fri, 23 May 2025 16:59:15 +0800 Subject: [PATCH 014/366] fix: uninstall application exception output log update-desktop-database and update-mime-database will generate system files in specify a directory. these files do not belong to the applications and should not be printed in the log. --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 3e925637f..798a6f120 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1806,6 +1806,14 @@ void OSTreeRepo::unexportReference(const package::Reference &ref) noexcept } if (!info.isSymLink()) { + // update-desktop-database and update-mime-database will generate system files in + // specify a directory. these files do not belong to the applications and should not be + // printed in the log. + if (info.absoluteFilePath().contains("share/mime") + || info.absoluteFilePath().contains("share/applications")) { + continue; + } + // NOTE: Everything in entries should be directory or symbol link. // But it can be some cache file, we should not remove it too. qWarning() << "Invalid file detected." << info.absoluteFilePath(); From c5f2665f12fa639ee6d7602c291a486697b256c0 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 21 May 2025 15:13:51 +0800 Subject: [PATCH 015/366] feat: Support extension environment variables 1. apply extension environment 2. apply app and extension permission binds 3. run ldconfig with -X option in cache generate phase 4. introduce dummy extension which is enabled by default Signed-off-by: reddevillg --- .../src/linglong/builder/linglong_builder.cpp | 20 +- .../src/linglong/extension/extension.cpp | 2 +- .../src/linglong/extension/extension.h | 10 + .../package_manager/package_manager.cpp | 2 +- .../src/linglong/runtime/run_context.cpp | 191 ++++++++++++++---- .../src/linglong/runtime/run_context.h | 13 +- .../container_cfg_builder.cpp | 18 ++ .../container_cfg_builder.h | 2 + 8 files changed, 204 insertions(+), 54 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 01265fea5..8370e6d6c 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1888,15 +1888,16 @@ utils::error::Result Builder::run(const QStringList &modules, auto container = this->containerBuilder.create(cfgBuilder, - QString::fromStdString(buildContext.getContainerId())); + QString::fromStdString(runContext.getContainerId())); if (!container) { return LINGLONG_ERR(container); } - ocppi::runtime::config::types::Process process{ - .args = - std::vector{ "/sbin/ldconfig", "-C", "/run/linglong/cache/ld.so.cache" } - }; + ocppi::runtime::config::types::Process process{ .args = std::vector{ + "/sbin/ldconfig", + "-X", + "-C", + "/run/linglong/cache/ld.so.cache" } }; ocppi::runtime::RunOption opt{}; auto result = (*container)->run(process, opt); if (!result) { @@ -2035,10 +2036,11 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, return LINGLONG_ERR(container); } - ocppi::runtime::config::types::Process process{ - .args = - std::vector{ "/sbin/ldconfig", "-C", "/run/linglong/cache/ld.so.cache" } - }; + ocppi::runtime::config::types::Process process{ .args = std::vector{ + "/sbin/ldconfig", + "-X", + "-C", + "/run/linglong/cache/ld.so.cache" } }; ocppi::runtime::RunOption opt{}; auto result = (*container)->run(process, opt); if (!result) { diff --git a/libs/linglong/src/linglong/extension/extension.cpp b/libs/linglong/src/linglong/extension/extension.cpp index 79ef3806f..9c48d3b4f 100644 --- a/libs/linglong/src/linglong/extension/extension.cpp +++ b/libs/linglong/src/linglong/extension/extension.cpp @@ -19,7 +19,7 @@ ExtensionIf *ExtensionFactory::makeExtension(const std::string &name) return new ExtensionImplNVIDIADisplayDriver(); } - return NULL; + return new ExtensionImplDummy(); } std::string ExtensionImplNVIDIADisplayDriver::name = "org.deepin.driver.display.nvidia"; diff --git a/libs/linglong/src/linglong/extension/extension.h b/libs/linglong/src/linglong/extension/extension.h index 305419eb6..b6e66862f 100644 --- a/libs/linglong/src/linglong/extension/extension.h +++ b/libs/linglong/src/linglong/extension/extension.h @@ -46,4 +46,14 @@ class ExtensionImplNVIDIADisplayDriver : public ExtensionIf std::string driverName; }; +class ExtensionImplDummy : public ExtensionIf +{ +public: + ExtensionImplDummy() = default; + + ~ExtensionImplDummy() = default; + + bool shouldEnable([[maybe_unused]] std::string &extensionName) override { return true; } +}; + } // namespace linglong::extension diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 5aa1e668a..67121c61e 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -2288,7 +2288,7 @@ utils::error::Result PackageManager::generateCache(const package::Referenc if (!currentArch) { return LINGLONG_ERR(currentArch); } - const auto ldGenerateCmd = "/sbin/ldconfig -C " + appCacheDest + "/ld.so.cache"; + const auto ldGenerateCmd = "/sbin/ldconfig -X -C " + appCacheDest + "/ld.so.cache"; #ifdef LINGLONG_FONT_CACHE_GENERATOR // Usage: font-cache-generator [cacheRoot] [id] const std::string fontGenerateCmd = diff --git a/libs/linglong/src/linglong/runtime/run_context.cpp b/libs/linglong/src/linglong/runtime/run_context.cpp index 36b1584d0..65bb8784c 100644 --- a/libs/linglong/src/linglong/runtime/run_context.cpp +++ b/libs/linglong/src/linglong/runtime/run_context.cpp @@ -160,6 +160,7 @@ utils::error::Result RunContext::resolve(const api::types::v1::BuilderProj return LINGLONG_ERR(targetRef); } containerID = runtime::genContainerID(*targetRef); + targetId = target.package.id; if (target.package.kind == "extension") { extensionOutput = buildOutput; @@ -269,11 +270,81 @@ utils::error::Result RunContext::resolveLayer(bool depsBinaryOnly, } } + auto replaceSubstring = [](std::string_view str, std::string_view from, std::string_view to) { + std::string result; + if (from.empty()) { + return std::string(str); + } + + size_t start = 0; + while (true) { + size_t pos = str.find(from, start); + if (pos == std::string_view::npos) { + break; + } + // Append the part before the match + result.append(str.data() + start, pos - start); + // Append the replacement + result.append(to.data(), to.size()); + // Move past the matched part + start = pos + from.size(); + } + // Append the remaining part of the string + result.append(str.data() + start, str.size() - start); + return result; + }; + for (auto &ext : extensionLayers) { if (!ext.resolveLayer()) { qWarning() << "ignore failed extension layer"; continue; } + + auto extensionOf = ext.getExtensionInfo(); + if (!extensionOf) { + continue; + } + const auto &[extensionDefine, layer] = *extensionOf; + if (!extensionDefine.allowEnv) { + continue; + } + const auto &allowEnv = *extensionDefine.allowEnv; + + auto extItem = ext.getCachedItem(); + if (!extItem) { + continue; + } + const auto &extInfo = extItem->info; + if (!extInfo.extImpl) { + qWarning() << "no ext_impl found for " << ext.getReference().toString(); + continue; + } + const auto &extImpl = *extInfo.extImpl; + if (!extImpl.env) { + continue; + } + for (const auto &env : *extImpl.env) { + auto allowed = allowEnv.find(env.first); + if (allowed == allowEnv.end()) { + qWarning() << "env " << QString::fromStdString(env.first) << " not allowed in " + << layer.get().getReference().toString(); + continue; + } + + std::string res = + replaceSubstring(env.second, + "$PREFIX", + "/opt/extensions/" + ext.getReference().id.toStdString()); + auto &value = environment[env.first]; + if (!value.empty()) { + res = replaceSubstring(res, "$ORIGIN", value); + } else if (!allowed->second.empty()) { + res = replaceSubstring(res, "$ORIGIN", allowed->second); + } + value = res; + qDebug() << "environment[" << QString::fromStdString(env.first) + << "]=" << QString::fromStdString(res); + } } return LINGLONG_OK; @@ -320,7 +391,10 @@ utils::error::Result RunContext::resolveExtension(RuntimeLayer &layer) qDebug() << "extension is not installed: " << fuzzyRef->toString(); continue; } - extensionLayers.emplace_back(RuntimeLayer(*ref, *this)); + + auto &extensionLayer = extensionLayers.emplace_back(*ref, *this); + extensionLayer.setExtensionInfo( + std::make_pair(extension, std::reference_wrapper(extensionLayer))); } } @@ -349,7 +423,6 @@ RunContext::fillContextCfg(linglong::generator::ContainerCfgBuilder &builder) } else { if (appLayer) { builder.setAppPath(appLayer->getLayerDir()->absoluteFilePath("files").toStdString()); - fillExtraAppMounts(builder); } } @@ -394,6 +467,15 @@ RunContext::fillContextCfg(linglong::generator::ContainerCfgBuilder &builder) builder.setBundlePath(bundle); + auto res = fillExtraAppMounts(builder); + if (!res) { + return res; + } + + if (!environment.empty()) { + builder.appendEnv(environment); + } + return LINGLONG_OK; } @@ -401,50 +483,75 @@ utils::error::Result RunContext::fillExtraAppMounts(generator::ContainerCf { LINGLONG_TRACE("fill extra app mounts"); - auto item = appLayer->getCachedItem(); - if (!item) { - return LINGLONG_ERR(item); - } - const auto &info = item->info; - if (info.permissions) { - std::vector applicationMounts{}; - auto bindMount = [&applicationMounts]( - const api::types::v1::ApplicationConfigurationPermissionsBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - - auto bindInnerMount = - [&applicationMounts, - this](const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { - applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = bind.destination, - .gidMappings = {}, - .options = { { "rbind" } }, - .source = bundle.string() + "/rootfs" + bind.source, - .type = "bind", - .uidMappings = {}, - }); - }; - - const auto &perm = info.permissions; - if (perm->binds) { - const auto &binds = perm->binds; - std::for_each(binds->cbegin(), binds->cend(), bindMount); + auto fillPermissionsBinds = [&builder, + this](RuntimeLayer &layer) -> utils::error::Result { + LINGLONG_TRACE("fill permissions binds"); + + auto item = layer.getCachedItem(); + if (!item) { + return LINGLONG_ERR(item); + } + const auto &info = item->info; + + if (info.permissions) { + std::vector applicationMounts{}; + auto bindMount = + [&applicationMounts]( + const api::types::v1::ApplicationConfigurationPermissionsBind &bind) { + applicationMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = bind.destination, + .gidMappings = {}, + .options = { { "rbind" } }, + .source = bind.source, + .type = "bind", + .uidMappings = {}, + }); + }; + + auto bindInnerMount = + [&applicationMounts, + this](const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { + applicationMounts.push_back(ocppi::runtime::config::types::Mount{ + .destination = bind.destination, + .gidMappings = {}, + .options = { { "rbind" } }, + .source = bundle.string() + "/rootfs" + bind.source, + .type = "bind", + .uidMappings = {}, + }); + }; + + const auto &perm = info.permissions; + if (perm->binds) { + const auto &binds = perm->binds; + std::for_each(binds->cbegin(), binds->cend(), bindMount); + } + + if (perm->innerBinds) { + const auto &innerBinds = perm->innerBinds; + std::for_each(innerBinds->cbegin(), innerBinds->cend(), bindInnerMount); + } + + builder.addExtraMounts(applicationMounts); } - if (perm->innerBinds) { - const auto &innerBinds = perm->innerBinds; - std::for_each(innerBinds->cbegin(), innerBinds->cend(), bindInnerMount); + return LINGLONG_OK; + }; + + if (appLayer) { + auto res = fillPermissionsBinds(*appLayer); + if (!res) { + return LINGLONG_ERR("failed to apply permission binds for " + + appLayer->getReference().toString(), + res); } + } - builder.addExtraMounts(applicationMounts); + for (auto &ext : extensionLayers) { + if (!fillPermissionsBinds(ext)) { + qWarning() << "failed to apply permission binds for " << ext.getReference().toString(); + continue; + } } return LINGLONG_OK; diff --git a/libs/linglong/src/linglong/runtime/run_context.h b/libs/linglong/src/linglong/runtime/run_context.h index 30443b3ab..aff117229 100644 --- a/libs/linglong/src/linglong/runtime/run_context.h +++ b/libs/linglong/src/linglong/runtime/run_context.h @@ -8,11 +8,13 @@ #include "linglong/api/types/v1/BuilderProject.hpp" #include "linglong/api/types/v1/ContainerProcessStateInfo.hpp" +#include "linglong/api/types/v1/ExtensionDefine.hpp" #include "linglong/oci-cfg-generators/container_cfg_builder.h" #include "linglong/repo/ostree_repo.h" #include "linglong/utils/error/error.h" #include +#include namespace linglong::runtime { @@ -24,6 +26,9 @@ class RuntimeLayer RuntimeLayer(package::Reference ref, RunContext &context); ~RuntimeLayer(); + using ExtensionRuntimeLayerInfo = + std::pair>; + utils::error::Result resolveLayer( const QStringList &modules = {}, const std::optional &subRef = std::nullopt); @@ -33,12 +38,17 @@ class RuntimeLayer const std::optional &getLayerDir() const { return layerDir; } + void setExtensionInfo(ExtensionRuntimeLayerInfo info) { extensionOf = info; } + + const std::optional &getExtensionInfo() const { return extensionOf; } + private: package::Reference reference; std::reference_wrapper runContext; std::optional layerDir; std::optional cachedItem; bool temporary; + std::optional extensionOf; }; class RunContext @@ -85,7 +95,7 @@ class RunContext std::optional baseLayer; std::optional runtimeLayer; std::optional appLayer; - std::vector extensionLayers; + std::list extensionLayers; std::string targetId; std::optional appOutput; @@ -94,6 +104,7 @@ class RunContext std::string containerID; std::filesystem::path bundle; + std::map environment; }; } // namespace linglong::runtime diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 59078a382..0dffcd596 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -315,6 +315,20 @@ ContainerCfgBuilder::forwardEnv(const std::vector &envList) noexcep return *this; } +ContainerCfgBuilder & +ContainerCfgBuilder::appendEnv(const std::map &envMap) noexcept +{ + for (const auto &[key, value] : envMap) { + if (envAppend.find(key) != envAppend.end()) { + std::cerr << "env " << key << " is already exist"; + } else { + envAppend[key] = value; + } + } + + return *this; +} + ContainerCfgBuilder &ContainerCfgBuilder::bindHostRoot() noexcept { hostRootMount = { @@ -1145,6 +1159,10 @@ bool ContainerCfgBuilder::buildEnv() noexcept } } + for (const auto &[key, value] : envAppend) { + environment[key] = value; + } + if (appPath) { environment["LINGLONG_APPID"] = appId; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 929bc0513..dc26b2c4a 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -128,6 +128,7 @@ class ContainerCfgBuilder ContainerCfgBuilder &forwardDefaultEnv() noexcept; ContainerCfgBuilder &forwardEnv(const std::vector &envList = {}) noexcept; + ContainerCfgBuilder &appendEnv(const std::map &envMap) noexcept; ContainerCfgBuilder &bindHostRoot() noexcept; ContainerCfgBuilder &bindHostStatics() noexcept; @@ -255,6 +256,7 @@ class ContainerCfgBuilder // environment std::unordered_set envForward; std::unordered_map environment; + std::unordered_map envAppend; std::optional envMount; // home dir From a8127f77def01e51d7aa328f4311f508fd3cf12a Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 27 May 2025 14:53:25 +0800 Subject: [PATCH 016/366] feat: prune support extension Signed-off-by: reddevillg --- .../src/linglong/extension/extension.cpp | 14 +++---- .../src/linglong/extension/extension.h | 5 ++- .../package_manager/package_manager.cpp | 37 +++++++++++++++++++ .../src/linglong/runtime/run_context.cpp | 3 +- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/libs/linglong/src/linglong/extension/extension.cpp b/libs/linglong/src/linglong/extension/extension.cpp index 9c48d3b4f..ad9753ba6 100644 --- a/libs/linglong/src/linglong/extension/extension.cpp +++ b/libs/linglong/src/linglong/extension/extension.cpp @@ -13,17 +13,15 @@ namespace linglong::extension { ExtensionIf::~ExtensionIf() { } -ExtensionIf *ExtensionFactory::makeExtension(const std::string &name) +std::unique_ptr ExtensionFactory::makeExtension(const std::string &name) { - if (name == ExtensionImplNVIDIADisplayDriver::name) { - return new ExtensionImplNVIDIADisplayDriver(); + if (name == ExtensionImplNVIDIADisplayDriver::Identify) { + return std::make_unique(); } - return new ExtensionImplDummy(); + return std::make_unique(); } -std::string ExtensionImplNVIDIADisplayDriver::name = "org.deepin.driver.display.nvidia"; - ExtensionImplNVIDIADisplayDriver::ExtensionImplNVIDIADisplayDriver() { driverName = hostDriverEnable(); @@ -31,12 +29,12 @@ ExtensionImplNVIDIADisplayDriver::ExtensionImplNVIDIADisplayDriver() bool ExtensionImplNVIDIADisplayDriver::shouldEnable(std::string &extensionName) { - if (extensionName != name) { + if (extensionName != Identify) { return false; } if (!driverName.empty()) { - extensionName = name + "." + driverName; + extensionName = std::string(Identify) + "." + driverName; return true; } diff --git a/libs/linglong/src/linglong/extension/extension.h b/libs/linglong/src/linglong/extension/extension.h index b6e66862f..f8b2044b5 100644 --- a/libs/linglong/src/linglong/extension/extension.h +++ b/libs/linglong/src/linglong/extension/extension.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace linglong::extension { @@ -26,7 +27,7 @@ class ExtensionIf class ExtensionFactory { public: - static ExtensionIf *makeExtension(const std::string &name); + static std::unique_ptr makeExtension(const std::string &name); }; class ExtensionImplNVIDIADisplayDriver : public ExtensionIf @@ -38,7 +39,7 @@ class ExtensionImplNVIDIADisplayDriver : public ExtensionIf bool shouldEnable(std::string &extensionName) override; - static std::string name; + static constexpr auto Identify = "org.deepin.driver.display.nvidia"; private: std::string hostDriverEnable(); diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 67121c61e..930435561 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -13,6 +13,7 @@ #include "linglong/api/types/v1/PackageManager1PruneResult.hpp" #include "linglong/api/types/v1/Repo.hpp" #include "linglong/api/types/v1/State.hpp" +#include "linglong/extension/extension.h" #include "linglong/package/layer_file.h" #include "linglong/package/layer_packager.h" #include "linglong/package/reference.h" @@ -2080,6 +2081,39 @@ PackageManager::Prune(std::vector &removed) noexc } std::unordered_map target; + + auto scanExtensionsByInfo = [&target, this](const api::types::v1::PackageInfoV2 &info) { + if (info.extensions) { + for (const auto &extension : *info.extensions) { + std::string name = extension.name; + auto ext = extension::ExtensionFactory::makeExtension(name); + if (!ext->shouldEnable(name)) { + continue; + } + + auto fuzzyRef = + package::FuzzyReference::create(QString::fromStdString(info.channel), + QString::fromStdString(name), + QString::fromStdString(extension.version), + std::nullopt); + auto ref = repo.clearReference( + *fuzzyRef, + { .forceRemote = false, .fallbackToRemote = false, .semanticMatching = true }); + if (ref) { + target[*ref] += 1; + } + } + } + }; + auto scanExtensionsByRef = [scanExtensionsByInfo, this](package::Reference &ref) { + auto item = this->repo.getLayerItem(ref); + if (!item) { + qWarning() << item.error().message(); + return; + } + scanExtensionsByInfo(item->info); + }; + for (const auto &info : *pkgsInfo) { if (info.packageInfoV2Module != "binary" && info.packageInfoV2Module != "runtime") { continue; @@ -2115,6 +2149,7 @@ PackageManager::Prune(std::vector &removed) noexc continue; } target[*runtimeRef] += 1; + scanExtensionsByRef(*runtimeRef); } auto baseFuzzyRef = package::FuzzyReference::parse(QString::fromStdString(info.base)); @@ -2134,6 +2169,8 @@ PackageManager::Prune(std::vector &removed) noexc continue; } target[*baseRef] += 1; + scanExtensionsByRef(*baseRef); + scanExtensionsByInfo(info); } for (const auto &it : target) { diff --git a/libs/linglong/src/linglong/runtime/run_context.cpp b/libs/linglong/src/linglong/runtime/run_context.cpp index 65bb8784c..ad5bcd6bf 100644 --- a/libs/linglong/src/linglong/runtime/run_context.cpp +++ b/libs/linglong/src/linglong/runtime/run_context.cpp @@ -373,8 +373,7 @@ utils::error::Result RunContext::resolveExtension(RuntimeLayer &layer) } std::string name = extension.name; - std::shared_ptr ext( - extension::ExtensionFactory::makeExtension(name)); + auto ext = extension::ExtensionFactory::makeExtension(name); if (!ext->shouldEnable(name)) { continue; } From 3e9f0b890292cfac39e666bff16a8d1aacdf6576 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 27 May 2025 13:43:54 +0800 Subject: [PATCH 017/366] fix: enable self adjust mount in builder run If the current RunContext contains innerBinds, self-adjust mount must be enabled; otherwise, execution may fail due to missing mount points. Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 8370e6d6c..93e13721a 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1879,7 +1879,8 @@ utils::error::Result Builder::run(const QStringList &modules, .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .addExtraMounts(applicationMounts); + .addExtraMounts(applicationMounts) + .enableSelfAdjustingMount(); if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); @@ -2010,7 +2011,8 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", .options = { { "rbind", "ro" } }, .source = ldConfPath, - .type = "bind" }); + .type = "bind" }) + .enableSelfAdjustingMount(); // write ld.so.conf std::string triplet = ref.arch.getTriplet().toStdString(); From 1fc517735b8aef648a99f7e8811207d352de194f Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 28 May 2025 14:47:01 +0800 Subject: [PATCH 018/366] fix: remove unused code Signed-off-by: reddevillg --- .../linglong/runtime/container_builder.cpp | 339 ------------------ 1 file changed, 339 deletions(-) diff --git a/libs/linglong/src/linglong/runtime/container_builder.cpp b/libs/linglong/src/linglong/runtime/container_builder.cpp index 2f57c4bcc..de670b2ad 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.cpp +++ b/libs/linglong/src/linglong/runtime/container_builder.cpp @@ -6,347 +6,8 @@ #include "linglong/runtime/container_builder.h" -#include "linglong/api/types/v1/ApplicationConfiguration.hpp" -#include "linglong/oci-cfg-generators/builtins.h" -#include "linglong/utils/configure.h" -#include "linglong/utils/error/error.h" -#include "linglong/utils/finally/finally.h" -#include "linglong/utils/serialize/json.h" -#include "linglong/utils/serialize/yaml.h" -#include "ocppi/runtime/config/types/Generators.hpp" -#include "ocppi/runtime/config/types/Mount.hpp" - -#include -#include -#include - -#include -#include - -#include - namespace linglong::runtime { -namespace { -auto getPatchesForApplication(const QString &appID) noexcept - -> std::vector -{ - auto filePath = - QStandardPaths::locate(QStandardPaths::ConfigLocation, "linglong/" + appID + "/config.yaml"); - if (filePath.isEmpty()) { - return {}; - } - - LINGLONG_TRACE(QString("get OCI patches for application %1").arg(appID)); - - auto config = - utils::serialize::LoadYAMLFile(filePath); - if (!config) { - qWarning() << LINGLONG_ERRV(config); - Q_ASSERT(false); - return {}; - } - - if (!config->permissions) { - return {}; - } - - if (!config->permissions->binds) { - return {}; - } - - std::vector patches; - patches.reserve(config->permissions->binds->size()); - - for (const auto &bind : *config->permissions->binds) { - patches.push_back({ - .ociVersion = "1.0.1", - .patch = nlohmann::json::array({ - { "op", "add" }, - { "path", "/mounts/-" }, - { "value", - { { "source", bind.source }, - { "destination", bind.destination }, - { "options", - nlohmann::json::array({ - "rbind", - "nosuid", - "nodev", - }) } } }, - }), - }); - } - - return patches; -} - -void applyJSONPatch(nlohmann::json &cfg, - const api::types::v1::OciConfigurationPatch &patch) noexcept -{ - LINGLONG_TRACE("apply oci runtime config patch"); - - try { - cfg = cfg.patch(patch.patch); - } catch (...) { - qCritical() << LINGLONG_ERRV("apply patch", std::current_exception()); - Q_ASSERT(false); - return; - } -} - -void applyJSONFilePatch(ocppi::runtime::config::types::Config &cfg, const QFileInfo &info) noexcept -{ - LINGLONG_TRACE(QString("apply oci runtime config patch file %1").arg(info.absoluteFilePath())); - - auto patch = utils::serialize::LoadJSONFile( - info.absoluteFilePath()); - if (!patch) { - qWarning() << LINGLONG_ERRV(patch); - Q_ASSERT(false); - return; - } - - if (cfg.ociVersion != patch->ociVersion) { - qWarning() << "ociVersion mismatched:" - << nlohmann::json(*patch).dump(-1, ' ', true).c_str(); - Q_ASSERT(false); - return; - } - - auto raw = nlohmann::json(cfg); - applyJSONPatch(raw, *patch); - cfg = raw.get(); -} - -void applyExecutablePatch(ocppi::runtime::config::types::Config &cfg, - const QFileInfo &info) noexcept -{ - LINGLONG_TRACE(QString("process oci configuration generator %1").arg(info.absoluteFilePath())); - - QProcess generatorProcess; - generatorProcess.setProgram(info.absoluteFilePath()); - generatorProcess.start(); - generatorProcess.write(QByteArray::fromStdString(nlohmann::json(cfg).dump())); - generatorProcess.closeWriteChannel(); - - constexpr auto timeout = 200; - if (!generatorProcess.waitForFinished(timeout)) { - qCritical() << LINGLONG_ERRV(generatorProcess.errorString(), generatorProcess.error()); - Q_ASSERT(false); - return; - } - - auto error = generatorProcess.readAllStandardError(); - if (generatorProcess.exitCode() != 0) { - qCritical() << "generator" << info.absoluteFilePath() << "return" - << generatorProcess.exitCode() << "\ninput:\n" - << nlohmann::json(cfg).dump().c_str() << "\n\nstderr:\n" - << qPrintable(error); - Q_ASSERT(false); - return; - } - if (not error.isEmpty()) { - qDebug() << "generator" << info.absoluteFilePath() << "stderr:" << error; - } - - auto result = generatorProcess.readAllStandardOutput(); - auto modified = utils::serialize::LoadJSON(result); - if (!modified) { - qCritical() << LINGLONG_ERRV("parse stdout", modified); - Q_ASSERT(false); - return; - } - - cfg = *modified; -} - -void applyPatches(ocppi::runtime::config::types::Config &cfg, const QFileInfoList &patches) noexcept -{ - const auto &builtins = linglong::generator::builtin_generators(); - for (const auto &info : patches) { - if (!info.isFile()) { - qWarning() << "info is not file:" << info.absoluteFilePath(); - continue; - } - - if (info.completeSuffix() == "json") { - applyJSONFilePatch(cfg, info); - continue; - } - - if (info.isExecutable()) { - applyExecutablePatch(cfg, info); - continue; - } - - auto gen = builtins.find(info.completeBaseName().toStdString()); - if (gen == builtins.cend()) { - qDebug() << "unsupported generator:" << info.absoluteFilePath(); - continue; - } - - if (!gen->second->generate(cfg)) { - qDebug() << "builtin generator failed:" << gen->first.data(); - } - } -} - -void applyPatches(ocppi::runtime::config::types::Config &cfg, - const std::vector &patches) noexcept -{ - auto raw = nlohmann::json(cfg); - for (const auto &patch : patches) { - if (patch.ociVersion != cfg.ociVersion) { - qWarning() << "ociVersion mismatched: " - << nlohmann::json(patch).dump(-1, ' ', true).c_str(); - continue; - } - - applyJSONPatch(raw, patch); - } - - cfg = raw.get(); -} - -auto fixMount(ocppi::runtime::config::types::Config config) noexcept - -> utils::error::Result -{ - - LINGLONG_TRACE("fix mount points.") - - if (!config.mounts || !config.root) { - return config; - } - - auto originalRoot = QDir{ QString::fromStdString(config.root.value().path) }; - config.root = { { .path = "rootfs", .readonly = false } }; - - auto &mounts = config.mounts.value(); - auto commonParent = [](const QString &path1, const QString &path2) { - QString ret = path2; - while (!path1.startsWith(ret)) { - ret.chop(1); - } - if (ret.isEmpty()) { - return ret; - } - while (!ret.endsWith('/')) { - ret.chop(1); - } - return QDir::cleanPath(ret); - }; - - QStringList tmpfsPath; - for (const auto &mount : mounts) { - if (mount.destination.empty() || mount.destination.at(0) != '/') { - continue; - } - - auto hostSource = QDir::cleanPath( - originalRoot.filePath(QString::fromStdString(mount.destination.substr(1)))); - if (QFileInfo::exists(hostSource)) { - continue; - } - - auto elem = hostSource.split(QDir::separator()); - while (!elem.isEmpty() && !QFile::exists(elem.join(QDir::separator()))) { - elem.removeLast(); - } - - if (elem.isEmpty()) { - qWarning() << "invalid host source:" << hostSource; - continue; - } - - bool newTmp{ true }; - auto existsPath = elem.join(QDir::separator()); - auto originalRootPath = QDir::cleanPath(originalRoot.absolutePath()); - if (existsPath <= originalRootPath) { - continue; - } - - for (const auto &it : tmpfsPath) { - if (existsPath == it) { - newTmp = false; - break; - } - } - - if (newTmp) { - tmpfsPath.push_back(existsPath); - } - } - - using MountType = std::remove_reference_t::value_type; - const auto rootBinds = - originalRoot.entryInfoList(QDir::Dirs | QDir::Files | QDir::System | QDir::NoDotAndDotDot); - auto pos = mounts.begin(); - for (const auto &bind : rootBinds) { - auto mountPoint = MountType{ - .destination = ("/" + bind.fileName()).toStdString(), - .gidMappings = {}, - .options = { { "rbind", "ro" } }, - .source = bind.absoluteFilePath().toStdString(), - .type = "bind", - .uidMappings = {}, - }; - if (bind.isSymLink()) { - mountPoint.options->emplace_back("copy-symlink"); - } - pos = mounts.insert(pos, std::move(mountPoint)); - ++pos; - } - - for (const auto &tmpfs : tmpfsPath) { - pos = mounts.insert( - pos, - MountType{ - .destination = tmpfs.mid(originalRoot.absolutePath().size()).toStdString(), - .gidMappings = {}, - .options = { { "nodev", "nosuid", "mode=755" } }, - .source = "tmpfs", - .type = "tmpfs", - .uidMappings = {}, - }); - ++pos; - - auto dir = QDir{ tmpfs }; - for (const auto &rootDest : - dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::System | QDir::NoDotAndDotDot)) { - auto rootDestPath = rootDest.absoluteFilePath(); - auto destination = rootDestPath.mid(originalRoot.absolutePath().size()); - auto mountPoint = MountType{ - .destination = destination.toStdString(), - .gidMappings = {}, - .options = { { "rbind", "ro" } }, - .source = rootDestPath.toStdString(), - .type = "bind", - .uidMappings = {}, - }; - if (rootDest.isSymLink()) { - mountPoint.options->emplace_back("copy-symlink"); - } - pos = mounts.insert(pos, std::move(mountPoint)); - ++pos; - } - } - - // remove extra mount points - std::unordered_set dups; - for (auto it = mounts.crbegin(); it != mounts.crend(); ++it) { - if (dups.find(it->destination) != dups.end()) { - mounts.erase(std::next(it).base()); - continue; - } - - dups.insert(it->destination); - } - - return config; -}; - -} // namespace - ContainerBuilder::ContainerBuilder(ocppi::cli::CLI &cli) : cli(cli) { From 01455c39f2b3cb0b9b543882a80ce248b21d8369 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 28 May 2025 14:14:05 +0800 Subject: [PATCH 019/366] feat: support architecture specfied linglong.yaml 1. ll-builder use current directory as project directory. 2. Project yaml file(aka linglong.yaml) must reside within project directory or its subdirectories. 3. User can use -f option to specfy a project yaml file. 4. ll-builder will attempt to load project yaml file in the following order from the project root directory: - linglong..yaml (architecture-specific) - linglong.yaml (generic) Signed-off-by: reddevillg --- apps/ll-builder/src/main.cpp | 96 +++++++++++++------ .../utils/src/linglong/utils/serialize/yaml.h | 23 ++--- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index e174fdd52..f12f1ea6c 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -98,9 +98,10 @@ std::string validateNonEmptyString(const std::string ¶meter) } linglong::utils::error::Result -parseProjectConfig(const QString &filename) +parseProjectConfig(const std::filesystem::path &filename) { - LINGLONG_TRACE(QString("parse project config %1").arg(filename)); + LINGLONG_TRACE("parse project config " + QString::fromStdString(filename)); + std::cerr << "Using project file " + filename.string() << std::endl; auto project = linglong::utils::serialize::LoadYAMLFile(filename); if (!project) { @@ -149,6 +150,45 @@ parseProjectConfig(const QString &filename) return project; } +linglong::utils::error::Result +getProjectYAMLPath(const std::filesystem::path &projectDir, const std::string &usePath) +{ + LINGLONG_TRACE("get project yaml path"); + + std::error_code ec; + if (!usePath.empty()) { + std::filesystem::path path = std::filesystem::canonical(usePath, ec); + if (ec) { + return LINGLONG_ERR(QString("invalid file path %1 error: %2") + .arg(usePath.c_str()) + .arg(ec.message().c_str())); + } + return path; + } + + auto arch = linglong::package::Architecture::currentCPUArchitecture(); + if (arch && *arch != linglong::package::Architecture()) { + std::filesystem::path path = + projectDir / ("linglong." + arch->toString().toStdString() + ".yaml"); + if (std::filesystem::exists(path, ec)) { + return path; + } + if (ec) { + return LINGLONG_ERR(QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); + } + } + + std::filesystem::path path = projectDir / "linglong.yaml"; + if (std::filesystem::exists(path, ec)) { + return path; + } + if (ec) { + return LINGLONG_ERR(QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); + } + + return LINGLONG_ERR("project yaml file not found"); +} + int handleCreate(const CreateCommandOptions &options) { qInfo() << "Handling create for project:" << QString::fromStdString(options.projectName); @@ -607,22 +647,6 @@ std::vector getProjectModule(const linglong::api::types::v1::Builde return { modules.begin(), modules.end() }; } -std::optional getProjectDir(std::filesystem::path &yamlPath) -{ - std::error_code ec; - std::filesystem::path path = std::filesystem::canonical(yamlPath, ec); - if (ec) { - qCritical() << "invalid project file path: " << QString::fromStdString(yamlPath.string()) - << " error: " << ec.message().c_str(); - return std::nullopt; - } - - QDir projectDir(QString::fromStdString(path.parent_path().string())); - // put canonical path back - yamlPath = path; - return std::make_optional(projectDir); -} - std::optional backupFailedMigrationRepo(const std::filesystem::path &repoPath) { @@ -707,14 +731,13 @@ You can report bugs to the linyaps team under this project: https://github.com/O ->check(validatorString); // add builder build - std::string filePath{ "./linglong.yaml" }; + std::string filePath; // group empty will hide command std::string hiddenGroup = ""; auto buildBuilder = commandParser.add_subcommand("build", _("Build a linyaps project")); buildBuilder->usage(_("Usage: ll-builder build [OPTIONS] [COMMAND...]")); buildBuilder->add_option("-f, --file", filePath, _("File path of the linglong.yaml")) ->type_name("FILE") - ->capture_default_str() ->check(CLI::ExistingFile); buildBuilder->add_option( "COMMAND", @@ -756,7 +779,6 @@ You can report bugs to the linyaps team under this project: https://github.com/O buildRun->usage(_("Usage: ll-builder run [OPTIONS] [COMMAND...]")); buildRun->add_option("-f, --file", filePath, _("File path of the linglong.yaml")) ->type_name("FILE") - ->capture_default_str() ->check(CLI::ExistingFile); buildRun ->add_option("--modules", @@ -784,7 +806,6 @@ You can report bugs to the linyaps team under this project: https://github.com/O buildExport->add_option("-f, --file", filePath, _("File path of the linglong.yaml")) ->type_name("FILE") - ->capture_default_str() ->check(CLI::ExistingFile); buildExport ->add_option("-z, --compressor", @@ -823,7 +844,6 @@ You can report bugs to the linyaps team under this project: https://github.com/O buildPush->usage(_("Usage: ll-builder push [OPTIONS]")); buildPush->add_option("-f, --file", filePath, _("File path of the linglong.yaml")) ->type_name("FILE") - ->capture_default_str() ->check(CLI::ExistingFile); buildPush->add_option("--repo-url", pushOpts.repoOptions.repoUrl, _("Remote repo url")) ->type_name("URL") @@ -1023,21 +1043,37 @@ You can report bugs to the linyaps team under this project: https://github.com/O auto *containerBuilder = new linglong::runtime::ContainerBuilder(**ociRuntime); containerBuilder->setParent(QCoreApplication::instance()); - std::filesystem::path canonicalYamlPath{ filePath }; - auto optProjectDir = getProjectDir(canonicalYamlPath); - if (!optProjectDir) { + // use the current directory as the project(working) directory + std::error_code ec; + auto projectDir = std::filesystem::current_path(ec); + if (ec) { + std::cerr << "invalid current directory: " << ec.message() << std::endl; + return -1; + } + + auto canonicalYamlPath = getProjectYAMLPath(projectDir, filePath); + if (!canonicalYamlPath) { + std::cerr << canonicalYamlPath.error().message().toStdString() << std::endl; + return -1; + } + if (canonicalYamlPath->string().rfind(projectDir.string(), 0) != 0) { + std::cerr << "the project file " << canonicalYamlPath->string() + << " is not under the current project directory " << projectDir.string(); return -1; } - const auto &projectDir = *optProjectDir; - auto project = parseProjectConfig(QString::fromStdString(canonicalYamlPath.string())); + auto project = parseProjectConfig(*canonicalYamlPath); if (!project) { qCritical() << project.error(); return -1; } - linglong::builder::Builder builder(*project, projectDir, repo, *containerBuilder, *builderCfg); - builder.projectYamlFile = canonicalYamlPath; + linglong::builder::Builder builder(*project, + QDir(QString::fromStdString(projectDir)), + repo, + *containerBuilder, + *builderCfg); + builder.projectYamlFile = std::move(canonicalYamlPath).value(); if (buildBuilder->parsed()) { return handleBuild(builder, buildOpts); diff --git a/libs/utils/src/linglong/utils/serialize/yaml.h b/libs/utils/src/linglong/utils/serialize/yaml.h index bb8a85499..5732edffe 100644 --- a/libs/utils/src/linglong/utils/serialize/yaml.h +++ b/libs/utils/src/linglong/utils/serialize/yaml.h @@ -15,6 +15,10 @@ #include #include +#include +#include +#include +#include namespace linglong::utils::serialize { @@ -32,25 +36,16 @@ error::Result LoadYAML(Source &content) } template -error::Result LoadYAMLFile(const QString &filename) noexcept +error::Result LoadYAMLFile(const std::filesystem::path &filename) noexcept { LINGLONG_TRACE("load yaml from file"); - QFile file{ filename }; - - file.open(QFile::ReadOnly); - if (!file.isOpen()) { - return LINGLONG_ERR("open", file); - } - - Q_ASSERT(file.error() == QFile::NoError); - - auto content = file.readAll(); - if (file.error() != QFile::NoError) { - return LINGLONG_ERR("read all", file); + std::ifstream file_stream(filename); + if (!file_stream.is_open()) { + return LINGLONG_ERR("Failed to open file: " + QString::fromStdString(filename)); } - return LoadYAML(content); + return LoadYAML(file_stream); } } // namespace linglong::utils::serialize From 5916132cbf2b704a725ca7dbd80e09fc5f445e49 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 29 May 2025 09:52:18 +0800 Subject: [PATCH 020/366] doc: update ll-builder multiarch build Signed-off-by: reddevillg --- docs/pages/guide/ll-builder/multiarch.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/docs/pages/guide/ll-builder/multiarch.md b/docs/pages/guide/ll-builder/multiarch.md index 6d8e44f60..53e0c1c8c 100644 --- a/docs/pages/guide/ll-builder/multiarch.md +++ b/docs/pages/guide/ll-builder/multiarch.md @@ -26,31 +26,29 @@ ```txt 项目根目录/ -├── linglong.yaml # x86_64 架构配置文件 -├── arm64/ -│ └── linglong.yaml # arm64 架构配置文件 -├── loong64/ -│ └── linglong.yaml # loong64 架构配置文件 +├── linglong.x86_64.yaml # x86_64 架构配置文件 +├── linglong.arm64.yaml # arm64 架构配置文件 +├── linglong.loong64.yaml # loong64 架构配置文件 ├── src/ # 共享的源代码 └── resources/ # 共享的资源文件 ``` -将源代码、资源文件等放在项目根目录,各架构目录只存放差异化的配置文件 +将源代码、资源文件等放在项目根目录,不同架构的构建由对应架构的配置文件决定。 ### 构建命令示例 -构建指定架构的包: +ll-builder 会优先查找当前架构的项目配置文件,因此在不同架构的机器上执行 ll-builder 会自动使用当前架构对应的配置文件。如果架构配置文件不在默认位置,可以使用下面的方法指定配置文件的位置: ```bash # 构建 arm64 架构包 ll-builder -f arm64/linglong.yaml -``` -```bash # 构建 loongarch64 架构包 ll-builder -f loongarch64/linglong.yaml ``` +需要注意项目配置文件(即由 -f 指定的 linglong.yaml 文件),需要在项目目录(运行 ll-builder 的当前目录)的目录或者子目录下。 + ### 龙芯 龙芯新旧世界的差异可查看 [咱龙了吗](https://areweloongyet.com/docs/old-and-new-worlds/) @@ -67,7 +65,7 @@ ll-builder -f loongarch64/linglong.yaml 迁移步骤: -1. 准备一个新世界架构的机器并安装 deepin 或 uos 系统 -1. 在宿主机安装 `liblol-dkms` 内核模块 `apt install liblol-dkms` -1. 编写一个 linglong.yaml 文件,base 和 runtime 填写上文所属的版本号。 -1. 在 linglong.yaml 里解压旧世界应用的软件包,复制到$PREFIX 目录 +1. 准备一个新世界架构的机器并安装 deepin 或 uos 系统。 +2. 在宿主机安装 `liblol-dkms` 内核模块 `apt install liblol-dkms`。 +3. 编写一个 linglong.yaml 文件,base 和 runtime 填写上文所属的版本号。 +4. 在 linglong.yaml 里解压旧世界应用的软件包,复制到 `$PREFIX` 目录。 From 6e99856fd482c44a948996ba7f3c097fc7144f55 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 28 May 2025 18:08:47 +0800 Subject: [PATCH 021/366] fix: ensure bundle directory is clean Containers may fail to start if the bundle directory contains residual files or conflicts from previous run. Signed-off-by: reddevillg --- .../src/linglong/runtime/container_builder.h | 12 ++++++++++-- libs/linglong/src/linglong/runtime/run_context.cpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/libs/linglong/src/linglong/runtime/container_builder.h b/libs/linglong/src/linglong/runtime/container_builder.h index a99506e5c..ef852a8ee 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -38,8 +38,8 @@ inline std::string genContainerID(const package::Reference &ref) noexcept .toStdString(); } -// getBundleDir 用于获取容器的运行目录 -inline utils::error::Result getBundleDir(const std::string &containerID) +// Used to obtain a clean container bundle directory. +inline utils::error::Result makeBundleDir(const std::string &containerID) { LINGLONG_TRACE("get bundle dir"); @@ -48,6 +48,14 @@ inline utils::error::Result getBundleDir(const std::strin auto bundle = runtimeDir / "linglong" / containerID; std::error_code ec; + if (std::filesystem::exists(bundle, ec)) { + std::filesystem::remove_all(bundle, ec); + if (ec) { + qWarning() << QString("failed to remove bundle directory %1: %2") + .arg(bundle.c_str(), ec.message().c_str()); + } + } + if (!std::filesystem::create_directories(bundle, ec) && ec) { return LINGLONG_ERR(QString("failed to create bundle directory %1: %2") .arg(bundle.c_str(), ec.message().c_str())); diff --git a/libs/linglong/src/linglong/runtime/run_context.cpp b/libs/linglong/src/linglong/runtime/run_context.cpp index ad5bcd6bf..9c7e116bd 100644 --- a/libs/linglong/src/linglong/runtime/run_context.cpp +++ b/libs/linglong/src/linglong/runtime/run_context.cpp @@ -409,7 +409,7 @@ RunContext::fillContextCfg(linglong::generator::ContainerCfgBuilder &builder) return LINGLONG_ERR("run context doesn't resolved"); } - auto bundleDir = runtime::getBundleDir(containerID); + auto bundleDir = runtime::makeBundleDir(containerID); if (!bundleDir) { return LINGLONG_ERR("failed to get bundle dir of " + QString::fromStdString(containerID)); } From 59fbf35dea130484ca0542bfb73c0f42fdf214c4 Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 29 May 2025 11:24:25 +0800 Subject: [PATCH 022/366] feat: bind /etc/hosts to container Bind /etc/hosts to the container to facilitate network debugging. --- .../src/linglong/oci-cfg-generators/container_cfg_builder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 0dffcd596..b0f3c2ce3 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -365,6 +365,7 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindHostStatics() noexcept "/etc/localtime", "/etc/resolv.conf", "/etc/timezone", + "/etc/hosts" }; hostStaticsMount = std::vector{}; From 4ed2ad9216939f36d6a71956a21f1ab2e52f8325 Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 29 May 2025 11:46:11 +0800 Subject: [PATCH 023/366] feat: add /etc/hosts to old generators Bind /etc/hosts to the container to facilitate network debugging. --- .../src/linglong/oci-cfg-generators/90_legacy.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp index 24e020e64..df7466d4a 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp @@ -48,6 +48,8 @@ bool Legacy::generate(ocppi::runtime::config::types::Config &config) const noexc // repaired later. std::multimap roMountMap{ { "/etc/resolvconf", "/run/host/etc/resolvconf" }, + { "/etc/hosts", "/run/host/etc/hosts" }, + { "/etc/hosts", "/etc/hosts" }, { "/etc/machine-id", "/run/host/etc/machine-id" }, { "/etc/machine-id", "/etc/machine-id" }, { "/etc/ssl/certs", "/run/host/etc/ssl/certs" }, From ec9011598f8b0ff78466504ad2f9bad3f1238ff5 Mon Sep 17 00:00:00 2001 From: myml Date: Fri, 30 May 2025 16:13:03 +0800 Subject: [PATCH 024/366] docs: add instructions for download debug symbolsy Included detailed steps for accessing the container, locating the repository, and downloading the necessary debug symbol packages for system dependencies. This enhances the debugging process for applications relying on external libraries. --- docs/pages/guide/debug/debug.md | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/docs/pages/guide/debug/debug.md b/docs/pages/guide/debug/debug.md index 4df730888..4f6c63816 100644 --- a/docs/pages/guide/debug/debug.md +++ b/docs/pages/guide/debug/debug.md @@ -126,3 +126,47 @@ CONFIG += debug ``` cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外配置。其他构建工具可自定查询文档。 + +## 从debian仓库下载调试符号 + +由于base镜像中没有包含调试符号,如果需要调试应用的系统依赖库,需要从base对应的debian仓库手动下载调试符号包。具体步骤如下: + +1. 使用以下命令之一进入容器命令行环境: + ```bash + ll-builder run --bash + # 或 + ll-cli run $appid --bash + ``` + +2. 查看base镜像使用的仓库地址: + ```bash + cat /etc/apt/sources.list + ``` + +3. 在宿主机浏览器中打开仓库地址,定位依赖库的deb包所在目录: + - 使用命令 `apt-cache show | grep Filename` 查看deb包在仓库中的路径 + - 完整的下载地址为: 仓库地址 + deb包路径 + + 例如,要下载libgtk-3-0的调试符号包: + ```bash + apt-cache show libgtk-3-0 | grep Filename + # 输出: pool/main/g/gtk+3.0/libgtk-3-0_3.24.41-1deepin3_amd64.deb + # 完整目录: /pool/main/g/gtk+3.0/ + ``` + +4. 在该目录下寻找对应的调试符号包,通常有两种命名格式: + - `-dbgsym.deb` + - `-dbg.deb` + +5. 下载并解压调试符号包: + ```bash + dpkg-deb -R -dbgsym.deb /tmp/ + ``` + +6. 配置调试器查找调试符号: + 在上面的场景设置debug-file-directory时,追加解压的目录,用冒号分隔: + ``` + ${workspaceFolder}/linglong/output/develop/files/lib/debug:/tmp//usr/lib/debug + ``` + +这样调试器就能在解压的目录中找到系统依赖库的调试符号了。 \ No newline at end of file From 881f0d5b1e0f0fa085b5ab63cd11f277014f8b1d Mon Sep 17 00:00:00 2001 From: ComixHe Date: Fri, 30 May 2025 18:32:01 +0800 Subject: [PATCH 025/366] refactor: move gvfs envs to OstreeRepo ctor ensure that gvfs module wouldn't be loaded Signed-off-by: ComixHe --- apps/ll-builder/src/main.cpp | 12 ------------ libs/linglong/src/linglong/repo/ostree_repo.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index f12f1ea6c..a58f06b78 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -968,14 +968,6 @@ You can report bugs to the linyaps team under this project: https://github.com/O return -1; } - // To avoid glib start thread - // set GIO_USE_VFS to local and GVFS_REMOTE_VOLUME_MONITOR_IGNORE to 1 - auto gioGuard = - std::make_unique("GIO_USE_VFS", "local"); - auto gvfsGuard = std::make_unique( - "GVFS_REMOTE_VOLUME_MONITOR_IGNORE", - "1"); - auto result = linglong::repo::tryMigrate(builderCfg->repo, *repoCfg); if (result == linglong::repo::MigrateResult::Failed) { if (!backupFailedMigrationRepo(builderCfg->repo)) { @@ -993,10 +985,6 @@ You can report bugs to the linyaps team under this project: https://github.com/O linglong::repo::OSTreeRepo repo(repoRoot, *repoCfg, clientFactory); - // restore to original value - gioGuard.reset(); - gvfsGuard.reset(); - if (buildRepo->parsed()) { return handleRepo(repo, repoCmdOpts, diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 798a6f120..5f532312e 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -749,6 +749,14 @@ OSTreeRepo::OSTreeRepo(const QDir &path, qFatal("%s", msg.c_str()); } + // To avoid glib start thread + // set GIO_USE_VFS to local and GVFS_REMOTE_VOLUME_MONITOR_IGNORE to 1 + linglong::utils::command::EnvironmentVariableGuard gioGuard{ "GIO_USE_VFS", "local" }; + linglong::utils::command::EnvironmentVariableGuard gvfsGuard{ + "GVFS_REMOTE_VOLUME_MONITOR_IGNORE", + "1" + }; + g_autoptr(GError) gErr = nullptr; g_autoptr(GFile) repoPath = nullptr; g_autoptr(OstreeRepo) ostreeRepo = nullptr; From 286d413070c2c4b06b0175f8195bf2f02d9b213d Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 3 Jun 2025 16:28:23 +0800 Subject: [PATCH 026/366] fix: export desktop to a invalid export path 1. The custom desktop exported directory(CUSTOM_DATA_DIR) should only be in the share dir, not in the subdirectory; 2. LINGLONG_DATA_DIR should be exported; 3. need to update LINGLONG_EXPORT_VERSION to fix export. --- CMakeLists.txt | 37 +++++---- .../src/linglong/repo/ostree_repo.cpp | 13 ++-- libs/utils/src/linglong/utils/configure.h.in | 4 +- misc/lib/linglong/generate-xdg-data-dirs.sh | 75 ++++++++++++++----- 4 files changed, 88 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfab3d132..50b04f615 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,9 +53,18 @@ set(GETTEXT_DOMAIN_NAME "linyaps" CACHE STRING "The name of gettext domain.") set(QT_VERSION_MAJOR CACHE STRING "The major version of qt.") -set(LINGLONG_DESKTOP_EXPORT_PATH - "share/applications" - CACHE STRING "The path to export linglong desktop files.") +set(LINGLONG_EXPORT_PATH + "share" + CACHE STRING + "The path to export linglong config files, it must end with share.") + +if(NOT LINGLONG_EXPORT_PATH MATCHES ".*share$") + message( + WARNING + "LINGLONG_EXPORT_PATH '${LINGLONG_EXPORT_PATH}' must end with 'share'" + ) + set(LINGLONG_EXPORT_PATH "share") +endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(PFL) @@ -173,16 +182,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # build ll-build-utils only if(BUILD_LINGLONG_BUILDER_UTILS_IN_BOX) - pfl_init(AUTO) - pfl_add_libraries( - LIBS - api - ocppi - oci-cfg-generators - APPS - ll-builder-utils - uab) - return() + pfl_init(AUTO) + pfl_add_libraries( + LIBS + api + ocppi + oci-cfg-generators + APPS + ll-builder-utils + uab) + return() endif() set(CMAKE_AUTOMOC ON) @@ -275,7 +284,7 @@ pfl_add_libraries( ll-session-helper) if(ENABLE_LINGLONG_APP_BUILDER_UTILS) - add_subdirectory(apps/ll-builder-utils) + add_subdirectory(apps/ll-builder-utils) endif() add_subdirectory(misc) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 5f532312e..bfdce8950 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -2102,12 +2102,14 @@ OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, destination = rootEntriesDir / "lib/systemd/user"; } + auto desktopExportPath = std::string{ LINGLONG_EXPORT_PATH } + "/applications"; + if (path == "share/applications") { - if (strcmp(LINGLONG_DESKTOP_EXPORT_PATH, "share/applications") != 0) { + if (desktopExportPath != "share/applications") { qInfo() << "destination update from " << destination.c_str() << " to " - << QString::fromStdString(rootEntriesDir / LINGLONG_DESKTOP_EXPORT_PATH); + << QString::fromStdString(rootEntriesDir / desktopExportPath); } - destination = rootEntriesDir / LINGLONG_DESKTOP_EXPORT_PATH; + destination = rootEntriesDir / desktopExportPath; } // 检查源目录是否存在,跳过不存在的目录 @@ -2207,8 +2209,9 @@ void OSTreeRepo::updateSharedInfo() noexcept { auto defaultApplicationDir = QDir(this->repoDir.absoluteFilePath("entries/share/applications")); // 自定义desktop安装路径 - QDir customApplicationDir = QDir( - this->repoDir.absoluteFilePath(QString{ "entries/%1" }.arg(LINGLONG_DESKTOP_EXPORT_PATH))); + auto desktopExportPath = std::string{ LINGLONG_EXPORT_PATH } + "/applications"; + QDir customApplicationDir = + QDir(this->repoDir.absoluteFilePath(QString{ "entries/%1" }.arg(desktopExportPath.c_str()))); auto mimeDataDir = QDir(this->repoDir.absoluteFilePath("entries/share/mime")); auto glibSchemasDir = QDir(this->repoDir.absoluteFilePath("entries/share/glib-2.0/schemas")); diff --git a/libs/utils/src/linglong/utils/configure.h.in b/libs/utils/src/linglong/utils/configure.h.in index c3d23b2c2..4643085fc 100644 --- a/libs/utils/src/linglong/utils/configure.h.in +++ b/libs/utils/src/linglong/utils/configure.h.in @@ -21,9 +21,9 @@ #define LINGLONG_CONTAINER_INIT LINGLONG_LIBEXEC_DIR "/dumb-init" #define LINGLONG_CLIENT_NAME "@LINGLONG_CLI_BIN@" #define LINGLONG_CLIENT_PATH "@CMAKE_INSTALL_FULL_BINDIR@/@LINGLONG_CLI_BIN@" -#define LINGLONG_DESKTOP_EXPORT_PATH "@LINGLONG_DESKTOP_EXPORT_PATH@" +#define LINGLONG_EXPORT_PATH "@LINGLONG_EXPORT_PATH@" -#define LINGLONG_EXPORT_VERSION "1.0.0.1" +#define LINGLONG_EXPORT_VERSION "1.0.0.2" // The package's locale domain. #define PACKAGE_LOCALE_DOMAIN "@GETTEXT_DOMAIN_NAME@" diff --git a/misc/lib/linglong/generate-xdg-data-dirs.sh b/misc/lib/linglong/generate-xdg-data-dirs.sh index 31a33628a..485bfe0d2 100644 --- a/misc/lib/linglong/generate-xdg-data-dirs.sh +++ b/misc/lib/linglong/generate-xdg-data-dirs.sh @@ -10,25 +10,60 @@ # So we append the path to XDG_DATA_DIRS here like, # instead of prepending it like flatpak. +# --- 变量初始化和规范化 --- LINGLONG_ROOT="@LINGLONG_ROOT@" -LINGLONG_DESKTOP_EXPORT_PATH="@LINGLONG_DESKTOP_EXPORT_PATH@" - -LINGLONG_DATA_DIR=${LINGLONG_ROOT}/entries/share -CUSTOM_DESKTOP_DATA_DIR=${LINGLONG_ROOT}/entries/${LINGLONG_DESKTOP_EXPORT_PATH} - -if [ "$LINGLONG_DESKTOP_EXPORT_PATH" != "share/applications" ]; then - # 检查XDG_DATA_DIRS是否包含CUSTOM_DESKTOP_DATA_DIR - case ":$XDG_DATA_DIRS:" in - *":${CUSTOM_DESKTOP_DATA_DIR}:"* | *":${CUSTOM_DESKTOP_DATA_DIR}/:"*) ;; - *) - XDG_DATA_DIRS=$(echo "$XDG_DATA_DIRS" | sed -E "s@(/usr/local/share/?)(:|$)@\1:$CUSTOM_DESKTOP_DATA_DIR\2@g") - ;; - esac -else - case ":$XDG_DATA_DIRS:" in - *":$LINGLONG_DATA_DIR:"* | *":$LINGLONG_DATA_DIR/:"*) : ;; - *) - XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share:/usr/share}:${LINGLONG_DATA_DIR}" - ;; - esac +LINGLONG_EXPORT_PATH="@LINGLONG_EXPORT_PATH@" + +# 规范化 LINGLONG_DATA_DIR:移除末尾可能存在的斜杠 +LINGLONG_DATA_DIR="${LINGLONG_ROOT}/entries/share" +LINGLONG_DATA_DIR=${LINGLONG_DATA_DIR%/} + +# --- 辅助函数:安全地添加路径到 XDG_DATA_DIRS --- +# 这个函数会检查路径是否已存在,如果不存在则添加。 +# 参数1: 要添加的路径 (path_to_add) +# 参数2: 添加位置 ('start' 或 'end',默认为 'start') +_add_path_to_xdg_data_dirs() { + local path_to_add="${1%/}" # 确保要添加的路径没有末尾斜杠 + local position="${2:-start}" # 默认添加到开头 + + # 确保 XDG_DATA_DIRS 变量已定义,如果未定义则初始化为空字符串 + : "${XDG_DATA_DIRS:=}" + + # 检查路径是否已存在于 XDG_DATA_DIRS 中 + # 在 XDG_DATA_DIRS 两端加上冒号,以确保精确匹配(无论路径在开头、中间还是结尾) + if [[ ":${XDG_DATA_DIRS}:" == *":${path_to_add}:"* ]]; then + # 路径已存在,不执行任何操作 + return 0 + fi + + # 如果路径不存在,则根据指定位置添加 + if [[ -z "$XDG_DATA_DIRS" ]]; then + # 如果 XDG_DATA_DIRS 当前为空,直接赋值 + XDG_DATA_DIRS="$path_to_add" + elif [[ "$position" == "start" ]]; then + # 添加到开头 + XDG_DATA_DIRS="$path_to_add:$XDG_DATA_DIRS" + elif [[ "$position" == "end" ]]; then + # 添加到末尾 + XDG_DATA_DIRS="$XDG_DATA_DIRS:$path_to_add" + fi +} + +# 如果有自定义 LINGLONG_EXPORT_PATH(默认为 "share"),将自定义路径添加到 XDG_DATA_DIRS +if [ "$LINGLONG_EXPORT_PATH" != "share" ]; then + # 规范化 CUSTOM_DATA_DIR:移除末尾可能存在的斜杠 + CUSTOM_DATA_DIR="${LINGLONG_ROOT}/entries/${LINGLONG_EXPORT_PATH}" + CUSTOM_DATA_DIR=${CUSTOM_DATA_DIR%/} + _add_path_to_xdg_data_dirs "$CUSTOM_DATA_DIR" "start" fi + +# 2. 处理 LINGLONG_DATA_DIR 的添加逻辑 +# 如果 XDG_DATA_DIRS 为空,则先设置为 /usr/local/share:/usr/share, +# 然后再将 LINGLONG_DATA_DIR 添加到末尾。 +: "${XDG_DATA_DIRS:=/usr/local/share:/usr/share}" + +# 然后,将 LINGLONG_DATA_DIR 添加到 XDG_DATA_DIRS 的末尾(如果不存在) +_add_path_to_xdg_data_dirs "$LINGLONG_DATA_DIR" "end" + +# --- 清理辅助函数 --- +unset -f _add_path_to_xdg_data_dirs From 975aa956f84f6e6a0501f01f2c391ae3d1b7645d Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 29 May 2025 13:08:10 +0800 Subject: [PATCH 027/366] chore: Development cycle for version 1.9.0 Signed-off-by: reddevillg --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50b04f615..dc4e664e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.11.4) project( linglong - VERSION 1.8.0 + VERSION 1.9.0 DESCRIPTION "a container based application package manager for Linux desktop" HOMEPAGE_URL "https://github.com/OpenAtom-Linyaps/linyaps" LANGUAGES CXX C) From c6386bdfe53baa72520d7aa243be108e4c2a9888 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 30 May 2025 18:27:28 +0800 Subject: [PATCH 028/366] feat: modify the way container patches work 1. provide application level patches 2. application level patches will apply after global patches move configure.h.in to src root, becasue lib utils depends on QT, we don't want to introduce QT in certain scenarios. Signed-off-by: reddevillg --- CMakeLists.txt | 7 +- apps/ll-builder/src/main.cpp | 8 +- apps/ll-cli/src/main.cpp | 2 +- apps/ll-dialog/src/main.cpp | 2 +- apps/ll-package-manager/src/main.cpp | 2 +- .../utils/configure.h.in => configure.h.in | 0 .../src/linglong/builder/linglong_builder.cpp | 2 +- .../src/linglong/builder/source_fetcher.cpp | 2 +- libs/linglong/src/linglong/cli/cli.cpp | 2 +- .../src/linglong/package/uab_packager.cpp | 2 +- .../package_manager/package_manager.cpp | 2 +- .../src/linglong/repo/client_factory.h | 2 +- libs/linglong/src/linglong/repo/migrate.cpp | 2 +- .../linglong/src/linglong/repo/repo_cache.cpp | 2 +- .../src/linglong/runtime/container.cpp | 2 +- .../container_cfg_builder.cpp | 274 +++++++++++++++++- .../container_cfg_builder.h | 12 + libs/utils/CMakeLists.txt | 2 - libs/utils/src/linglong/utils/configure.cpp | 7 - .../src/linglong/utils/global/initialize.cpp | 2 +- misc/lib/linglong/container/README.md | 55 +++- 21 files changed, 347 insertions(+), 44 deletions(-) rename libs/utils/src/linglong/utils/configure.h.in => configure.h.in (100%) delete mode 100644 libs/utils/src/linglong/utils/configure.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index dc4e664e9..bb6c540a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,11 @@ endfunction() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +include(GNUInstallDirs) +# depends on GNUInstallDirs +configure_file(configure.h.in ${CMAKE_CURRENT_BINARY_DIR}/configure.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + # build ll-build-utils only if(BUILD_LINGLONG_BUILDER_UTILS_IN_BOX) pfl_init(AUTO) @@ -264,8 +269,6 @@ pfl_init(AUTO) add_subdirectory(external/http) add_subdirectory(tools/qdbusxml2cpp) -include(GNUInstallDirs) - pfl_add_libraries( LIBS api diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index a58f06b78..d01157446 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -5,6 +5,7 @@ */ #include "command_options.h" +#include "configure.h" #include "linglong/builder/config.h" #include "linglong/builder/linglong_builder.h" #include "linglong/cli/cli.h" @@ -14,7 +15,6 @@ #include "linglong/repo/config.h" #include "linglong/repo/migrate.h" #include "linglong/utils/command/env.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/gettext.h" #include "linglong/utils/global/initialize.h" @@ -174,7 +174,8 @@ getProjectYAMLPath(const std::filesystem::path &projectDir, const std::string &u return path; } if (ec) { - return LINGLONG_ERR(QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); + return LINGLONG_ERR( + QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); } } @@ -183,7 +184,8 @@ getProjectYAMLPath(const std::filesystem::path &projectDir, const std::string &u return path; } if (ec) { - return LINGLONG_ERR(QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); + return LINGLONG_ERR( + QString("path %1 error: %2").arg(path.c_str()).arg(ec.message().c_str())); } return LINGLONG_ERR("project yaml file not found"); diff --git a/apps/ll-cli/src/main.cpp b/apps/ll-cli/src/main.cpp index a49ab7a63..519e851dd 100644 --- a/apps/ll-cli/src/main.cpp +++ b/apps/ll-cli/src/main.cpp @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: LGPL-3.0-or-later */ +#include "configure.h" #include "linglong/api/dbus/v1/dbus_peer.h" #include "linglong/cli/cli.h" #include "linglong/cli/cli_printer.h" @@ -13,7 +14,6 @@ #include "linglong/repo/config.h" #include "linglong/repo/ostree_repo.h" #include "linglong/runtime/container_builder.h" -#include "linglong/utils/configure.h" #include "linglong/utils/finally/finally.h" #include "linglong/utils/gettext.h" #include "linglong/utils/global/initialize.h" diff --git a/apps/ll-dialog/src/main.cpp b/apps/ll-dialog/src/main.cpp index a5e55de5c..612c6927b 100644 --- a/apps/ll-dialog/src/main.cpp +++ b/apps/ll-dialog/src/main.cpp @@ -3,7 +3,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "cache_dialog.h" -#include "linglong/utils/configure.h" +#include "configure.h" #include "linglong/utils/gettext.h" #include "permissionDialog.h" #include "tl/expected.hpp" diff --git a/apps/ll-package-manager/src/main.cpp b/apps/ll-package-manager/src/main.cpp index eeb026cd2..e860b00ab 100644 --- a/apps/ll-package-manager/src/main.cpp +++ b/apps/ll-package-manager/src/main.cpp @@ -4,12 +4,12 @@ * SPDX-License-Identifier: LGPL-3.0-or-later */ +#include "configure.h" #include "linglong/adaptors/package_manager/package_manager1.h" #include "linglong/package_manager/package_manager.h" #include "linglong/repo/config.h" #include "linglong/repo/migrate.h" #include "linglong/repo/ostree_repo.h" -#include "linglong/utils/configure.h" #include "linglong/utils/dbus/register.h" #include "linglong/utils/global/initialize.h" #include "ocppi/cli/CLI.hpp" diff --git a/libs/utils/src/linglong/utils/configure.h.in b/configure.h.in similarity index 100% rename from libs/utils/src/linglong/utils/configure.h.in rename to configure.h.in diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 93e13721a..78e9ba794 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -6,6 +6,7 @@ #include "linglong_builder.h" +#include "configure.h" #include "linglong/api/types/v1/ExportDirs.hpp" #include "linglong/api/types/v1/Generators.hpp" #include "linglong/builder/printer.h" @@ -18,7 +19,6 @@ #include "linglong/repo/ostree_repo.h" #include "linglong/runtime/container.h" #include "linglong/utils/command/env.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/file.h" #include "linglong/utils/global/initialize.h" diff --git a/libs/linglong/src/linglong/builder/source_fetcher.cpp b/libs/linglong/src/linglong/builder/source_fetcher.cpp index fc8b00165..6828bb5ec 100644 --- a/libs/linglong/src/linglong/builder/source_fetcher.cpp +++ b/libs/linglong/src/linglong/builder/source_fetcher.cpp @@ -6,8 +6,8 @@ #include "source_fetcher.h" +#include "configure.h" #include "linglong/utils/command/env.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/global/initialize.h" diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index eae6ef75a..20818e50e 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -6,6 +6,7 @@ #include "linglong/cli/cli.h" +#include "configure.h" #include "linglong/api/dbus/v1/dbus_peer.h" #include "linglong/api/types/v1/InteractionReply.hpp" #include "linglong/api/types/v1/InteractionRequest.hpp" @@ -27,7 +28,6 @@ #include "linglong/package/reference.h" #include "linglong/runtime/container_builder.h" #include "linglong/runtime/run_context.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" #include "linglong/utils/gettext.h" diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 34c08eb86..12cc1a5e7 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -4,12 +4,12 @@ #include "linglong/package/uab_packager.h" +#include "configure.h" #include "linglong/api/types/v1/Generators.hpp" #include "linglong/api/types/v1/UabLayer.hpp" #include "linglong/api/types/v1/Version.hpp" #include "linglong/package/architecture.h" #include "linglong/utils/command/env.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/file.h" #include "linglong/utils/serialize/json.h" diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 930435561..f0c55b528 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -6,6 +6,7 @@ #include "package_manager.h" +#include "configure.h" #include "linglong/api/types/helper.h" #include "linglong/api/types/v1/Generators.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" @@ -23,7 +24,6 @@ #include "linglong/repo/ostree_repo.h" #include "linglong/runtime/run_context.h" #include "linglong/utils/command/env.h" -#include "linglong/utils/configure.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" #include "linglong/utils/packageinfo_handler.h" diff --git a/libs/linglong/src/linglong/repo/client_factory.h b/libs/linglong/src/linglong/repo/client_factory.h index 6f4cea647..6f6bf8557 100644 --- a/libs/linglong/src/linglong/repo/client_factory.h +++ b/libs/linglong/src/linglong/repo/client_factory.h @@ -10,7 +10,7 @@ extern "C" { #include "api/ClientAPI.h" } -#include "linglong/utils/configure.h" +#include "configure.h" #include #include diff --git a/libs/linglong/src/linglong/repo/migrate.cpp b/libs/linglong/src/linglong/repo/migrate.cpp index c1616abbf..1a00e4565 100644 --- a/libs/linglong/src/linglong/repo/migrate.cpp +++ b/libs/linglong/src/linglong/repo/migrate.cpp @@ -4,9 +4,9 @@ #include "migrate.h" +#include "configure.h" #include "linglong/package/version.h" #include "linglong/repo/config.h" -#include "linglong/utils/configure.h" #include #include diff --git a/libs/linglong/src/linglong/repo/repo_cache.cpp b/libs/linglong/src/linglong/repo/repo_cache.cpp index 5dbd78f75..3069a69e4 100644 --- a/libs/linglong/src/linglong/repo/repo_cache.cpp +++ b/libs/linglong/src/linglong/repo/repo_cache.cpp @@ -6,8 +6,8 @@ #include "repo_cache.h" +#include "configure.h" #include "linglong/package/version.h" -#include "linglong/utils/configure.h" #include "linglong/utils/packageinfo_handler.h" #include "linglong/utils/serialize/json.h" diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index ae4d175a3..906b9b6fb 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -6,7 +6,7 @@ #include "linglong/runtime/container.h" -#include "linglong/utils/configure.h" +#include "configure.h" #include "linglong/utils/finally/finally.h" #include "ocppi/runtime/RunOption.hpp" #include "ocppi/runtime/config/types/Generators.hpp" diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index b0f3c2ce3..a768b621d 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -6,13 +6,19 @@ #include "linglong/oci-cfg-generators/container_cfg_builder.h" +#include "configure.h" +#include "linglong/api/types/v1/Generators.hpp" +#include "linglong/api/types/v1/OciConfigurationPatch.hpp" #include "ocppi/runtime/config/types/Generators.hpp" +#include #include #include +#include #include #include +#include #include extern char **environ; @@ -320,7 +326,7 @@ ContainerCfgBuilder::appendEnv(const std::map &envMap) { for (const auto &[key, value] : envMap) { if (envAppend.find(key) != envAppend.end()) { - std::cerr << "env " << key << " is already exist"; + std::cerr << "env " << key << " is already exist" << std::endl; } else { envAppend[key] = value; } @@ -970,7 +976,7 @@ bool ContainerCfgBuilder::buildMountIPC() noexcept } if (buf.st_uid != ::getuid()) { - std::cerr << hostXDGRuntimeDir << " doesn't belong to current user."; + std::cerr << hostXDGRuntimeDir << " doesn't belong to current user." << std::endl; return; } @@ -1204,6 +1210,248 @@ bool ContainerCfgBuilder::buildEnv() noexcept return true; } +bool ContainerCfgBuilder::applyPatch() noexcept +{ + if (!applyPatchEnabled) { + return true; + } + + std::filesystem::path containerConfigPath{ LINGLONG_INSTALL_PREFIX + "/lib/linglong/container/config.d" }; + std::error_code ec; + if (!std::filesystem::exists(containerConfigPath, ec)) { + // if no-exists or failed to check exists, ignore it + return true; + } + + std::vector globalPatchFiles; + std::vector appPatchFiles; + auto iter = std::filesystem::directory_iterator{ + containerConfigPath, + std::filesystem::directory_options::skip_permission_denied, + ec + }; + if (ec) { + error_.reason = + "failed to iterator directory " + containerConfigPath.string() + ": " + ec.message(); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + for (const auto &entry : iter) { + if (entry.is_regular_file(ec)) { + const auto &path = entry.path(); + // application-specific patch will be applied last + if (path.stem().string() == appId) { + appPatchFiles.emplace_back(path); + continue; + } + globalPatchFiles.emplace_back(path); + } + } + std::sort(globalPatchFiles.begin(), globalPatchFiles.end()); + + auto doPatch = [this](const std::vector &patchFiles) -> bool { + for (const auto &patchFile : patchFiles) { + applyPatchFile(patchFile); + } + return true; + }; + + if (!doPatch(globalPatchFiles) || !doPatch(appPatchFiles)) { + return false; + } + + return true; +} + +bool ContainerCfgBuilder::applyPatchFile(const std::filesystem::path &patchFile) noexcept +{ + std::error_code ec; + auto status = std::filesystem::status(patchFile, ec); + if (ec) { + std::cerr << "Failed to get status of patch file " << patchFile << ": " << ec.message() + << std::endl; + return true; + } + + if ((status.permissions() & std::filesystem::perms::owner_exec) != std::filesystem::perms::none + || (status.permissions() & std::filesystem::perms::group_exec) + != std::filesystem::perms::none + || (status.permissions() & std::filesystem::perms::others_exec) + != std::filesystem::perms::none) { + applyExecutablePatch(patchFile); + return true; + } + + if (patchFile.extension() == ".json") { + // skip if failed to apply + applyJsonPatchFile(patchFile); + return true; + } + + std::cerr << "Patch file " << patchFile + << " is not an executable or a JSON patch file, skipping." << std::endl; + return true; +} + +bool ContainerCfgBuilder::applyJsonPatchFile(const std::filesystem::path &patchFile) noexcept +{ + std::ifstream file(patchFile); + if (!file.is_open()) { + std::cerr << "Failed to open file " << patchFile << std::endl; + return false; + } + + try { + auto json = nlohmann::json::parse(file); + auto patchContent = json.get(); + + if (config.ociVersion != patchContent.ociVersion) { + std::cerr << "ociVersion mismatched " << patchFile << std::endl; + return false; + } + + auto raw = nlohmann::json(config); + auto patchedJson = raw.patch(patchContent.patch); + config = patchedJson.get(); + } catch (const std::exception &e) { + std::cerr << "Failed to apply JSON patch " << patchFile << ": " << e.what() << std::endl; + return false; + } + + return true; +} + +bool ContainerCfgBuilder::applyExecutablePatch(const std::filesystem::path &patchFile) noexcept +{ + std::string command = patchFile.string(); + std::string inputJsonStr; + try { + inputJsonStr = nlohmann::json(config).dump(); + } catch (const std::exception &e) { + error_.reason = std::string("Failed to serialize config: ") + e.what(); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + + int stdinPipe[2]; + int stdoutPipe[2]; + if (pipe(stdinPipe) == -1) { + error_.reason = std::string("Failed to create stdin pipe: ") + strerror(errno); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + if (pipe(stdoutPipe) == -1) { + close(stdinPipe[0]); + close(stdinPipe[1]); + error_.reason = std::string("Failed to create stdout pipe: ") + strerror(errno); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + + pid_t pid = fork(); + if (pid == -1) { + close(stdinPipe[0]); + close(stdinPipe[1]); + close(stdoutPipe[0]); + close(stdoutPipe[1]); + error_.reason = "Failed to fork " + command + ": " + strerror(errno); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + + if (pid == 0) { // Child process + close(stdinPipe[1]); + close(stdoutPipe[0]); + + if (dup2(stdinPipe[0], STDIN_FILENO) == -1) { + perror(("dup2 stdin failed for " + command).c_str()); + _exit(EXIT_FAILURE); + } + if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1) { + perror(("dup2 stdout failed for " + command).c_str()); + _exit(EXIT_FAILURE); + } + + close(stdinPipe[0]); + close(stdoutPipe[1]); + + execl(patchFile.c_str(), patchFile.filename().c_str(), (char *)nullptr); + + // If execl returns, it's an error + perror(("execl failed for " + command).c_str()); + _exit(127); + } + + // Parent process + close(stdinPipe[0]); // Close read end of stdin pipe + close(stdoutPipe[1]); // Close write end of stdout pipe + + size_t bytesWritten = 0; + while (bytesWritten < inputJsonStr.size()) { + ssize_t n = write(stdinPipe[1], + inputJsonStr.c_str() + bytesWritten, + inputJsonStr.size() - bytesWritten); + if (n == -1) { + if (errno == EINTR) { + continue; + } + error_.reason = "Failed to write to stdin of " + command + ": " + strerror(errno); + error_.code = BUILD_PREPARE_ERROR; + close(stdinPipe[1]); // Attempt to close before waiting + close(stdoutPipe[0]); + waitpid(pid, nullptr, 0); // Clean up child + return false; + } + bytesWritten += n; + } + close(stdinPipe[1]); // Close write end to signal EOF to child + + std::stringstream outputJson; + char buffer[4096]; + ssize_t bytesRead; + while ((bytesRead = read(stdoutPipe[0], buffer, sizeof(buffer))) > 0) { + outputJson.write(buffer, bytesRead); + } + close(stdoutPipe[0]); // Close read end + + if (bytesRead == -1 && errno != EINTR + && errno != 0) { // EINTR is ok, 0 means EOF was already hit + error_.reason = "Failed to read from stdout of " + command + ": " + strerror(errno); + error_.code = BUILD_PREPARE_ERROR; + waitpid(pid, nullptr, 0); // Clean up child + return false; + } + + int status; + waitpid(pid, &status, 0); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + std::string exitInfo; + if (WIFEXITED(status)) { + exitInfo = "exited with status " + std::to_string(WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + exitInfo = "killed by signal " + std::to_string(WTERMSIG(status)); + } else { + exitInfo = "terminated abnormally"; + } + error_.reason = "Command " + command + " " + exitInfo + ". Output: " + outputJson.str(); + error_.code = BUILD_PREPARE_ERROR; + return false; + } + + std::string outputJsonStr = outputJson.str(); + try { + config = nlohmann::json::parse(outputJsonStr).get(); + } catch (const std::exception &e) { + error_.reason = "Failed to process output from " + command + ": " + e.what() + + ". Output: " + outputJsonStr; + error_.code = BUILD_PREPARE_ERROR; + return false; + } + return true; +} + bool ContainerCfgBuilder::mergeMount() noexcept { // merge all mounts here, the order of mounts is relevant @@ -1291,12 +1539,6 @@ bool ContainerCfgBuilder::mergeMount() noexcept std::move(extraMount->begin(), extraMount->end(), std::back_inserter(mounts)); } - if (selfAdjustingMountEnabled) { - if (!selfAdjustingMount()) { - return false; - } - } - config.mounts = std::move(mounts); return true; @@ -1598,6 +1840,12 @@ void ContainerCfgBuilder::generateMounts() noexcept bool ContainerCfgBuilder::selfAdjustingMount() noexcept { + if (!selfAdjustingMountEnabled) { + return true; + } + + mounts = std::move(config.mounts).value(); + // Some apps depends on files which doesn't exist in runtime layer or base layer, we have to // mount host files to container, or create the file on demand, but the layer is readonly. We // make a workaround by mount the suitable target's ancestor directory as tmpfs. @@ -1621,6 +1869,8 @@ bool ContainerCfgBuilder::selfAdjustingMount() noexcept generateMounts(); + config.mounts = std::move(mounts); + return true; } @@ -1672,6 +1922,14 @@ bool ContainerCfgBuilder::build() noexcept return false; } + if (!applyPatch()) { + return false; + } + + if (!selfAdjustingMount()) { + return false; + } + return true; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index dc26b2c4a..a12708c20 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -166,6 +166,12 @@ class ContainerCfgBuilder return *this; } + ContainerCfgBuilder &disablePatch() noexcept + { + applyPatchEnabled = false; + return *this; + } + std::string ldConf(const std::string &triplet); bool build() noexcept; @@ -198,6 +204,10 @@ class ContainerCfgBuilder bool buildLDCache() noexcept; bool buildQuirkVolatile() noexcept; bool buildEnv() noexcept; + bool applyPatch() noexcept; + bool applyPatchFile(const std::filesystem::path &patchFile) noexcept; + bool applyJsonPatchFile(const std::filesystem::path &patchFile) noexcept; + bool applyExecutablePatch(const std::filesystem::path &patchFile) noexcept; bool mergeMount() noexcept; bool finalize() noexcept; @@ -284,9 +294,11 @@ class ContainerCfgBuilder // .mount_idx > 0 represents the path is a mount point, and it's the subscript of the array // mounts std::vector mountpoints; + // this 'mounts' is used internally, distinct from config.mounts std::vector mounts; bool isolateNetWorkEnabled = false; + bool applyPatchEnabled = true; std::vector maskedPaths; ocppi::runtime::config::types::Config config; diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt index 4c6a4d2c6..59a59e751 100644 --- a/libs/utils/CMakeLists.txt +++ b/libs/utils/CMakeLists.txt @@ -13,8 +13,6 @@ pfl_add_library( src/linglong/utils/command/env.h src/linglong/utils/command/ocppi-helper.cpp src/linglong/utils/command/ocppi-helper.h - src/linglong/utils/configure.cpp - src/linglong/utils/configure.h.in src/linglong/utils/dbus/log.cpp src/linglong/utils/dbus/log.h src/linglong/utils/dbus/properties_forwarder.cpp diff --git a/libs/utils/src/linglong/utils/configure.cpp b/libs/utils/src/linglong/utils/configure.cpp deleted file mode 100644 index 533b932a7..000000000 --- a/libs/utils/src/linglong/utils/configure.cpp +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#include "linglong/utils/configure.h" diff --git a/libs/utils/src/linglong/utils/global/initialize.cpp b/libs/utils/src/linglong/utils/global/initialize.cpp index ff850b8ab..4c40ef66f 100644 --- a/libs/utils/src/linglong/utils/global/initialize.cpp +++ b/libs/utils/src/linglong/utils/global/initialize.cpp @@ -6,7 +6,7 @@ #include "linglong/utils/global/initialize.h" -#include "linglong/utils/configure.h" +#include "configure.h" #include #include diff --git a/misc/lib/linglong/container/README.md b/misc/lib/linglong/container/README.md index 83b8d3fc5..5f83c8343 100644 --- a/misc/lib/linglong/container/README.md +++ b/misc/lib/linglong/container/README.md @@ -1,17 +1,8 @@ # OCI configurations for linglong containers -*NOTO*: [config.json] and generators has been builtin to program itself. all generator could be override by user. - -[config.json] is the initial OCI configuration file -for linglong desktop containers. - Directory [config.d] contains OCI configuration patches and generators. They will be applied in file name order. -[config.json]: ./config.json - -[config.d]: ./config.d - ## generator Files in [config.d] that is executable for linglong runtime program @@ -55,3 +46,49 @@ The json schema definition of OCI configuration patch file can be found at [/api/schema/v1.yaml]. [/api/schema/v1.yaml]: ../../../../api/schema/v1.yaml + + +## Application-specific patches + +Patches whose filenames match the application ID are treated as application-specific. +These patches are applied after global patches. + +## Examples + +- Global patch: `99-dump-conf` +- App patch: `com.example.app.json` (matches app ID) + +com.example.app.json: + +```json +{ + "ociVersion": "1.0.1", + "patch": [ + { + "op": "add", + "path": "/mounts/-", + "value": { + "destination": "/opt/host-apps/", + "type": "bind", + "source": "/opt/apps", + "options": [ + "rbind" + ] + } + } + ] +} +``` + +com.example.app.json add an extra mounts, which bind host's `/opt/apps` to container's `/opt/host-apps`, +this patch will applied after 99-dump-conf. + +99-dump-conf can write following content to print the container's configuration: + +``` bash +#!/bin/sh + +content=$(cat -) +echo $content >&2 +echo ${content} +``` From a77322acc9a989a2f3582b5e3a7024e432156dd3 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 3 Jun 2025 15:37:20 +0800 Subject: [PATCH 029/366] fix: preserve set-default compatibility The set-default command ensures compatibility by setting the priority. However, its modification to the priority is unidirectional and one-time, subsequent set-priority invokes will not alter the default state. Signed-off-by: reddevillg --- libs/linglong/src/linglong/cli/cli.cpp | 30 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 20818e50e..2f5f57a89 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -26,6 +26,7 @@ #include "linglong/oci-cfg-generators/container_cfg_builder.h" #include "linglong/package/layer_file.h" #include "linglong/package/reference.h" +#include "linglong/repo/config.h" #include "linglong/runtime/container_builder.h" #include "linglong/runtime/run_context.h" #include "linglong/utils/error/error.h" @@ -1897,14 +1898,25 @@ int Cli::repo(CLI::App *app) } if (argsParseFunc("remove")) { - if (cfgRef.defaultRepo == alias) { - this->printer.printErr( - LINGLONG_ERRV(QString{ "repo " } + alias.c_str() - + "is default repo, please change default repo before removing it.")); + if (cfgRef.repos.size() == 1) { + this->printer.printErr(LINGLONG_ERRV(QString{ "repo " } + alias.c_str() + + " is the only repo, please add another repo " + "before removing it or update it directly.")); return -1; } - cfgRef.repos.erase(existingRepo); + + if (cfgRef.defaultRepo == alias) { + // choose the max priority repo as default repo + auto maxPriority = linglong::repo::getRepoMaxPriority(cfgRef); + for (auto &repo : cfgRef.repos) { + if (repo.priority == maxPriority) { + cfgRef.defaultRepo = repo.alias.value_or(repo.name); + break; + } + } + } + return this->setRepoConfig(utils::serialize::toQVariantMap(cfgRef)); } @@ -1921,6 +1933,14 @@ int Cli::repo(CLI::App *app) if (argsParseFunc("set-default")) { if (cfgRef.defaultRepo != alias) { cfgRef.defaultRepo = alias; + // set-default is equal to set-priority to the current max priority + 100 + auto maxPriority = linglong::repo::getRepoMaxPriority(cfgRef); + for (auto &repo : cfgRef.repos) { + if (repo.alias.value_or(repo.name) == alias) { + repo.priority = maxPriority + 100; + break; + } + } return this->setRepoConfig(utils::serialize::toQVariantMap(cfgRef)); } From b54fd561aa78139d53b80ed9677e59a3f59a763b Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 6 Mar 2025 09:45:42 +0800 Subject: [PATCH 030/366] feat: add hooks features Add hooks features for app install. --- configure.h.in | 2 + .../package_manager/package_manager.cpp | 124 +++++++++ .../package_manager/package_manager.h | 2 + libs/utils/CMakeLists.txt | 2 + libs/utils/src/linglong/utils/hooks.cpp | 258 ++++++++++++++++++ libs/utils/src/linglong/utils/hooks.h | 38 +++ misc/lib/tmpfiles.d/linglong.conf | 3 + 7 files changed, 429 insertions(+) create mode 100644 libs/utils/src/linglong/utils/hooks.cpp create mode 100644 libs/utils/src/linglong/utils/hooks.h diff --git a/configure.h.in b/configure.h.in index 4643085fc..e8b42a617 100644 --- a/configure.h.in +++ b/configure.h.in @@ -22,6 +22,8 @@ #define LINGLONG_CLIENT_NAME "@LINGLONG_CLI_BIN@" #define LINGLONG_CLIENT_PATH "@CMAKE_INSTALL_FULL_BINDIR@/@LINGLONG_CLI_BIN@" #define LINGLONG_EXPORT_PATH "@LINGLONG_EXPORT_PATH@" +// The directory where the package install hooks reside. +#define LINGLONG_INSTALL_HOOKS_DIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@/linglong/config.d" #define LINGLONG_EXPORT_VERSION "1.0.0.2" // The package's locale domain. diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index f0c55b528..635bf254c 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -26,6 +26,7 @@ #include "linglong/utils/command/env.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" +#include "linglong/utils/hooks.h" #include "linglong/utils/packageinfo_handler.h" #include "linglong/utils/serialize/json.h" #include "linglong/utils/transaction.h" @@ -738,6 +739,12 @@ QVariantMap PackageManager::installFromLayer(const QDBusUnixFileDescriptor &fd, << "after install" << packageRef.toString() << ":" << ret.error().message(); } + + ret = executePostInstallHooks(*newRef); + if (!ret) { + taskRef.reportError(std::move(ret).error()); + return; + } }; auto refSpec = @@ -768,6 +775,18 @@ QVariantMap PackageManager::installFromUAB(const QDBusUnixFileDescriptor &fd, return toDBusReply(-1, "invalid file descriptor"); } + std::unique_ptr installHookManager = + std::make_unique(); + auto ret = installHookManager->parseInstallHooks(); + if (!ret) { + return toDBusReply(ret); + } + + ret = installHookManager->executeInstallHooks(fd.fileDescriptor()); + if (!ret) { + return toDBusReply(-1, "uab package signature verification failed."); + } + auto uabRet = package::UABFile::loadFromFile(fd.fileDescriptor()); if (!uabRet) { return toDBusReply(uabRet); @@ -1072,6 +1091,12 @@ QVariantMap PackageManager::installFromUAB(const QDBusUnixFileDescriptor &fd, } } + auto ret = executePostInstallHooks(newAppRef); + if (!ret) { + taskRef.reportError(std::move(ret).error()); + return; + } + transaction.commit(); taskRef.updateState(linglong::api::types::v1::State::Succeed, "install uab successfully"); }; @@ -1439,6 +1464,13 @@ void PackageManager::Install(PackageTask &taskContext, } } + auto ret = executePostInstallHooks(newRef); + if (!ret) { + taskContext.updateState(linglong::api::types::v1::State::Failed, + "Failed to execute postInstall hooks.\n" + ret.error().message()); + return; + } + transaction.commit(); taskContext.updateState(linglong::api::types::v1::State::Succeed, "Install " + newRef.toString() + " (from repo: " @@ -1713,6 +1745,11 @@ void PackageManager::Uninstall(PackageTask &taskContext, return; } + auto ret = executePostUninstallHooks(ref); + if (!ret) { + qWarning() << "failed to execute postUninstall hooks" << ret.error(); + } + transaction.commit(); taskContext.updateState(linglong::api::types::v1::State::Succeed, @@ -1875,6 +1912,12 @@ void PackageManager::Update(PackageTask &taskContext, return; } + ret = executePostInstallHooks(newRef); + if (!ret) { + qCritical() << "failed to execute post install hooks" << ret.error().message(); + return; + } + auto result = this->tryGenerateCache(newRef); if (!result) { taskContext.reportError( @@ -2001,12 +2044,25 @@ void PackageManager::pullDependency(PackageTask &taskContext, return; } + auto ret = executePostInstallHooks(runtime->reference); + if (!ret) { + taskContext.updateState(linglong::api::types::v1::State::Failed, + LINGLONG_ERRV(ret).message()); + return; + } + transaction.addRollBack([this, runtimeRef = *runtime, module]() noexcept { auto result = this->repo.remove(runtimeRef.reference, module); if (!result) { qCritical() << result.error(); Q_ASSERT(false); } + + result = executePostUninstallHooks(runtimeRef.reference); + if (!result) { + qCritical() << result.error(); + Q_ASSERT(false); + } }); } } @@ -2041,6 +2097,27 @@ void PackageManager::pullDependency(PackageTask &taskContext, if (isTaskDone(taskContext.subState())) { return; } + + auto ret = executePostInstallHooks(base->reference); + if (!ret) { + taskContext.updateState(linglong::api::types::v1::State::Failed, + LINGLONG_ERRV(ret).message()); + return; + } + + transaction.addRollBack([this, baseRef = *base, module]() noexcept { + auto result = this->repo.remove(baseRef.reference, module); + if (!result) { + qCritical() << result.error(); + Q_ASSERT(false); + } + + result = executePostUninstallHooks(baseRef.reference); + if (!result) { + qCritical() << result.error(); + Q_ASSERT(false); + } + }); } transaction.commit(); @@ -2431,4 +2508,51 @@ auto PackageManager::GenerateCache(const QString &reference) noexcept -> QVarian return result; } +utils::error::Result +PackageManager::executePostInstallHooks(const package::Reference &ref) noexcept +{ + LINGLONG_TRACE("execute post install hooks for: " + ref.toString()); + + std::unique_ptr installHookManager = + std::make_unique(); + auto ret = installHookManager->parseInstallHooks(); + if (!ret) { + return LINGLONG_ERR(ret); + } + + auto layerDir = this->repo.getLayerDir(ref); + if (!layerDir) { + return LINGLONG_ERR(layerDir); + } + + auto appPath = layerDir->absolutePath(); + + ret = installHookManager->executePostInstallHooks(ref.id.toStdString(), appPath.toStdString()); + if (!ret) { + return LINGLONG_ERR(ret); + } + + return LINGLONG_OK; +} + +utils::error::Result +PackageManager::executePostUninstallHooks(const package::Reference &ref) noexcept +{ + LINGLONG_TRACE("execute post uninstall hooks for: " + ref.toString()); + + std::unique_ptr installHookManager = + std::make_unique(); + auto ret = installHookManager->parseInstallHooks(); + if (!ret) { + return LINGLONG_ERR(ret); + } + + ret = installHookManager->executePostUninstallHooks(ref.id.toStdString()); + if (!ret) { + return LINGLONG_ERR(ret); + } + + return LINGLONG_OK; +} + } // namespace linglong::service diff --git a/libs/linglong/src/linglong/package_manager/package_manager.h b/libs/linglong/src/linglong/package_manager/package_manager.h index 3606e1eb3..83af5a200 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.h +++ b/libs/linglong/src/linglong/package_manager/package_manager.h @@ -156,6 +156,8 @@ public utils::error::Result generateCache(const package::Reference &ref) noexcept; utils::error::Result tryGenerateCache(const package::Reference &ref) noexcept; utils::error::Result removeCache(const package::Reference &ref) noexcept; + utils::error::Result executePostInstallHooks(const package::Reference &ref) noexcept; + utils::error::Result executePostUninstallHooks(const package::Reference &ref) noexcept; linglong::repo::OSTreeRepo &repo; // NOLINT PackageTaskQueue tasks; diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt index 59a59e751..a39218294 100644 --- a/libs/utils/CMakeLists.txt +++ b/libs/utils/CMakeLists.txt @@ -45,6 +45,8 @@ pfl_add_library( src/linglong/utils/xdg/desktop_entry.h src/linglong/utils/xdg/directory.h src/linglong/utils/gkeyfile_wrapper.h + src/linglong/utils/hooks.cpp + src/linglong/utils/hooks.h COMPILE_FEATURES PUBLIC cxx_std_17 diff --git a/libs/utils/src/linglong/utils/hooks.cpp b/libs/utils/src/linglong/utils/hooks.cpp new file mode 100644 index 000000000..68a761258 --- /dev/null +++ b/libs/utils/src/linglong/utils/hooks.cpp @@ -0,0 +1,258 @@ +/* + * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#include "hooks.h" + +#include "configure.h" +#include "linglong/utils/error/error.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace linglong::utils { + +// Constants for hook action prefixes +static const std::string PRE_INSTALL_ACTION_PREFIX = "ll-pre-install="; +static const std::string POST_INSTALL_ACTION_PREFIX = "ll-post-install="; +static const std::string POST_UNINSTALL_ACTION_PREFIX = "ll-post-uninstall="; + +// Ensures variables are cleaned up even on early returns or exceptions. +class EnvVarGuard +{ +public: + EnvVarGuard(const std::string &name, const std::string &value) + : name(name) + , setOK(false) + { + if (setenv(name.c_str(), value.c_str(), 1) == 0) { + setOK = true; + } else { + qWarning() << "Failed to set environment variable" << name.c_str() << ":" << errno; + } + } + + EnvVarGuard(const EnvVarGuard &) = delete; + EnvVarGuard &operator=(const EnvVarGuard &) = delete; + + EnvVarGuard(EnvVarGuard &&other) noexcept + : name(std::move(other.name)) + , setOK(other.setOK) + { + other.setOK = false; + } + + EnvVarGuard &operator=(EnvVarGuard &&other) noexcept + { + if (this != &other) { + if (setOK && ::getenv(name.c_str()) != nullptr) { + if (unsetenv(name.c_str()) != 0) { + qWarning() << "Failed to unset old environment variable" << name.c_str() << ":" + << errno; + } + } + name = std::move(other.name); + setOK = other.setOK; + other.setOK = false; + } + return *this; + } + + ~EnvVarGuard() + { + if (setOK && ::getenv(name.c_str()) != nullptr) { + if (unsetenv(name.c_str()) != 0) { + qWarning() << "Failed to unset environment variable" << name.c_str() << ":" + << errno; + } + } + } + +private: + std::string name; // Name of the environment variable + bool setOK; +}; + +// This function ensures the command string is safely wrapped for 'sh -c'. +static std::string escapeAndWrapCommandForShell(const std::string &command) +{ + std::string escapedCommand = command; + size_t pos = 0; + // Replace ' with '\'' (close current quote, add literal single quote, open new quote) + while ((pos = escapedCommand.find('\'', pos)) != std::string::npos) { + escapedCommand.replace(pos, 1, "'\\''"); + pos += 4; + } + + return "sh -c " + escapedCommand; +} + +using CommandList = const std::vector &; + +utils::error::Result executeHookCommands( + CommandList commands, const std::vector> &envVars) noexcept +{ + LINGLONG_TRACE("Executing command"); + + std::vector envVarGuards; + envVarGuards.reserve(envVars.size()); + for (const auto &pair : envVars) { + envVarGuards.emplace_back(pair.first, pair.second); + } + + for (const auto &command_raw : commands) { + std::string fullCommand = escapeAndWrapCommandForShell(command_raw); + + int ret = std::system(fullCommand.c_str()); + + if (ret == -1) { + return LINGLONG_ERR(QString("Failed to execute command: '%1'. System error: %2.") + .arg(QString::fromStdString(fullCommand)) + .arg(strerror(errno))); + } + + if (!WIFEXITED(ret)) { + int signalNum = WTERMSIG(ret); + return LINGLONG_ERR(QString("Command '%1' terminated by signal %2 (%3).") + .arg(QString::fromStdString(fullCommand)) + .arg(signalNum) + .arg(strsignal(signalNum))); + } + + int exitStatus = WEXITSTATUS(ret); + if (exitStatus != 0) { + return LINGLONG_ERR(QString("Command '%1' exited with non-zero status: %2.") + .arg(QString::fromStdString(fullCommand)) + .arg(exitStatus)); + } + } + return LINGLONG_OK; +} + +utils::error::Result InstallHookManager::parseInstallHooks() +{ + LINGLONG_TRACE("Parsing install hooks"); + + std::error_code ec; + for (const auto &entry : std::filesystem::directory_iterator(LINGLONG_INSTALL_HOOKS_DIR, ec)) { + if (ec) { + return LINGLONG_ERR(QString("Failed to iterate directory %1: %2") + .arg(LINGLONG_INSTALL_HOOKS_DIR) + .arg(QString::fromStdString(ec.message()))); + } + + if (!std::filesystem::is_regular_file(entry.status(ec))) { + if (ec) { + qWarning() << "Failed to get status for" << entry.path().c_str() << ":" + << QString::fromStdString(ec.message()); + } + continue; + } + + std::ifstream file(entry.path()); + if (!file.is_open()) { + return LINGLONG_ERR(QString{ "Couldn't open file: %1" }.arg(entry.path().c_str())); + } + + std::string line; + while (std::getline(file, line)) { + std::size_t pos = line.find(PRE_INSTALL_ACTION_PREFIX); + if (pos != std::string::npos) { + preInstallCommands.emplace_back( + line.substr(pos + PRE_INSTALL_ACTION_PREFIX.length())); + break; + } + + pos = line.find(POST_INSTALL_ACTION_PREFIX); + if (pos != std::string::npos) { + postInstallCommands.emplace_back( + line.substr(pos + POST_INSTALL_ACTION_PREFIX.length())); + break; + } + + pos = line.find(POST_UNINSTALL_ACTION_PREFIX); + if (pos != std::string::npos) { + postUninstallCommands.emplace_back( + line.substr(pos + POST_UNINSTALL_ACTION_PREFIX.length())); + break; + } + } + } + + return LINGLONG_OK; +} + +utils::error::Result InstallHookManager::executeInstallHooks(int fd) noexcept +{ + LINGLONG_TRACE("Executing pre-install hooks."); + + if (preInstallCommands.empty()) { + LINGLONG_TRACE("No pre-install commands to execute."); + return LINGLONG_OK; + } + + // Convert fd into a specific path using /proc/pid/fd/fd_num + std::ostringstream oss; + oss << "/proc/" << getpid() << "/fd/" << fd; + + std::array pathBuf{}; + auto size = readlink(oss.str().c_str(), pathBuf.data(), PATH_MAX); + + if (size == -1) { + return LINGLONG_ERR( + QString{ "Failed to read file link for fd %1: %2" }.arg(fd).arg(strerror(errno))); + } + + pathBuf[size] = '\0'; + std::string uabPath = pathBuf.data(); + + std::vector> envVars = { { "LINGLONG_UAB_PATH", uabPath } }; + + return executeHookCommands(preInstallCommands, envVars); +} + +utils::error::Result InstallHookManager::executePostInstallHooks( + const std::string &appID, const std::string &path) noexcept +{ + LINGLONG_TRACE("Executing post-install hooks."); + + if (postInstallCommands.empty()) { + LINGLONG_TRACE("No post-install commands to execute."); + return LINGLONG_OK; + } + + std::vector> envVars = { { "LINGLONG_APPID", appID }, + { "LINGLONG_APP_INSTALL_PATH", + path } }; + + return executeHookCommands(postInstallCommands, envVars); +} + +utils::error::Result +InstallHookManager::executePostUninstallHooks(const std::string &appID) noexcept +{ + LINGLONG_TRACE("Executing post-uninstall hooks."); + + if (postUninstallCommands.empty()) { + LINGLONG_TRACE("No post-uninstall commands to execute."); + return LINGLONG_OK; + } + + std::vector> envVars = { { "LINGLONG_APPID", appID } }; + + return executeHookCommands(postUninstallCommands, envVars); +} + +} // namespace linglong::utils diff --git a/libs/utils/src/linglong/utils/hooks.h b/libs/utils/src/linglong/utils/hooks.h new file mode 100644 index 000000000..92a940b96 --- /dev/null +++ b/libs/utils/src/linglong/utils/hooks.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: LGPL-3.0-or-later + */ + +#pragma once + +#include "linglong/utils/error/error.h" + +#include +#include + +namespace linglong::utils { + +class InstallHookManager final +{ +public: + InstallHookManager() = default; + InstallHookManager(const InstallHookManager &) = delete; + InstallHookManager(InstallHookManager &&) = delete; + InstallHookManager &operator=(const InstallHookManager &) = delete; + InstallHookManager &operator=(InstallHookManager &&) = delete; + ~InstallHookManager() = default; + + utils::error::Result parseInstallHooks(); + utils::error::Result executeInstallHooks(int fd) noexcept; + utils::error::Result executePostInstallHooks(const std::string &appID, + const std::string &path) noexcept; + utils::error::Result executePostUninstallHooks(const std::string &appID) noexcept; + +private: + std::vector preInstallCommands; + std::vector postInstallCommands; + std::vector postUninstallCommands; +}; + +} // namespace linglong::utils diff --git a/misc/lib/tmpfiles.d/linglong.conf b/misc/lib/tmpfiles.d/linglong.conf index c59d11b38..8a35a8961 100644 --- a/misc/lib/tmpfiles.d/linglong.conf +++ b/misc/lib/tmpfiles.d/linglong.conf @@ -10,3 +10,6 @@ d @LINGLONG_ROOT@ 0755 @LINGLONG_USERNAME@ @LINGLONG_USERNAME@ - #FIXME: set /run/linglong to 777 temporarily, add group "deepin-linglong" in the future d /run/linglong 0777 @LINGLONG_USERNAME@ @LINGLONG_USERNAME@ - - + +# Create a directory to place the hook script +d @CMAKE_INSTALL_FULL_SYSCONFDIR@/linglong/config.d 0755 root root - - From 728d6e610e2b141ced3ace46de951bac524f6df1 Mon Sep 17 00:00:00 2001 From: ice909 Date: Mon, 9 Jun 2025 15:02:57 +0800 Subject: [PATCH 031/366] chore: update i18n files Signed-off-by: ice909 --- po/en_US.po | 498 ++++++++++++++++++++++++++----------------------- po/linyaps.pot | 463 +++++++++++++++++++++++---------------------- 2 files changed, 508 insertions(+), 453 deletions(-) diff --git a/po/en_US.po b/po/en_US.po index bff7783b1..a7ceb7eb5 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-01-07 17:11+0800\n" "Last-Translator: deepiner, 2024\n" "Language-Team: LANGUAGE \n" @@ -17,44 +17,48 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Permission denied, please check whether you are running as root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "To install the module, one must first install the app." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "Module is already installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Install failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "The module could not be found remotely." + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Uninstall failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "Upgrade failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "Application is not installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "Latest version is already installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -64,7 +68,7 @@ msgstr "" "1. Check your internet connection\n" "2. Verify network proxy settings if used" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -72,15 +76,15 @@ msgstr "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "Application %1 is not found in remote repo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "Cannot specify a version when installing a module." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -88,13 +92,13 @@ msgstr "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "The cache generation failed, please uninstall and reinstall the application." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -102,34 +106,34 @@ msgstr "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Print this help message and exit" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Expand all help" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Show version" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -137,47 +141,47 @@ msgstr "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Use json format to output result" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Input parameter is empty, please input valid parameter instead" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Show debug info (verbose logs)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Managing installed applications and runtimes" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Managing running applications" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Finding applications and runtimes" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Managing remote repositories" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Run an application" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Specify the application ID" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -199,70 +203,70 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Pass file to applications running in a sandbox" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Pass url to applications running in a sandbox" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Run commands in a running sandbox" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "List running applications" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Usage: ll-cli ps [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Execute commands in the currently running sandbox" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "Specify the application running instance(you can get it by ps command)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Specify working directory" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Enter the namespace where the application is running" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Stop running applications" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Usage: ll-cli kill [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Specify the signal to send to the application" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Specify the running application" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Installing an application or runtime" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -298,56 +302,60 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "Specify the application ID, and it can also be a .uab or .layer file" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Install a specify module" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "Install from a specific repo" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Force install the application" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Automatically answer yes to all questions" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Uninstall the application or runtimes" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Usage: ll-cli uninstall [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Specify the applications ID" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Uninstall a specify module" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Remove all unused modules" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Uninstall all modules" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Upgrade the application or runtimes" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Usage: ll-cli upgrade [OPTIONS] [APP]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be " "upgraded" @@ -355,7 +363,7 @@ msgstr "" "Specify the application ID. If it not be specified, all applications will be " "upgraded" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -363,60 +371,71 @@ msgstr "" "Search the applications/runtimes containing the specified text from the " "remote repository" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" "# find remotely runtime by name\n" "ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Specify the Keywords" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "" -"Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "include develop application in result" +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "Specify the repo" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Show all results" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "Include develop application in result" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "List installed applications or runtimes" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "Show all versions of an application(s), base(s) or runtime(s)" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "List installed application(s), base(s) or runtime(s)" + +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" @@ -425,238 +444,254 @@ msgstr "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Display or modify information of the repository currently using" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Add a new repository" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo add [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Specify the repo name" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "Url of the repository" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias of the repo name" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Modify repository URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Remove a repository" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Usage: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Update the repository URL" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Set a default repository name" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Usage: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Show repository information" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Usage: ll-cli repo show [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Set the priority of the repo" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Usage: ll-cli repo set-priority ALIAS PRIORITY" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Priority of the repo" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Display information about installed apps or runtimes" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Usage: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specify the application ID, and it can also be a .layer file" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Display the exported files of installed application" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Usage: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Specify the installed application ID" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Remove the unused base or runtime" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Usage: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Display the information of installed application" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Usage: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Specify the process id" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Invalid pid format" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Specify the installed app(base or runtime)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "linyaps CLI version " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Name" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "version" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Channel" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Module" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Description" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "No packages found in the remote repo." + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "Repo" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "No containers are running." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "App" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ContainerID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "Pid" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "Url" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Priority" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "No apps available for update." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Installed" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "New" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -664,55 +699,51 @@ msgstr "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Create linyaps build template project" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Usage: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Project name" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Build a linyaps project" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "File path of the linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Set the build arch" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "Enter the container to execute command instead of building applications" msgstr "" "Enter the container to execute command instead of building applications" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -720,196 +751,195 @@ msgstr "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Build full develop packages, runtime requires" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Skip fetch sources" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Skip pull dependency" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Skip run container" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Skip commit build output" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Skip output check" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Skip strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Build in an isolated network environment" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Run built linyaps app" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Only use local files" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Run specified module. eg: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "Enter the container to execute command instead of running application" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Run in debug mode (enable develop module)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "List built linyaps app" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Usage: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Remove built linyaps app" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Usage: ll-builder remove [OPTIONS] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Export to linyaps layer or uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Usage: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Uab icon (optional)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Export uab fully" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Export to linyaps layer file" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "Export to linyaps layer file (deprecated)" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Use custom loader" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Don't export the develop module" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Output file" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Push linyaps app to remote repo" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Usage: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "Remote repo url" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Remote repo name" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Push single module" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Import linyaps layer to build repo" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Usage: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Layer file path" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Import linyaps layer dir to build repo" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Layer dir path" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Extract linyaps layer to dir" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Usage: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Destination directory" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Display and manage repositories" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Usage: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Usage: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Usage: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "linyaps build tool version " diff --git a/po/linyaps.pot b/po/linyaps.pot index b193ceeee..47f5bae8e 100644 --- a/po/linyaps.pot +++ b/po/linyaps.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,152 +17,156 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" msgstr "" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" msgstr "" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -175,70 +179,70 @@ msgid "" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" msgstr "" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -258,583 +262,604 @@ msgid "" " " msgstr "" -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be " "upgraded" msgstr "" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" msgstr "" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" msgstr "" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "Enter the container to execute command instead of building applications" msgstr "" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "" From 627eb6721ef6cd51c5087616b6fe37416d828faf Mon Sep 17 00:00:00 2001 From: ice909 Date: Tue, 10 Jun 2025 14:37:23 +0800 Subject: [PATCH 032/366] fix: correct translation key in po/en_US.po Signed-off-by: ice909 --- po/en_US.po | 2 +- po/linyaps.pot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/po/en_US.po b/po/en_US.po index a7ceb7eb5..4ab574e78 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -407,7 +407,7 @@ msgstr "Specify the Keywords" msgid "" "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " "\"all\"" -msgid "" +msgstr "" "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " "\"all\"" diff --git a/po/linyaps.pot b/po/linyaps.pot index 47f5bae8e..716bd087f 100644 --- a/po/linyaps.pot +++ b/po/linyaps.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-06-10 14:30+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" From d8a3191d2f6de9e4c6ed3ed12f03b1c51a9cbfcf Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 10 Jun 2025 14:54:39 +0800 Subject: [PATCH 033/366] fix: Preserve host's HOME env in container. 1. Ensure container HOME env matches the host environment exactly, we rely on it before support portal well. 2. remove /run/udev bind, udev database path and file across different versions are not guaranteed to be compatible. 3. add all_proxy env to defulat forward list. Signed-off-by: reddevillg --- .../src/linglong/builder/linglong_builder.cpp | 13 ++++++------- libs/linglong/src/linglong/cli/cli.cpp | 11 +++++------ .../container_cfg_builder.cpp | 17 ++++++----------- .../oci-cfg-generators/container_cfg_builder.h | 2 +- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 78e9ba794..6e209befc 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1807,9 +1807,8 @@ utils::error::Result Builder::run(const QStringList &modules, } auto *homeEnv = ::getenv("HOME"); - auto *userNameEnv = ::getenv("USER"); - if (homeEnv == nullptr || userNameEnv == nullptr) { - return LINGLONG_ERR("Couldn't get HOME or USER from env."); + if (homeEnv == nullptr) { + return LINGLONG_ERR("Couldn't get HOME env."); } std::vector applicationMounts{}; @@ -1833,7 +1832,7 @@ utils::error::Result Builder::run(const QStringList &modules, f << "set debug-file-directory " + debugDir << std::endl; applicationMounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::string("/home/") + userNameEnv + "/.gdbinit", + .destination = std::string{ homeEnv } + "/.gdbinit", .options = { { "ro", "rbind" } }, .source = gdbinit, .type = "bind", @@ -1924,10 +1923,10 @@ utils::error::Result Builder::run(const QStringList &modules, .bindMedia() .bindHostRoot() .bindHostStatics() - .bindHome(homeEnv, userNameEnv) + .bindHome(homeEnv) .enablePrivateDir() - .mapPrivate(std::string("/home/") + userNameEnv + "/.ssh", true) - .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) + .mapPrivate(std::string{ homeEnv } + "/.ssh", true) + .mapPrivate(std::string{ homeEnv } + "/.gnupg", true) .bindIPC() .forwardDefaultEnv() .addExtraMounts(applicationMounts) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 2f5f57a89..ed6dd5a3f 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -689,9 +689,8 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) } auto *homeEnv = ::getenv("HOME"); - auto *userNameEnv = ::getenv("USER"); - if (homeEnv == nullptr || userNameEnv == nullptr) { - qCritical() << "Couldn't get HOME or USER from env."; + if (homeEnv == nullptr) { + qCritical() << "Couldn't get HOME env."; return -1; } @@ -714,10 +713,10 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) .bindMedia() .bindHostRoot() .bindHostStatics() - .bindHome(homeEnv, userNameEnv) + .bindHome(homeEnv) .enablePrivateDir() - .mapPrivate(std::string("/home/") + userNameEnv + "/.ssh", true) - .mapPrivate(std::string("/home/") + userNameEnv + "/.gnupg", true) + .mapPrivate(std::string{ homeEnv } + "/.ssh", true) + .mapPrivate(std::string{ homeEnv } + "/.gnupg", true) .bindIPC() .forwardDefaultEnv() .enableSelfAdjustingMount(); diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index a768b621d..0e996af5b 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -174,10 +174,6 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindRun() noexcept .options = string_list{ "nosuid", "strictatime", "mode=0755", "size=65536k" }, .source = "tmpfs", .type = "tmpfs" }, - Mount{ .destination = "/run/udev", - .options = string_list{ "rbind" }, - .source = "/run/udev", - .type = "bind" }, Mount{ .destination = "/run/user", .options = string_list{ "nodev", "nosuid", "mode=700" }, .source = "tmpfs", @@ -279,6 +275,7 @@ ContainerCfgBuilder &ContainerCfgBuilder::forwardDefaultEnv() noexcept "CLUTTER_IM_MODULE", "QT4_IM_MODULE", "GTK_IM_MODULE", + "all_proxy", "auto_proxy", // 网络系统代理自动代理 "http_proxy", // 网络系统代理手动http代理 "https_proxy", // 网络系统代理手动https代理 @@ -389,11 +386,9 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindHostStatics() noexcept return *this; } -ContainerCfgBuilder &ContainerCfgBuilder::bindHome(std::filesystem::path hostHome, - std::string user) noexcept +ContainerCfgBuilder &ContainerCfgBuilder::bindHome(std::filesystem::path hostHome) noexcept { homePath = hostHome; - homeUser = user; homeMount = std::vector{}; return *this; @@ -608,8 +603,8 @@ bool ContainerCfgBuilder::buildMountHome() noexcept return true; } - if (homePath->empty() || homeUser.empty()) { - error_.reason = "homePath or user is empty"; + if (homePath->empty()) { + error_.reason = "homePath is empty"; error_.code = BUILD_MOUNT_HOME_ERROR; return false; } @@ -626,7 +621,7 @@ bool ContainerCfgBuilder::buildMountHome() noexcept .source = "tmpfs", .type = "tmpfs" }); - auto containerHome = "/home/" + homeUser; + auto containerHome = homePath->string(); homeMount->emplace_back(Mount{ .destination = containerHome, .options = string_list{ "rbind" }, @@ -1070,7 +1065,7 @@ bool ContainerCfgBuilder::buildMountIPC() noexcept } auto hostXauthFile = *homePath / ".Xauthority"; - auto cognitiveXauthFile = std::string{ "/home/" } + homeUser + "/.Xauthority"; + auto cognitiveXauthFile = homePath->string() + "/.Xauthority"; auto *xauthFileEnv = ::getenv("XAUTHORITY"); // NOLINT std::error_code ec; diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index a12708c20..a535c8387 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -132,7 +132,7 @@ class ContainerCfgBuilder ContainerCfgBuilder &bindHostRoot() noexcept; ContainerCfgBuilder &bindHostStatics() noexcept; - ContainerCfgBuilder &bindHome(std::filesystem::path hostHome, std::string user) noexcept; + ContainerCfgBuilder &bindHome(std::filesystem::path hostHome) noexcept; ContainerCfgBuilder &enablePrivateDir() noexcept; ContainerCfgBuilder &mapPrivate(std::string containerPath, bool isDir) noexcept; From 2615ac3525c2d5ef66494e73f543ea244cc7926e Mon Sep 17 00:00:00 2001 From: ComixHe Date: Wed, 11 Jun 2025 13:29:00 +0800 Subject: [PATCH 034/366] refactor: remove all generators Signed-off-by: ComixHe --- libs/oci-cfg-generators/CMakeLists.txt | 35 -- .../oci-cfg-generators/00_id_mapping.cpp | 45 -- .../oci-cfg-generators/00_id_mapping.h | 17 - .../oci-cfg-generators/05_initialize.cpp | 75 ---- .../oci-cfg-generators/05_initialize.h | 18 - .../linglong/oci-cfg-generators/10_basics.cpp | 50 --- .../oci-cfg-generators/10_basics.h.in | 21 - .../oci-cfg-generators/20_devices.cpp | 129 ------ .../linglong/oci-cfg-generators/20_devices.h | 18 - .../oci-cfg-generators/25_host_env.cpp | 101 ----- .../linglong/oci-cfg-generators/25_host_env.h | 16 - .../oci-cfg-generators/25_host_rootfs.cpp | 51 --- .../oci-cfg-generators/25_host_rootfs.h.in | 21 - .../oci-cfg-generators/25_host_statics.cpp | 50 --- .../oci-cfg-generators/25_host_statics.h.in | 23 -- .../oci-cfg-generators/30_user_home.cpp | 360 ---------------- .../oci-cfg-generators/30_user_home.h | 18 - .../oci-cfg-generators/40_host_ipc.cpp | 383 ------------------ .../linglong/oci-cfg-generators/40_host_ipc.h | 16 - .../linglong/oci-cfg-generators/90_legacy.h | 17 - .../linglong/oci-cfg-generators/builtins.h.in | 65 --- .../linglong/oci-cfg-generators/generator.h | 21 - 22 files changed, 1550 deletions(-) delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.h.in delete mode 100755 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.h.in delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.h.in delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.h delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/builtins.h.in delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/generator.h diff --git a/libs/oci-cfg-generators/CMakeLists.txt b/libs/oci-cfg-generators/CMakeLists.txt index 8f19a82d1..74958eaf7 100644 --- a/libs/oci-cfg-generators/CMakeLists.txt +++ b/libs/oci-cfg-generators/CMakeLists.txt @@ -2,19 +2,6 @@ # # SPDX-License-Identifier: LGPL-3.0-or-later -macro(configure_patch_variable source) - get_filename_component(BASE_NAME ${source} NAME_WE) - string(TOUPPER ${BASE_NAME} PATCH_VAR) - string(REPLACE "-" "_" PATCH_VAR ${PATCH_VAR}) - string(PREPEND PATCH_VAR "LINGLONG_OCI_CFG_GEN_") - file(READ ${source} ${PATCH_VAR}) -endmacro() - -configure_patch_variable(${PROJECT_SOURCE_DIR}/misc/lib/linglong/container/config.json) -configure_patch_variable(${PROJECT_SOURCE_DIR}/misc/lib/linglong/container/config.d/10-basics.json) -configure_patch_variable(${PROJECT_SOURCE_DIR}/misc/lib/linglong/container/config.d/25-host-rootfs.json) -configure_patch_variable(${PROJECT_SOURCE_DIR}/misc/lib/linglong/container/config.d/25-host-statics.json) - pfl_add_library( MERGED_HEADER_PLACEMENT DISABLE_INSTALL @@ -22,30 +9,8 @@ pfl_add_library( STATIC SOURCES # find -regex '\.\/.+\.[ch]\(pp\)?' -type f -printf '%P\n'| sort - src/linglong/oci-cfg-generators/00_id_mapping.cpp - src/linglong/oci-cfg-generators/00_id_mapping.h - src/linglong/oci-cfg-generators/05_initialize.cpp - src/linglong/oci-cfg-generators/05_initialize.h - src/linglong/oci-cfg-generators/10_basics.cpp - src/linglong/oci-cfg-generators/10_basics.h.in - src/linglong/oci-cfg-generators/20_devices.cpp - src/linglong/oci-cfg-generators/20_devices.h - src/linglong/oci-cfg-generators/25_host_env.cpp - src/linglong/oci-cfg-generators/25_host_env.h - src/linglong/oci-cfg-generators/25_host_rootfs.cpp - src/linglong/oci-cfg-generators/25_host_rootfs.h.in - src/linglong/oci-cfg-generators/25_host_statics.cpp - src/linglong/oci-cfg-generators/25_host_statics.h.in - src/linglong/oci-cfg-generators/30_user_home.cpp - src/linglong/oci-cfg-generators/30_user_home.h - src/linglong/oci-cfg-generators/40_host_ipc.cpp - src/linglong/oci-cfg-generators/40_host_ipc.h - src/linglong/oci-cfg-generators/90_legacy.cpp - src/linglong/oci-cfg-generators/90_legacy.h - src/linglong/oci-cfg-generators/builtins.h.in src/linglong/oci-cfg-generators/container_cfg_builder.cpp src/linglong/oci-cfg-generators/container_cfg_builder.h - src/linglong/oci-cfg-generators/generator.h COMPILE_FEATURES PUBLIC cxx_std_17 diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.cpp deleted file mode 100644 index ef50fdbca..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "00_id_mapping.h" - -#include - -#include - -namespace linglong::generator { - -bool IDMapping::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - auto linux_ = config.linux_.value_or(ocppi::runtime::config::types::Linux{}); - - auto uidMappings = std::vector{ - ocppi::runtime::config::types::IdMapping{ - .containerID = ::getuid(), - .hostID = ::getuid(), - .size = 1, - } - }; - - auto gidMappings = std::vector{ - ocppi::runtime::config::types::IdMapping{ - .containerID = ::getgid(), - .hostID = ::getgid(), - .size = 1, - } - }; - - linux_.uidMappings = std::move(uidMappings); - linux_.gidMappings = std::move(gidMappings); - config.linux_ = std::move(linux_); - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.h deleted file mode 100644 index 862eb2723..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/00_id_mapping.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { -struct IDMapping : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "00-id-mapping"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.cpp deleted file mode 100644 index 6045c39a1..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "05_initialize.h" - -#include -#include - -namespace linglong::generator { - -bool Initialize::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - const auto &annotations = config.annotations.value(); - - auto appID = config.annotations->find("org.deepin.linglong.appID"); - if (appID == config.annotations->end()) { - std::cerr << "appID not found." << std::endl; - return false; - } - - if (appID->second.empty()) { - std::cerr << "appID is empty." << std::endl; - return false; - } - - auto mounts = config.mounts.value_or(std::vector{}); - - if (auto runtimeDir = annotations.find("org.deepin.linglong.runtimeDir"); - runtimeDir != annotations.end()) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/runtime", - .options = string_list{ "rbind", "ro" }, - .source = std::filesystem::path(runtimeDir->second) / "files", - .type = "bind" }); - } - - if (auto appDir = annotations.find("org.deepin.linglong.appDir"); appDir != annotations.end()) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/opt", - .options = string_list{ "nodev", "nosuid", "mode=700" }, - .source = "tmpfs", - .type = "tmpfs", - }); - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::filesystem::path("/opt/apps") / appID->second / "files", - .options = string_list{ "rbind", "rw" }, - .source = std::filesystem::path(appDir->second) / "files", - .type = "bind" }); - } - - std::srand(std::time(0)); - auto tmpDir = - std::filesystem::temp_directory_path() / ("linglong_tmp_" + std::to_string(std::rand())); - std::filesystem::create_directory(tmpDir.string()); - mounts.push_back(ocppi::runtime::config::types::Mount{ .destination = "/tmp", - .options = string_list{ "rbind", "rw" }, - .source = tmpDir, - .type = "bind" }); - - config.mounts = std::move(mounts); - - return true; -} -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.h deleted file mode 100644 index a6d082416..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/05_initialize.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct Initialize : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "05-initialize"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.cpp deleted file mode 100644 index b8a932f68..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later -#include "10_basics.h" - -#include "ocppi/runtime/config/types/Generators.hpp" - -#include - -namespace linglong::generator { - -bool Basics::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - nlohmann::json rawPatch; - - try { - rawPatch = nlohmann::json::parse(basicsPatch); - } catch (const std::exception &e) { - std::cerr << "parse basicsPatch failed:" << e.what() << std::endl; - return false; - } - - if (config.ociVersion != rawPatch["ociVersion"].get()) { - std::cerr << "ociVersion mismatched" << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - try { - auto rawConfig = nlohmann::json(config); - rawConfig = rawConfig.patch(rawPatch["patch"]); - config = rawConfig.get(); - } catch (const std::exception &e) { - std::cerr << "patch basics failed:" << e.what() << std::endl; - return false; - } - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.h.in b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.h.in deleted file mode 100644 index 9cb6567b8..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/10_basics.h.in +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct Basics : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "10-basics"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; - -private: - static constexpr std::string_view basicsPatch{ R"(@LINGLONG_OCI_CFG_GEN_10_BASICS@)" }; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp deleted file mode 100755 index aee503957..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "20_devices.h" - -#include -#include - -namespace linglong::generator { - -bool Devices::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - auto mounts = config.mounts.value_or(std::vector{}); - - auto bindIfExist = [&mounts](std::string_view source, std::string_view destination) mutable { - std::error_code ec; - if (!std::filesystem::exists(source, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << source << ": " << ec.message() - << std::endl; - return; - } - - return; - } - - auto realDest = destination.empty() ? source : destination; - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::string{ realDest }, - .options = string_list{ "rbind" }, - .source = std::string{ source }, - .type = "bind", - }); - }; - - bindIfExist("/run/udev", ""); - bindIfExist("/dev/snd", ""); - bindIfExist("/dev/dri", ""); - - for (const auto &entry : std::filesystem::directory_iterator{ "/dev" }) { - const auto &devPath = entry.path(); - auto devName = devPath.filename().string(); - if ((devName.rfind("video", 0) == 0) || (devName.rfind("nvidia", 0) == 0)) { - mounts.emplace_back(ocppi::runtime::config::types::Mount{ - .destination = devPath, - .options = string_list{ "rbind" }, - .source = devPath, - .type = "bind", - }); - } - } - - // using FHS media directory and ignore '/run/media' for now - // FIXME: the mount base location of udisks will be affected by the flag - // '--enable-fhs-media', if not set this option, udisks will choose `/run/media` as the - // mount location. some linux distros (e.g. ArchLinux) don't have this flag enabled, perhaps - // we could find a better way to compatible with those distros. - // https://github.com/storaged-project/udisks/commit/ae2a5ff1e49ae924605502ace170eb831e9c38e4 - std::error_code ec; - auto mediaDir = std::filesystem::path("/media"); - auto status = std::filesystem::symlink_status(mediaDir, ec); - if (ec && ec != std::errc::no_such_file_or_directory) { - std::cerr << "failed to get /media status of " - << ": " << ec.message() << std::endl; - return false; - } - - if (status.type() == std::filesystem::file_type::symlink) { - auto targetDir = std::filesystem::read_symlink(mediaDir, ec); - if (ec) { - std::cerr << "failed to resolve symlink." << std::endl; - return false; - } - - auto destinationDir = "/" + targetDir.string(); - - if (!std::filesystem::exists(destinationDir, ec)) { - if (ec) { - std::cerr << "check destination dir existence." << std::endl; - return false; - } - - std::cerr << "destination path not found." << std::endl; - return false; - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = destinationDir, - .options = string_list{ "rbind", "rshared" }, - .source = destinationDir, - .type = "bind", - }); - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/media", - .options = string_list{ "rbind", "ro", "copy-symlink" }, - .source = "/media", - .type = "bind", - }); - } else { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/media", - .options = string_list{ "rbind", "rshared" }, - .source = "/media", - .type = "bind", - }); - } - - config.mounts = std::move(mounts); - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.h deleted file mode 100644 index 6ec4cbbab..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/20_devices.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct Devices : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "20-devices"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.cpp deleted file mode 100644 index 478c271cf..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "25_host_env.h" - -#include - -#include - -namespace linglong::generator { - -bool HostEnv::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto appID = config.annotations->find("org.deepin.linglong.appID"); - if (appID == config.annotations->end()) { - std::cerr << "appID not found." << std::endl; - return false; - } - - if (appID->second.empty()) { - std::cerr << "appID is empty." << std::endl; - return false; - } - - auto process = config.process.value_or(ocppi::runtime::config::types::Process{}); - auto env = process.env.value_or(std::vector{}); - - env.push_back("LINGLONG_APPID=" + appID->second); - - const std::vector envList = { - "DISPLAY", - "LANG", - "LANGUAGE", - "XDG_SESSION_DESKTOP", - "D_DISABLE_RT_SCREEN_SCALE", - "XMODIFIERS", - "XCURSOR_SIZE", // 鼠标尺寸 - "DESKTOP_SESSION", - "DEEPIN_WINE_SCALE", - "XDG_CURRENT_DESKTOP", - "XIM", - "XDG_SESSION_TYPE", - "XDG_RUNTIME_DIR", - "CLUTTER_IM_MODULE", - "QT4_IM_MODULE", - "GTK_IM_MODULE", - "auto_proxy", // 网络系统代理自动代理 - "http_proxy", // 网络系统代理手动http代理 - "https_proxy", // 网络系统代理手动https代理 - "ftp_proxy", // 网络系统代理手动ftp代理 - "SOCKS_SERVER", // 网络系统代理手动socks代理 - "no_proxy", // 网络系统代理手动配置代理 - "USER", // wine应用会读取此环境变量 - "QT_IM_MODULE", // 输入法 - "LINGLONG_ROOT", // 玲珑安装位置 - "WAYLAND_DISPLAY", // 导入wayland相关环境变量 - "QT_QPA_PLATFORM", - "QT_WAYLAND_SHELL_INTEGRATION", - "GDMSESSION", - "QT_WAYLAND_FORCE_DPI", - "GIO_LAUNCHED_DESKTOP_FILE", // 系统监视器 - "GNOME_DESKTOP_SESSION_ID", // gnome 桌面标识,有些应用会读取此变量以使用gsettings配置, - // 如chrome - "TERM", - "DSG_APP_ID" // DSG 配置文件环境变量 - }; - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - // 如果是 onlyApp 模式,直接追加所有环境变量并返回 - for (char **envp = environ; *envp != nullptr; envp++) { - env.emplace_back(*envp); - } - } else { - // get the environment variables of current process - for (const auto &filter : envList) { - auto *host = ::getenv(filter.data()); - if (host != nullptr) { - env.emplace_back(std::string{ filter } + "=" + host); - } - } - } - - process.env = std::move(env); - config.process = std::move(process); - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.h deleted file mode 100644 index cce3b370f..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_env.h +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { -struct HostEnv : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "25-host-env"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.cpp deleted file mode 100644 index 357770dbb..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "25_host_rootfs.h" - -#include "ocppi/runtime/config/types/Generators.hpp" - -#include - -namespace linglong::generator { - -bool HostRootfs::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - nlohmann::json rawPatch; - - try { - rawPatch = nlohmann::json::parse(hostRootfsPatch); - } catch (const std::exception &e) { - std::cerr << "parse basicsPatch failed:" << e.what() << std::endl; - return false; - } - - if (config.ociVersion != rawPatch["ociVersion"].get()) { - std::cerr << "ociVersion mismatched" << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - try { - auto rawConfig = nlohmann::json(config); - rawConfig = rawConfig.patch(rawPatch["patch"]); - config = rawConfig.get(); - } catch (const std::exception &e) { - std::cerr << "patch basics failed:" << e.what() << std::endl; - return false; - } - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.h.in b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.h.in deleted file mode 100644 index 5a5585769..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_rootfs.h.in +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct HostRootfs : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "25-host-rootfs"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; - -private: - static constexpr std::string_view hostRootfsPatch{ R"(@LINGLONG_OCI_CFG_GEN_25_HOST_ROOTFS@)" }; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.cpp deleted file mode 100644 index d0c615a5a..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "25_host_statics.h" - -#include "ocppi/runtime/config/types/Generators.hpp" - -#include - -namespace linglong::generator { -bool HostStatics::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - nlohmann::json rawPatch; - - try { - rawPatch = nlohmann::json::parse(hostStaticsPatch); - } catch (const std::exception &e) { - std::cerr << "parse basicsPatch failed:" << e.what() << std::endl; - return false; - } - - if (config.ociVersion != rawPatch["ociVersion"].get()) { - std::cerr << "ociVersion mismatched" << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - try { - auto rawConfig = nlohmann::json(config); - rawConfig = rawConfig.patch(rawPatch["patch"]); - config = rawConfig.get(); - } catch (const std::exception &e) { - std::cerr << "patch basics failed:" << e.what() << std::endl; - return false; - } - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.h.in b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.h.in deleted file mode 100644 index e909bacac..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/25_host_statics.h.in +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct HostStatics : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "25-host-statics"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; - -private: - static constexpr std::string_view hostStaticsPatch{ - R"(@LINGLONG_OCI_CFG_GEN_25_HOST_STATICS@)" - }; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.cpp deleted file mode 100644 index 6c653102c..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "30_user_home.h" - -#include "linglong/api/types/v1/Generators.hpp" - -#include - -#include -#include -#include - -#include -#include - -// TODO: resolve xdg-user-dir config -std::string resolveXDGDir(const std::string &dirType) -{ - return dirType; -} - -namespace linglong::generator { - -bool UserHome::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (::getenv("LINGLONG_SKIP_HOME_GENERATE") != nullptr) { - return true; - } - - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - auto appID = config.annotations->find("org.deepin.linglong.appID"); - if (appID == config.annotations->end()) { - std::cerr << "appID not found." << std::endl; - return false; - } - - if (appID->second.empty()) { - std::cerr << "appID is empty." << std::endl; - return false; - } - - auto mounts = config.mounts.value_or(std::vector{}); - auto process = config.process.value_or(ocppi::runtime::config::types::Process{}); - auto env = process.env.value_or(std::vector{}); - - auto *homeEnv = ::getenv("HOME"); - auto *userNameEnv = ::getenv("USER"); - if (homeEnv == nullptr || userNameEnv == nullptr) { - std::cerr << "Couldn't get HOME or USER from env." << std::endl; - return false; - } - - auto hostHomeDir = std::filesystem::path(homeEnv); - auto cognitiveHomeDir = std::filesystem::path{ "/home" } / userNameEnv; - if (!std::filesystem::exists(hostHomeDir)) { - std::cerr << "Home " << hostHomeDir << "doesn't exists." << std::endl; - return false; - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/home", - .options = string_list{ "nodev", "nosuid", "mode=700" }, - .source = "tmpfs", - .type = "tmpfs", - }); - - auto envExist = [&env](const std::string &key) { - auto prefix = key + "="; - auto it = std::find_if(env.cbegin(), env.cend(), [&prefix](const std::string &item) { - return (item.rfind(prefix, 0) == 0); - }); - return it != env.cend(); - }; - - auto mountDir = [&mounts](const std::string &hostDir, const std::string &containerDir) { - std::error_code ec; - if (!std::filesystem::exists(hostDir, ec)) { - if (ec) { - std::cerr << "failed to get state of directories " << hostDir << ":" << ec.message() - << std::endl; - return false; - } - - if (!std::filesystem::create_directories(hostDir, ec) && ec) { - std::cerr << "failed to create directories " << hostDir << ":" << ec.message() - << std::endl; - return false; - } - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = containerDir, - .options = string_list{ "rbind" }, - .source = hostDir, - .type = "bind", - }); - - return true; - }; - - if (!mountDir(hostHomeDir, cognitiveHomeDir)) { - return false; - } - if (envExist("HOME")) { - std::cerr << "HOME already exist." << std::endl; - return false; - } - env.emplace_back("HOME=" + cognitiveHomeDir.string()); - - // process XDG_* environment variables. - std::error_code ec; - auto privateAppDir = hostHomeDir / ".linglong" / appID->second; - - if (!std::filesystem::create_directories(privateAppDir, ec) && ec) { - std::cerr << "failed to create " << privateAppDir << ": " << ec.message() << std::endl; - return false; - } - - // XDG_DATA_HOME - auto *ptr = ::getenv("XDG_DATA_HOME"); - std::filesystem::path XDGDataHome = ptr == nullptr ? "" : std::string{ ptr }; - if (XDGDataHome.empty()) { - XDGDataHome = hostHomeDir / ".local" / "share"; - } - - std::filesystem::path cognitiveDataHome = cognitiveHomeDir / ".local" / "share"; - if (!mountDir(XDGDataHome, cognitiveDataHome)) { - return false; - } - - if (envExist("XDG_DATA_HOME")) { - std::cerr << "XDG_DATA_HOME already exist." << std::endl; - return false; - } - env.emplace_back("XDG_DATA_HOME=" + cognitiveDataHome.string()); - - // XDG_CONFIG_HOME - ptr = ::getenv("XDG_CONFIG_HOME"); - std::filesystem::path XDGConfigHome = ptr == nullptr ? "" : std::string{ ptr }; - if (XDGConfigHome.empty()) { - XDGConfigHome = hostHomeDir / ".config"; - } - if (auto privateConfigDir = privateAppDir / "config"; - std::filesystem::exists(privateConfigDir, ec)) { - XDGConfigHome = privateConfigDir; - } - ec.clear(); - - auto cognitiveConfigHome = cognitiveHomeDir / ".config"; - if (!mountDir(XDGConfigHome, cognitiveConfigHome)) { - return false; - } - - if (envExist("XDG_CONFIG_HOME")) { - std::cerr << "XDG_CONFIG_HOME already exist." << std::endl; - return false; - } - env.emplace_back("XDG_CONFIG_HOME=" + cognitiveConfigHome.string()); - - // XDG_CACHE_HOME - ptr = ::getenv("XDG_CACHE_HOME"); - std::filesystem::path XDGCacheHome = ptr == nullptr ? "" : std::string{ ptr }; - if (XDGCacheHome.empty()) { - XDGCacheHome = hostHomeDir / ".cache"; - } - if (auto privateCacheDir = privateAppDir / "cache"; - std::filesystem::exists(privateCacheDir, ec)) { - XDGCacheHome = privateCacheDir; - } - ec.clear(); - - auto cognitiveCacheHome = cognitiveHomeDir / ".cache"; - if (!mountDir(XDGCacheHome, cognitiveCacheHome)) { - return false; - } - - if (envExist("XDG_CACHE_HOME")) { - std::cerr << "XDG_CACHE_HOME already exist." << std::endl; - return false; - } - env.emplace_back("XDG_CACHE_HOME=" + cognitiveCacheHome.string()); - - // XDG_STATE_HOME - ptr = ::getenv("XDG_STATE_HOME"); - std::filesystem::path XDGStateHome = ptr == nullptr ? "" : std::string{ ptr }; - if (XDGStateHome.empty()) { - XDGStateHome = hostHomeDir / ".local" / "state"; - } - if (auto privateStateDir = privateAppDir / "config"; - std::filesystem::exists(privateStateDir, ec)) { - XDGStateHome = privateStateDir; - } - ec.clear(); - - auto cognitiveStateHome = cognitiveHomeDir / ".local" / "state"; - if (!mountDir(XDGStateHome, cognitiveStateHome)) { - return false; - } - - if (envExist("XDG_STATE_HOME")) { - std::cerr << "XDG_STATE_HOME already exist." << std::endl; - return false; - } - env.emplace_back("XDG_STATE_HOME=" + cognitiveStateHome.string()); - - // systemd user path - auto hostSystemdUserDir = XDGConfigHome / "systemd" / "user"; - if (std::filesystem::exists(hostSystemdUserDir, ec)) { - auto cognitiveSystemdUserDir = cognitiveConfigHome / "systemd" / "user"; - if (!mountDir(hostSystemdUserDir, cognitiveSystemdUserDir)) { - return false; - } - } - - // FIXME: Many applications get configurations from dconf, so we expose dconf to all - // applications for now. If there is a better solution to fix this issue, please change the - // following codes - auto hostUserDconfPath = XDGConfigHome / "dconf"; - if (std::filesystem::exists(hostUserDconfPath, ec)) { - auto cognitiveAppDconfPath = cognitiveConfigHome / "dconf"; - if (!mountDir(hostUserDconfPath, cognitiveAppDconfPath)) { - return false; - } - } - - // for dde application theme - auto hostDDEApiPath = XDGCacheHome / "deepin" / "dde-api"; - if (std::filesystem::exists(hostDDEApiPath, ec)) { - auto cognitiveDDEApiPath = cognitiveCacheHome / "deepin" / "dde-api"; - if (!mountDir(hostDDEApiPath, cognitiveDDEApiPath)) { - return false; - } - } - - // for xdg-user-dirs - auto XDGUserDirs = XDGConfigHome / "user-dirs.dirs"; - if (std::filesystem::exists(XDGUserDirs, ec)) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveConfigHome / "user-dirs.dirs", - .options = string_list{ "rbind" }, - .source = XDGUserDirs, - .type = "bind", - }); - } - - auto XDGUserLocale = XDGConfigHome / "user-dirs.locale"; - if (std::filesystem::exists(XDGUserLocale, ec)) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveConfigHome / "user-dirs" / ".locale", - .options = string_list{ "rbind" }, - .source = XDGUserLocale, - .type = "bind", - }); - } - - // NOTE: - // Running ~/.bashrc from user home is meaningless in linglong container, - // and might cause some issues, so we mask it with the default one. - // https://github.com/linuxdeepin/linglong/issues/459 - constexpr auto defaultBashrc = "/etc/skel/.bashrc"; - if (std::filesystem::exists(defaultBashrc)) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = hostHomeDir / ".bashrc", - .options = string_list{ "ro", "rbind" }, - .source = defaultBashrc, - .type = "bind", - }); - } else { - std::cerr << "failed to mask bashrc" << std::endl; - } - - // hide self data - auto linglongMaskDataDir = hostHomeDir / ".linglong" / "data"; - if (!mountDir(linglongMaskDataDir, cognitiveHomeDir / ".linglong")) { - return false; - } - - linglong::api::types::v1::ApplicationConfigurationPermissions permissions; - auto configFile = privateAppDir / "permissions.json"; - if (std::filesystem::exists(configFile, ec)) { - auto input = std::ifstream(configFile); - if (!input.is_open()) { - std::cerr << "couldn't open config file " << configFile.c_str() << std::endl; - return false; - } - - try { - auto content = nlohmann::json::parse(input); - permissions = - content.get(); - } catch (nlohmann::json::parse_error &e) { - std::cerr << "deserialize error:" << e.what() << std::endl; - return false; - } catch (std::exception &e) { - std::cerr << "unknown exception:" << e.what() << std::endl; - return false; - } - } - if (ec) { - std::cerr << "failed to get status of " << configFile.c_str() << ": " << ec.message() - << std::endl; - return false; - } - - auto directories = permissions.xdgDirectories.value_or( - std::vector{}); - - // FIXME: we should resolve real home through env GNUPGHOME - // FIXME: we should resolve user dirs through ${XDG_CONFIG_HOME}/user-dirs.dirs - std::vector blacklist = { ".gnupg", ".ssh" }; - for (const auto &[allowed, dirType] : directories) { - if (!allowed) { - blacklist.push_back(resolveXDGDir(dirType)); - } - } - - auto it = - std::remove_if(blacklist.begin(), blacklist.end(), [&hostHomeDir](const std::string &dir) { - std::error_code ec; - auto ret = !std::filesystem::exists(hostHomeDir / dir, ec); - if (ec) { - std::cerr << "failed to get state of " << hostHomeDir / dir << ": " << ec.message() - << std::endl; - } - return ret; - }); - - if (it != blacklist.end()) { - blacklist.erase(it); - } - - for (const auto &relative : blacklist) { - if (!mountDir(privateAppDir / relative, cognitiveHomeDir / relative)) { - return false; - } - } - - process.env = std::move(env); - config.process = std::move(process); - config.mounts = std::move(mounts); - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.h deleted file mode 100644 index 642cf0a90..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/30_user_home.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { - -struct UserHome : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "30-user-home"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp deleted file mode 100644 index fb1c55924..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.cpp +++ /dev/null @@ -1,383 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "40_host_ipc.h" - -#include - -#include -#include -#include -#include - -#include -#include - -namespace linglong::generator { - -bool HostIPC::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - auto it = config.annotations->find("org.deepin.linglong.bundleDir"); - if (it == config.annotations->end()) { - std::cerr << "bundleDir not found." << std::endl; - return false; - } - - if (it->second.empty()) { - std::cerr << "appID is empty." << std::endl; - return false; - } - - auto bundleDir = std::filesystem::path{ it->second }; - auto mounts = config.mounts.value_or(std::vector{}); - auto process = config.process.value_or(ocppi::runtime::config::types::Process{}); - auto env = process.env.value_or(std::vector{}); - - auto bindIfExist = [&mounts](std::string_view source, std::string_view destination) mutable { - std::error_code ec; - - if (!std::filesystem::exists(source, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << source << ": " << ec.message() - << std::endl; - return; - } - - return; - } - - auto realDest = destination.empty() ? source : destination; - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::string{ realDest }, - .options = string_list{ "rbind" }, - .source = std::string{ source }, - .type = "bind", - }); - }; - - bindIfExist("/tmp/.X11-unix", ""); - - auto mountTemplate = - ocppi::runtime::config::types::Mount{ .options = string_list{ "rbind" }, .type = "bind" }; - - // TODO 应该参考规范文档实现更完善的地址解析支持 - // https://dbus.freedesktop.org/doc/dbus-specification.html#addresses - [dbusMount = mountTemplate, &mounts, &env]() mutable { - // default value from - // https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types-system - std::string systemBusEnv = "unix:path=/var/run/dbus/system_bus_socket"; - if (auto cStr = std::getenv("DBUS_SYSTEM_BUS_ADDRESS"); cStr != nullptr) { - systemBusEnv = cStr; - } - // address 可能是 unix:path=/xxxx,giud=xxx 这种格式 - // 所以先将options部分提取出来,挂载时不需要关心 - std::string options; - auto optionsPos = systemBusEnv.find(","); - if (optionsPos != std::string::npos) { - options = systemBusEnv.substr(optionsPos); - systemBusEnv.resize(optionsPos); - } - auto systemBus = std::string_view{ systemBusEnv }; - auto suffix = std::string_view{ "unix:path=" }; - if (systemBus.rfind(suffix, 0) != 0U) { - std::cerr << "Unexpected DBUS_SYSTEM_BUS_ADDRESS=" << systemBus << std::endl; - return; - } - - auto socketPath = std::filesystem::path(systemBus.substr(suffix.size())); - std::error_code ec; - if (!std::filesystem::exists(socketPath, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << socketPath << ": " << ec.message() - << std::endl; - return; - } - - std::cerr << "D-Bus session bus socket not found at " << socketPath << std::endl; - return; - } - - dbusMount.destination = "/run/dbus/system_bus_socket"; - dbusMount.source = std::move(socketPath); - mounts.emplace_back(std::move(dbusMount)); - // 将提取的options再拼到容器中的环境变量 - env.emplace_back("DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket" + options); - }(); - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/run/user", - .options = string_list{ "nodev", "nosuid", "mode=700" }, - .source = "tmpfs", - .type = "tmpfs", - }); - - [XDGMount = mountTemplate, &mounts, &env, &bindIfExist]() { - auto *XDGRuntimeDirEnv = getenv("XDG_RUNTIME_DIR"); // NOLINT - if (XDGRuntimeDirEnv == nullptr) { - return; - } - - auto hostXDGRuntimeDir = std::filesystem::path{ XDGRuntimeDirEnv }; - auto status = std::filesystem::status(hostXDGRuntimeDir); - using perm = std::filesystem::perms; - if (status.permissions() != perm::owner_all) { - std::cerr << "The Unix permission of " << hostXDGRuntimeDir << "must be 0700." - << std::endl; - return; - } - - struct stat64 buf{}; - if (::stat64(hostXDGRuntimeDir.string().c_str(), &buf) != 0) { - std::cerr << "Failed to get state of " << hostXDGRuntimeDir << ": " << ::strerror(errno) - << std::endl; - return; - } - - if (buf.st_uid != ::getuid()) { - std::cerr << hostXDGRuntimeDir << " doesn't belong to current user."; - return; - } - - auto cognitiveXDGRuntimeDir = - std::filesystem::path{ "/run/user" } / std::to_string(::getuid()); - - // tmpfs - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveXDGRuntimeDir, - .options = string_list{ "nodev", "nosuid", "mode=700" }, - .source = "tmpfs", - .type = "tmpfs", - }); - env.emplace_back(std::string{ "XDG_RUNTIME_DIR=" } + cognitiveXDGRuntimeDir.string()); - - bindIfExist((hostXDGRuntimeDir / "pulse").string(), - (cognitiveXDGRuntimeDir / "pulse").string()); - bindIfExist((hostXDGRuntimeDir / "gvfs").string(), - (cognitiveXDGRuntimeDir / "gvfs").string()); - - [&hostXDGRuntimeDir, &cognitiveXDGRuntimeDir, &mounts]() { - auto *waylandDisplayEnv = getenv("WAYLAND_DISPLAY"); // NOLINT - if (waylandDisplayEnv == nullptr) { - std::cerr << "Couldn't get WAYLAND_DISPLAY." << std::endl; - return; - } - - auto socketPath = std::filesystem::path(hostXDGRuntimeDir) / waylandDisplayEnv; - std::error_code ec; - if (!std::filesystem::exists(socketPath, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << socketPath << ": " - << ec.message() << std::endl; - return; - } - - std::cerr << "Wayland display socket not found at " << socketPath << "." - << std::endl; - return; - } - - mounts.emplace_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveXDGRuntimeDir / waylandDisplayEnv, - .options = string_list{ "rbind" }, - .source = socketPath, - .type = "bind", - }); - }(); - - // TODO 应该参考规范文档实现更完善的地址解析支持 - // https://dbus.freedesktop.org/doc/dbus-specification.html#addresses - [&cognitiveXDGRuntimeDir, &mounts, &env]() { - std::string sessionBusEnv; - if (auto cStr = std::getenv("DBUS_SESSION_BUS_ADDRESS"); cStr != nullptr) { - sessionBusEnv = cStr; - } - if (sessionBusEnv.empty()) { - std::cerr << "Couldn't get DBUS_SESSION_BUS_ADDRESS" << std::endl; - return; - } - // address 可能是 unix:path=/xxxx,giud=xxx 这种格式 - // 所以先将options部分提取出来,挂载时不需要关心 - std::string options; - auto optionsPos = sessionBusEnv.find(","); - if (optionsPos != std::string::npos) { - options = sessionBusEnv.substr(optionsPos); - sessionBusEnv.resize(optionsPos); - } - auto sessionBus = std::string_view{ sessionBusEnv }; - auto suffix = std::string_view{ "unix:path=" }; - if (sessionBus.rfind(suffix, 0) != 0U) { - std::cerr << "Unexpected DBUS_SESSION_BUS_ADDRESS=" << sessionBus << std::endl; - return; - } - - auto socketPath = std::filesystem::path(sessionBus.substr(suffix.size())); - if (!std::filesystem::exists(socketPath)) { - std::cerr << "D-Bus session bus socket not found at " << socketPath << std::endl; - return; - } - - auto cognitiveSessionBus = cognitiveXDGRuntimeDir / "bus"; - mounts.emplace_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveSessionBus, - .options = string_list{ "rbind" }, - .source = socketPath, - .type = "bind", - }); - // 将提取的options再拼到容器中的环境变量 - env.emplace_back(std::string{ "DBUS_SESSION_BUS_ADDRESS=" } - + "unix:path=" + cognitiveSessionBus.string() + options); - }(); - - [&hostXDGRuntimeDir, &cognitiveXDGRuntimeDir, &mounts]() { - auto dconfPath = std::filesystem::path(hostXDGRuntimeDir) / "dconf"; - if (!std::filesystem::exists(dconfPath)) { - std::cerr << "dconf directory not found at " << dconfPath << "." << std::endl; - return; - } - mounts.emplace_back(ocppi::runtime::config::types::Mount{ - .destination = cognitiveXDGRuntimeDir / "dconf", - .options = string_list{ "rbind" }, - .source = dconfPath.string(), - .type = "bind", - }); - }(); - } - - (); - - [xauthPatch = mountTemplate, &mounts, &env]() mutable { - if (::getenv("LINGLONG_SKIP_HOME_GENERATE") != nullptr) { - return; - } - - auto *homeEnv = ::getenv("HOME"); // NOLINT - if (homeEnv == nullptr) { - std::cerr << "Couldn't get HOME from env." << std::endl; - return; - } - - auto *userEnv = ::getenv("USER"); - if (userEnv == nullptr) { - std::cerr << "Couldn't get USER from env." << std::endl; - return; - } - - auto hostXauthFile = std::string{ homeEnv } + "/.Xauthority"; - auto cognitiveXauthFile = std::string{ "/home/" } + userEnv + "/.Xauthority"; - - auto *xauthFileEnv = ::getenv("XAUTHORITY"); // NOLINT - std::error_code ec; - if (xauthFileEnv != nullptr && std::filesystem::exists(xauthFileEnv, ec)) { - hostXauthFile = xauthFileEnv; - } - - if (!std::filesystem::exists(hostXauthFile, ec) && ec) { - std::cerr << "XAUTHORITY file not found at " << hostXauthFile << ":" << ec.message() - << std::endl; - return; - } - - env.emplace_back("XAUTHORITY=" + cognitiveXauthFile); - - xauthPatch.destination = std::move(cognitiveXauthFile); - xauthPatch.source = hostXauthFile; - mounts.emplace_back(std::move(xauthPatch)); - }(); - - // 在容器中把易变的文件挂载成软链接,指向/run/host/rootfs,实现实时响应 - std::array vec{ - "/etc/localtime", - "/etc/resolv.conf", - "/etc/timezone", - }; - - std::error_code ec; - for (const auto &destination : vec) { - auto target = destination; - auto name = target.filename(); - - if (!std::filesystem::exists(target, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << target << ": " << ec.message() - << std::endl; - return false; - } - - continue; - } - - auto status = std::filesystem::symlink_status(target, ec); - if (ec) { - std::cerr << "Failed to get status of " << target << ": " << ec.message() << std::endl; - return false; - } - - if (status.type() == std::filesystem::file_type::symlink) { - std::array buf{}; - auto *rpath = ::realpath(target.c_str(), buf.data()); - if (rpath == nullptr) { - std::cerr << "Failed to get realpath of " << target << ": " << ::strerror(errno) - << std::endl; - return false; - } - - target.assign(rpath); - } - - auto linkfile = bundleDir / name; - target = "/run/host/rootfs" / target.lexically_relative("/"); - std::filesystem::create_symlink(target, linkfile, ec); - if (ec) { - std::cerr << "Failed to create symlink from " << target << " to " << linkfile << ": " - << ec.message() << std::endl; - continue; - }; - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::string{ destination }, - .options = string_list{ "rbind", "ro", "copy-symlink" }, - .source = linkfile, - .type = "bind", - }); - } - - // process ld.so.cache - auto ldLink = bundleDir / "ld.so.cache"; - std::filesystem::create_symlink("/run/linglong/cache/ld.so.cache", ldLink, ec); - if (ec) { - std::cerr << "Failed to create symlink from " << "/run/linglong/cache/ld.so.cache" << " to " - << ldLink << ": " << ec.message() << std::endl; - return false; - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/etc/ld.so.cache", - .options = string_list{ "rbind", "ro", "copy-symlink" }, - .source = ldLink, - .type = "bind", - }); - - process.env = std::move(env); - config.process = std::move(process); - config.mounts = std::move(mounts); - - return true; -} - -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.h deleted file mode 100644 index affe7bc98..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/40_host_ipc.h +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { -struct HostIPC : public Generator -{ - [[nodiscard]] std::string_view name() const override { return "40-host-ipc"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.h deleted file mode 100644 index 438df75e5..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/generator.h" - -namespace linglong::generator { -class Legacy : public Generator -{ -public: - [[nodiscard]] std::string_view name() const override { return "90-legacy"; } - - bool generate(ocppi::runtime::config::types::Config &config) const noexcept override; -}; -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/builtins.h.in b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/builtins.h.in deleted file mode 100644 index 79a26f01b..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/builtins.h.in +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "linglong/oci-cfg-generators/00_id_mapping.h" -#include "linglong/oci-cfg-generators/05_initialize.h" -#include "linglong/oci-cfg-generators/10_basics.h" -#include "linglong/oci-cfg-generators/20_devices.h" -#include "linglong/oci-cfg-generators/25_host_env.h" -#include "linglong/oci-cfg-generators/25_host_rootfs.h" -#include "linglong/oci-cfg-generators/25_host_statics.h" -#include "linglong/oci-cfg-generators/30_user_home.h" -#include "linglong/oci-cfg-generators/40_host_ipc.h" -#include "linglong/oci-cfg-generators/90_legacy.h" - -namespace linglong::generator { - -using generators = std::map>; - -constexpr auto initConfig = R"(@LINGLONG_OCI_CFG_GEN_CONFIG@)"; - -inline const generators &builtin_generators() noexcept -{ - static std::unique_ptr gens; - if (gens) { - return *gens; - } - - gens = std::make_unique(); - - auto *id = new IDMapping{}; - gens->emplace(id->name(), id); - - auto *init = new Initialize{}; - gens->emplace(init->name(), init); - - auto *basics = new Basics{}; - gens->emplace(basics->name(), basics); - - auto *dev = new Devices{}; - gens->emplace(dev->name(), dev); - - auto *env = new HostEnv{}; - gens->emplace(env->name(), env); - - auto *rootfs = new HostRootfs{}; - gens->emplace(rootfs->name(), rootfs); - - auto *statics = new HostStatics{}; - gens->emplace(statics->name(), statics); - - auto *home = new UserHome{}; - gens->emplace(home->name(), home); - - auto *ipc = new HostIPC{}; - gens->emplace(ipc->name(), ipc); - - auto *legacy = new Legacy{}; - gens->emplace(legacy->name(), legacy); - - return *gens; -} -} // namespace linglong::generator diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/generator.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/generator.h deleted file mode 100644 index 2be7d1567..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/generator.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#pragma once - -#include "ocppi/runtime/config/types/Config.hpp" - -namespace linglong::generator { - -using string_list = std::vector; - -struct Generator -{ - Generator() = default; - virtual ~Generator() = default; - virtual bool generate(ocppi::runtime::config::types::Config &config) const noexcept = 0; - - [[nodiscard]] virtual std::string_view name() const = 0; -}; -} // namespace linglong::generator From 053fe005c5ec4cdb63f87fd18a8a31ab0ebf4065 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Wed, 11 Jun 2025 13:29:17 +0800 Subject: [PATCH 035/366] chore: update linglong.yaml Signed-off-by: ComixHe --- linglong.yaml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/linglong.yaml b/linglong.yaml index 654be24da..4baa80aa1 100644 --- a/linglong.yaml +++ b/linglong.yaml @@ -1,9 +1,7 @@ # SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later - version: "1" - package: id: cn.org.linyaps.builder.utils name: ll-builder-utils @@ -15,7 +13,6 @@ package: command: [/opt/apps/cn.org.linyaps.builder.utils/files/bin/ll-builder-export] base: org.deepin.base/25.2.0 - sources: - kind: archive url: https://github.com/erofs/erofs-utils/archive/refs/tags/v1.8.6.tar.gz @@ -24,16 +21,15 @@ sources: url: https://github.com/libfuse/libfuse/releases/download/fuse-3.17.1/fuse-3.17.1.tar.gz digest: 2d8ae87a4525fbfa1db5e5eb010ff6f38140627a7004554ed88411c1843d51b2 - kind: archive - url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.0-rc.3.tar.gz - digest: e90b696e8b4400d4c5c284cd14b88469ea8165b726f2584d146680790f4bf71d - + url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.0-rc.5.tar.gz + digest: 109bf9e8539ce5818f52be4283de12bf9a1adf4d6a7ae422f02a3e66cc5ab0e6 build: | echo "$PREFIX" # build libfuse static library cd /project/linglong/sources/fuse-3.17.1.tar.gz/fuse-3.17.1 patch lib/mount.c /project/apps/ll-builder-utils/patch/libfuse.patch - mkdir build + mkdir build || true cd build meson setup ../ meson configure --default-library static -D utils=false -D examples=false -D tests=false -D disable-libc-symbol-version=false @@ -43,21 +39,20 @@ build: | cd /project/linglong/sources/v1.8.6.tar.gz/erofs-utils-1.8.6 ./autogen.sh ./configure -with-libzstd --enable-fuse --enable-static-fuse --with-libdeflate --without-xxhash libdeflate_LIBS=-ldeflate libdeflate_CFLAGS=-ldeflate - make -j4 + make -j$(nproc) make install # build static ll-box - cd /project/linglong/sources/2.0.0-rc.3.tar.gz/linyaps-box-2.0.0-rc.3/ + cd /project/linglong/sources/2.0.0-rc.5.tar.gz/linyaps-box-2.0.0-rc.5/ cmake --preset static - cmake --build build-static -j8 + cmake --build build-static -j$(nproc) cmake --install build-static --prefix=$PREFIX cd /project - cmake -B build-linglong -DCPM_LOCAL_PACKAGES_ONLY=true -DENABLE_TESTING=false -DBUILD_LINGLONG_BUILDER_UTILS_IN_BOX=true - cmake --build build-linglong -j8 + cmake -B build-linglong -DCPM_LOCAL_PACKAGES_ONLY=true -DENABLE_TESTING=false -DBUILD_LINGLONG_BUILDER_UTILS_IN_BOX=true -DAGGRESSIVE_UAB_SIZE=ON + cmake --build build-linglong -j$(nproc) cmake --install build-linglong --prefix=$PREFIX install /usr/local/bin/mkfs.erofs $PREFIX/bin/ - buildext: apt: build_depends: [patch, meson, libtool, pkg-config, uuid-dev, libdeflate-dev, libzstd-dev, nlohmann-json3-dev, libyaml-cpp-dev, liblz4-dev, liblzma-dev, libselinux1-dev, libpcre2-dev, libelf-dev, libcap-dev, libcli11-dev, libgtest-dev] From 67aff2635e36a07e9344ddec446f0b3eb4902057 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Wed, 11 Jun 2025 13:29:46 +0800 Subject: [PATCH 036/366] fix: correct the way of exporting only-app UAB Signed-off-by: ComixHe --- apps/uab/header/src/light_elf.h | 2 +- apps/uab/header/src/main.cpp | 432 +++++++++++------- apps/uab/header/src/sha256.h | 18 +- apps/uab/loader/CMakeLists.txt | 4 +- apps/uab/loader/src/main.cpp | 418 ++++++++--------- .../src/linglong/package/uab_packager.cpp | 343 ++++++++------ 6 files changed, 669 insertions(+), 548 deletions(-) diff --git a/apps/uab/header/src/light_elf.h b/apps/uab/header/src/light_elf.h index 106124f51..517a8d5a2 100644 --- a/apps/uab/header/src/light_elf.h +++ b/apps/uab/header/src/light_elf.h @@ -117,7 +117,7 @@ class Elf shdrstrndx = shdr.sh_link; } - auto shdrstrtab = elfHeader.e_shoff + shdrstrndx * elfHeader.e_shentsize; + auto shdrstrtab = elfHeader.e_shoff + (shdrstrndx * elfHeader.e_shentsize); bytesRead = ::pread(fd, &shdr, section_size, shdrstrtab); if (bytesRead == -1) { throw std::runtime_error("failed to read section header string table of" + path.string() diff --git a/apps/uab/header/src/main.cpp b/apps/uab/header/src/main.cpp index 64da70dce..66ba90256 100644 --- a/apps/uab/header/src/main.cpp +++ b/apps/uab/header/src/main.cpp @@ -1,12 +1,11 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024 - 2025 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "light_elf.h" -#include "linglong/api/types/v1/Generators.hpp" +#include "linglong/api/types/v1/Generators.hpp" // IWYU pragma: keep #include "linglong/api/types/v1/UabMetaInfo.hpp" #include "sha256.h" -#include "utils.h" #include #include @@ -14,27 +13,29 @@ #include #include -#include #include #include -#include #include #include #include #include -#include #include +#include #include +#include #include #include #include extern "C" int erofsfuse_main(int argc, char **argv); -static std::atomic_bool mountFlag{ false }; // NOLINT -static std::atomic_bool createFlag{ false }; // NOLINT -static std::filesystem::path mountPoint; // NOLINT +namespace { + +std::atomic_bool mountFlag{ false }; // NOLINT +std::atomic_bool createFlag{ false }; // NOLINT +std::filesystem::path mountPoint; // NOLINT +constexpr std::size_t default_page_size = 4096; constexpr auto usage = u8R"(Linglong Universal Application Bundle @@ -49,7 +50,21 @@ uabBundle [uabOptions...] [-- loaderOptions...] --help print usage of uab [exclusive] )"; -std::string resolveRealPath(std::string_view source) noexcept +enum uabOption : std::uint8_t { + Help = 1, + Extract, + Meta, +}; + +struct argOption +{ + bool help{ false }; + bool printMeta{ false }; + std::string extractPath; + std::vector loaderArgs; +}; + +std::string resolveRealPath(const std::string &source) noexcept { std::array resolvedPath{}; @@ -62,63 +77,121 @@ std::string resolveRealPath(std::string_view source) noexcept return { ptr }; } +std::size_t getChunkSize(std::size_t bundleSize) noexcept +{ + std::size_t page_size{ default_page_size }; + const auto ret = sysconf(_SC_PAGESIZE); + if (ret > 0) { + page_size = ret; + } + + std::size_t block_size{ 0 }; + struct statvfs fs_info{}; + if (statvfs(".", &fs_info) > 0) { + block_size = fs_info.f_bsize; + } + + const auto base_block = std::max(page_size, block_size); + if (bundleSize <= static_cast(10 * 1024 * 1024)) { + return 64 * base_block; + } + + if (bundleSize <= static_cast(100 * 1024 * 1024)) { + return 128 * base_block; + } + + return 256 * base_block; +} + std::string calculateDigest(int fd, std::size_t bundleOffset, std::size_t bundleLength) noexcept { digest::SHA256 sha256; - std::array buf{}; - std::array md_value{}; - auto expectedRead = buf.size(); - int readLength{ 0 }; - - while ((readLength = ::pread(fd, buf.data(), expectedRead, bundleOffset)) != 0) { - if (readLength == -1) { - if (errno == EINTR) { - continue; - } + std::array digest{}; + auto *mem = mmap(nullptr, bundleLength, PROT_READ, MAP_PRIVATE, fd, bundleOffset); + if (mem != MAP_FAILED) { + posix_madvise(mem, bundleLength, POSIX_FADV_WILLNEED | POSIX_FADV_SEQUENTIAL); + sha256.update(reinterpret_cast(mem), bundleLength); + if (munmap(mem, bundleLength) == -1) { + std::cerr << "munmap error:" << ::strerror(errno) << std::endl; + } + } else { + // fallback to read blocks + posix_fadvise(fd, bundleOffset, bundleLength, POSIX_FADV_WILLNEED | POSIX_FADV_SEQUENTIAL); + std::align_val_t alignment{ default_page_size }; + if (auto ret = sysconf(_SC_PAGESIZE); ret > 0) { + alignment = static_cast(ret); + } - std::cerr << "read uab error:" << ::strerror(errno) << std::endl; + auto chunkSize = getChunkSize(bundleLength); + auto *buf = ::operator new(chunkSize, alignment, std::nothrow); + if (buf == nullptr) { + std::cerr << "failed to allocate aligned memory" << std::endl; return {}; } - sha256.update(buf.data(), readLength); + auto deleter = [alignment](void *ptr) noexcept { + ::operator delete(ptr, alignment, std::nothrow); + }; + std::unique_ptr buffer{ reinterpret_cast(buf), + deleter }; + + std::size_t totalRead{ 0 }; + while (totalRead < bundleLength) { + auto remaining = bundleLength - totalRead; + auto readBytes = std::min(remaining, chunkSize); + + auto bytesRead = pread(fd, buffer.get(), readBytes, bundleOffset + totalRead); + if (bytesRead < 0) { + if (errno == EINTR) { + continue; + } + + std::cerr << "read uab error:" << ::strerror(errno) << std::endl; + return {}; + } - bundleLength -= readLength; - if (bundleLength == 0) { - sha256.final(md_value.data()); - break; - } + if (bytesRead == 0) { + break; + } - bundleOffset += readLength; - expectedRead = bundleLength > buf.size() ? buf.size() : bundleLength; + sha256.update(buffer.get(), bytesRead); + totalRead += bytesRead; + } } + sha256.final(digest.data()); + std::stringstream stream; stream << std::setfill('0') << std::hex; - for (auto v : md_value) { + for (auto v : digest) { stream << std::setw(2) << static_cast(v); } return stream.str(); } -std::string find_fusermount() +std::optional find_fusermount() noexcept { - std::string res; - - const char *path = getenv("PATH"); - if (!path) { - return res; + auto *pathEnv = getenv("PATH"); + if (pathEnv == nullptr) { + return std::nullopt; } - auto search_dir = [](std::filesystem::path dir, std::string &res) { + auto search_dir = [](const std::filesystem::path &dir) -> std::optional { std::error_code ec; - auto iter = std::filesystem::directory_iterator{ dir, ec }; + auto iter = std::filesystem::directory_iterator{ + dir, + std::filesystem::directory_options::skip_permission_denied, + ec + }; + if (ec) { std::cerr << "failed to open directory " << dir << ": " << ec.message() << std::endl; - return false; + return std::nullopt; } - for (auto const &entry : iter) { + + for (const auto &entry : iter) { std::string filename = entry.path().filename(); if (filename.rfind("fusermount", 0) != 0) { continue; @@ -128,7 +201,7 @@ std::string find_fusermount() continue; } - struct stat sb; + struct stat sb{}; if (stat(entry.path().c_str(), &sb) == -1) { std::cerr << "stat error: " << strerror(errno) << std::endl; continue; @@ -136,37 +209,25 @@ std::string find_fusermount() if (sb.st_uid != 0 || (sb.st_mode & S_ISUID) == 0) { std::cerr << "skip " << entry.path() << std::endl; - ; continue; } - res = entry.path(); - return true; + return entry.path(); } - return false; + return std::nullopt; }; - const char *begin = path; - const char *end = path + strlen(path); - - while (begin < end) { - const char *colon = std::strchr(begin, ':'); - if (!colon) { - colon = end; + std::stringstream ss{ pathEnv }; + std::string path; + while (std::getline(ss, path, ':')) { + auto res = search_dir(path); + if (res) { + return res; } - - std::string dir(begin, colon); - if (!dir.empty()) { - if (search_dir(dir, res)) { - return res; - } - } - - begin = colon + 1; } - return res; + return std::nullopt; } int mountSelfBundle(const lightElf::native_elf &elf, @@ -209,11 +270,11 @@ int mountSelfBundle(const lightElf::native_elf &elf, } } - if (!getenv("FUSERMOUNT_PROG")) { + if (getenv("FUSERMOUNT_PROG") == nullptr) { auto fuserMountProg = find_fusermount(); - if (!fuserMountProg.empty()) { - setenv("FUSERMOUNT_PROG", fuserMountProg.c_str(), 1); - std::cerr << "use fusermount:" << fuserMountProg << std::endl; + if (fuserMountProg) { + setenv("FUSERMOUNT_PROG", fuserMountProg.value().c_str(), 1); + std::cerr << "use fusermount:" << fuserMountProg->string() << std::endl; } else { std::cerr << "fusermount not found" << std::endl; } @@ -223,16 +284,25 @@ int mountSelfBundle(const lightElf::native_elf &elf, } int status{ 0 }; - auto ret = ::waitpid(fusePid, &status, 0); - if (ret == -1) { - std::cerr << "waitpid() failed:" << ::strerror(errno) << std::endl; - return -1; + while (true) { + auto ret = ::waitpid(fusePid, &status, 0); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + std::cerr << "waitpid() failed:" << ::strerror(errno) << std::endl; + return -1; + } + break; } - ret = WEXITSTATUS(status); - if (ret != 0) { - std::cerr << "couldn't mount bundle, fuse error code:" << ret << std::endl; - ret = -1; + int ret{ -1 }; + if (WIFEXITED(status)) { + auto code = WEXITSTATUS(status); + ret = code; + } else if (WIFSIGNALED(status)) { + auto sig = WTERMSIG(status); + std::cerr << "erofsfuse terminated due to signal " << strsignal(sig) << std::endl; } return ret; @@ -240,58 +310,48 @@ int mountSelfBundle(const lightElf::native_elf &elf, void cleanResource() noexcept { - auto umountRet = [] { - if (!mountFlag.load(std::memory_order_relaxed)) { - return true; - } - - auto pid = fork(); - if (pid < 0) { - std::cerr << "fork() error" << ": " << ::strerror(errno) << std::endl; - return false; - } + if (!mountFlag.load(std::memory_order_relaxed)) { + return; + } - if (pid == 0) { - if (::execlp("fusermount", "fusermount", "-z", "-u", mountPoint.c_str(), nullptr) - == -1) { - std::cerr << "fusermount error: " << ::strerror(errno) << std::endl; - return false; - } - } + auto pid = fork(); + if (pid < 0) { + std::cerr << "fork() error" << ": " << ::strerror(errno) << std::endl; + return; + } - int status{ 0 }; - auto ret = ::waitpid(pid, &status, 0); - if (ret == -1) { - std::cerr << "wait failed:" << ::strerror(errno) << std::endl; - return false; + if (pid == 0) { + if (::execlp("fusermount", "fusermount", "-z", "-u", mountPoint.c_str(), nullptr) == -1) { + std::cerr << "fusermount error: " << ::strerror(errno) << std::endl; + ::_exit(1); } - mountFlag.store(false, std::memory_order_relaxed); - return true; - }(); - - if (umountRet && createFlag.load(std::memory_order_relaxed)) { - std::error_code ec; - if (!std::filesystem::exists(mountPoint, ec)) { - if (ec) { - std::cerr << "filesystem error " << mountPoint << ":" << ec.message() << std::endl; - return; - } + ::_exit(0); + } - createFlag.store(false, std::memory_order_relaxed); - return; - } + int status{ 0 }; + auto ret = ::waitpid(pid, &status, 0); + if (ret == -1) { + std::cerr << "wait failed:" << ::strerror(errno) << std::endl; + return; + } + mountFlag.store(false, std::memory_order_relaxed); - if (std::filesystem::remove_all(mountPoint, ec) == static_cast(-1) || ec) { - std::cerr << "failed to remove mount point:" << ec.message() << std::endl; - return; - } + if (!createFlag.load(std::memory_order_relaxed)) { + return; + } - createFlag.store(false, std::memory_order_relaxed); + // try to remove mount point + std::error_code ec; + if (std::filesystem::remove_all(mountPoint, ec) == static_cast(-1) && ec) { + std::cerr << "failed to remove mount point:" << ec.message() << std::endl; + return; } + + createFlag.store(false, std::memory_order_relaxed); } -[[noreturn]] static void cleanAndExit(int exitCode) noexcept +[[noreturn]] void cleanAndExit(int exitCode) noexcept { cleanResource(); ::_exit(exitCode); @@ -299,20 +359,19 @@ void cleanResource() noexcept void handleSig() noexcept { - auto handler = [](int sig) -> void { - cleanAndExit(sig); - }; - sigset_t blocking_mask; sigemptyset(&blocking_mask); - auto quitSignals = { SIGTERM, SIGINT, SIGQUIT, SIGHUP, SIGABRT, SIGSEGV }; + auto quitSignals = { SIGTERM, SIGINT, SIGQUIT, SIGHUP, SIGABRT }; for (auto sig : quitSignals) { sigaddset(&blocking_mask, sig); } struct sigaction sa{}; - sa.sa_handler = handler; + sa.sa_handler = [](int sig) -> void { + // TODO: maybe not async safe, find a better way to handle signal + cleanAndExit(128 + sig); + }; sa.sa_mask = blocking_mask; sa.sa_flags = 0; @@ -335,16 +394,17 @@ int createMountPoint(std::string_view uuid) noexcept runtimeDirPtr = "/tmp"; } - auto mountPointPath = - std::filesystem::path{ resolveRealPath(runtimeDirPtr) } / "linglong" / "UAB" / uuid; + auto runtimeDir = resolveRealPath(runtimeDirPtr); + if (runtimeDir.empty()) { + return -1; + } + auto mountPointPath = std::filesystem::path{ runtimeDir } / "linglong" / "UAB" / uuid; std::error_code ec; - if (!std::filesystem::create_directories(mountPointPath, ec)) { - if (ec.value() != EEXIST) { - std::cerr << "couldn't create mount point " << mountPoint << ": " << ec.message() - << std::endl; - return ec.value(); - } + if (!std::filesystem::create_directories(mountPointPath, ec) && ec) { + std::cerr << "couldn't create mount point " << mountPointPath << ": " << ec.message() + << std::endl; + return ec.value(); } mountPoint = std::move(mountPointPath); @@ -353,7 +413,8 @@ int createMountPoint(std::string_view uuid) noexcept return 0; } -std::optional getMetaInfo(const lightElf::native_elf &elf) +std::optional +getMetaInfo(const lightElf::native_elf &elf) noexcept { auto metaSh = elf.getSectionHeader("linglong.meta"); if (!metaSh) { @@ -367,11 +428,13 @@ std::optional getMetaInfo(const lightElf: return {}; } - nlohmann::json meta; + std::optional meta; try { - meta = nlohmann::json::parse(content); - } catch (const std::exception &ex) { - std::cerr << "exception: " << ex.what() << std::endl; + auto json = nlohmann::json::parse(content); + meta = json.get(); + } catch (const nlohmann::json::parse_error &e) { + std::cerr << "exception: " << e.what() << std::endl; + return std::nullopt; } return meta; @@ -397,23 +460,32 @@ int extractBundle(std::string_view destination) noexcept return 0; } -[[noreturn]] void runAppLoader(bool onlyApp, - const std::vector &loaderArgs) noexcept +int runAppLoader(bool onlyApp, const std::vector &loaderArgs) noexcept { auto loader = mountPoint / "loader"; - auto loaderStr = loader.string(); + std::error_code ec; + if (!std::filesystem::exists(loader, ec)) { + if (ec) { + std::cerr << "failed to get loader status" << std::endl; + return -1; + } + + std::cout << "This UAB is not support for runnning" << std::endl; + return 0; + } + auto argc = loaderArgs.size() + 2; auto *argv = new (std::nothrow) const char *[argc](); if (argv == nullptr) { std::cerr << "out of memory, exit." << std::endl; - cleanAndExit(ENOMEM); + return ENOMEM; } auto deleter = defer([argv] { delete[] argv; }); - argv[0] = loaderStr.c_str(); + argv[0] = loader.c_str(); argv[argc - 1] = nullptr; for (std::size_t i = 0; i < loaderArgs.size(); ++i) { argv[i + 1] = loaderArgs[i].data(); @@ -422,20 +494,19 @@ int extractBundle(std::string_view destination) noexcept auto loaderPid = fork(); if (loaderPid < 0) { std::cerr << "fork() error" << ": " << ::strerror(errno) << std::endl; - cleanAndExit(errno); + return errno; } if (loaderPid == 0) { - std::string_view newEnv{ "LINGLONG_UAB_LOADER_ONLY_APP=true" }; - if (onlyApp && ::putenv(const_cast(newEnv.data())) < 0) { - std::cerr << "putenv error: " << ::strerror(errno) << std::endl; - cleanAndExit(errno); + if (onlyApp && ::setenv("LINGLONG_UAB_LOADER_ONLY_APP", "true", 1) < 0) { + std::cerr << "setenv error: " << ::strerror(errno) << std::endl; + return errno; } - if (::execv(loaderStr.c_str(), reinterpret_cast(const_cast(argv))) + if (::execv(loader.c_str(), reinterpret_cast(const_cast(argv))) == -1) { - std::cerr << "execv(" << loaderStr << ") error: " << ::strerror(errno) << std::endl; - cleanAndExit(errno); + std::cerr << "execv(" << loader << ") error: " << ::strerror(errno) << std::endl; + return errno; } } @@ -443,25 +514,21 @@ int extractBundle(std::string_view destination) noexcept auto ret = ::waitpid(loaderPid, &status, 0); if (ret == -1) { std::cerr << "waitpid failed:" << ::strerror(errno) << std::endl; - cleanAndExit(errno); + return errno; } - cleanAndExit(WEXITSTATUS(status)); -} + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } -enum uabOption { - Help = 1, - Extract, - Meta, -}; + if (WIFSIGNALED(status)) { + // maybe we runnning under a shell + return 128 + WTERMSIG(status); + } -struct argOption -{ - bool help{ false }; - bool printMeta{ false }; - std::string extractPath; - std::vector loaderArgs; -}; + std::cerr << "unknown exit state of loader" << std::endl; + return -1; +} argOption parseArgs(const std::vector &args) { @@ -538,12 +605,13 @@ int mountSelf(const lightElf::native_elf &elf, } if (auto ret = mountSelfBundle(elf, metaInfo); ret != 0) { - return -1; + return ret; } mountFlag.store(true, std::memory_order_relaxed); return 0; } +} // namespace int main(int argc, char **argv) { @@ -576,21 +644,33 @@ int main(int argc, char **argv) return 0; } + // for cleaning up mount point + if (std::atexit(cleanResource) != 0) { + std::cerr << "failed register exit handler" << std::endl; + return 1; + } + + std::set_terminate([]() { + cleanResource(); + std::abort(); + }); + if (!opts.extractPath.empty()) { - if (mountSelf(elf, metaInfo) != 0) { - cleanAndExit(-1); + if (auto ret = mountSelf(elf, metaInfo); ret != 0) { + return ret; } - cleanAndExit(extractBundle(opts.extractPath)); + return extractBundle(opts.extractPath); } - if (mountSelf(elf, metaInfo) != 0) { - cleanAndExit(-1); + if (auto ret = mountSelf(elf, metaInfo); ret != 0) { + return ret; } bool onlyApp = metaInfo.onlyApp.value_or(false); if (onlyApp) { - std::string appID, module; + std::string appID; + std::string module; for (const auto &layer : metaInfo.layers) { if (layer.info.kind == "app") { appID = layer.info.id; @@ -598,13 +678,19 @@ int main(int argc, char **argv) break; } } + + if (appID.empty() || module.empty()) { + std::cerr << "failed to find appID and module" << std::endl; + return 1; + } + std::string envAppRoot = std::string(mountPoint) + "/layers/" + appID + "/" + module + "/files"; - if (-1 == ::setenv("LINGLONG_UAB_APPROOT", const_cast(envAppRoot.data()), 1)) { + if (::setenv("LINGLONG_UAB_APPROOT", const_cast(envAppRoot.data()), 1) == -1) { std::cerr << "setenv error: " << ::strerror(errno) << std::endl; - cleanAndExit(errno); + return 1; } } - runAppLoader(onlyApp, opts.loaderArgs); + return runAppLoader(onlyApp, opts.loaderArgs); } diff --git a/apps/uab/header/src/sha256.h b/apps/uab/header/src/sha256.h index 0c1291078..9e54a1523 100644 --- a/apps/uab/header/src/sha256.h +++ b/apps/uab/header/src/sha256.h @@ -13,12 +13,12 @@ namespace digest { namespace details { -constexpr static inline uint32_t rotate_right(uint32_t x, unsigned n) noexcept +constexpr static uint32_t rotate_right(uint32_t x, unsigned n) noexcept { return (x >> n) | (x << (32 - n)); } -constexpr static inline uint32_t to_big_endian(uint32_t val) noexcept +constexpr static uint32_t to_big_endian(uint32_t val) noexcept { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return x; @@ -28,7 +28,7 @@ constexpr static inline uint32_t to_big_endian(uint32_t val) noexcept #endif } -constexpr static inline uint64_t to_big_endian(uint64_t val) noexcept +constexpr static uint64_t to_big_endian(uint64_t val) noexcept { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return x; @@ -40,32 +40,32 @@ constexpr static inline uint64_t to_big_endian(uint64_t val) noexcept #endif } -constexpr static inline uint32_t sum0(uint32_t x) noexcept +constexpr static uint32_t sum0(uint32_t x) noexcept { return rotate_right(x, 2) ^ rotate_right(x, 13) ^ rotate_right(x, 22); } -constexpr static inline uint32_t sum1(uint32_t x) noexcept +constexpr static uint32_t sum1(uint32_t x) noexcept { return rotate_right(x, 6) ^ rotate_right(x, 11) ^ rotate_right(x, 25); } -constexpr static inline uint32_t sigma0(uint32_t x) noexcept +constexpr static uint32_t sigma0(uint32_t x) noexcept { return rotate_right(x, 7) ^ rotate_right(x, 18) ^ (x >> 3); } -constexpr static inline uint32_t sigma1(uint32_t x) noexcept +constexpr static uint32_t sigma1(uint32_t x) noexcept { return rotate_right(x, 17) ^ rotate_right(x, 19) ^ (x >> 10); } -constexpr static inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) noexcept +constexpr static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) noexcept { return (x & y) ^ ((~x) & z); } -constexpr static inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) noexcept +constexpr static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) noexcept { return (x & y) ^ (x & z) ^ (y & z); } diff --git a/apps/uab/loader/CMakeLists.txt b/apps/uab/loader/CMakeLists.txt index 118304880..5f795839f 100644 --- a/apps/uab/loader/CMakeLists.txt +++ b/apps/uab/loader/CMakeLists.txt @@ -10,8 +10,8 @@ pfl_add_executable( uab-loader LINK_LIBRARIES PRIVATE - linglong::oci-cfg-generators - nlohmann_json::nlohmann_json) + linglong::api + linglong::oci-cfg-generators) set(UAB_LOADER_TARGET) get_real_target_name(UAB_LOADER_TARGET linglong::loader) diff --git a/apps/uab/loader/src/main.cpp b/apps/uab/loader/src/main.cpp index 67effbbdf..fed593967 100644 --- a/apps/uab/loader/src/main.cpp +++ b/apps/uab/loader/src/main.cpp @@ -2,12 +2,11 @@ // // SPDX-License-Identifier: LGPL-3.0-or-later -#include "linglong/api/types/v1/Generators.hpp" -#include "linglong/oci-cfg-generators/builtins.h" -#include "ocppi/runtime/config/types/Config.hpp" -#include "ocppi/runtime/config/types/Generators.hpp" +#include "linglong/api/types/v1/Generators.hpp" // IWYU pragma: keep +#include "linglong/oci-cfg-generators/container_cfg_builder.h" +#include "ocppi/runtime/config/types/Generators.hpp" // IWYU pragma: keep #include "ocppi/runtime/config/types/Hook.hpp" -#include "ocppi/runtime/config/types/Mount.hpp" +#include "ocppi/runtime/config/types/Linux.hpp" #include @@ -27,21 +26,9 @@ #include #include -static std::filesystem::path containerBundle; +namespace { -template -struct defer -{ - explicit defer(Func newF) - : f(std::move(newF)) - { - } - - ~defer() { f(); } - -private: - Func f; -}; +std::filesystem::path containerBundle; std::string genRandomString() noexcept { @@ -73,44 +60,33 @@ void cleanResource() } std::error_code ec; - if (!std::filesystem::exists(containerBundle, ec)) { - if (ec) { - std::cerr << "filesystem error:" << containerBundle << " " << ec.message() << std::endl; - return; - } - - return; - } - - if (std::filesystem::remove_all(containerBundle, ec) == static_cast(-1)) { + if (std::filesystem::remove_all(containerBundle, ec) == static_cast(-1) && ec) { std::cerr << "failed to remove directory " << containerBundle << ":" << ec.message() << std::endl; return; } } -[[noreturn]] static void cleanAndExit(int exitCode) noexcept +[[noreturn]] void cleanAndExit(int exitCode) noexcept { cleanResource(); - ::exit(exitCode); + ::_exit(exitCode); } void handleSig() noexcept { - auto handler = [](int sig) -> void { - cleanAndExit(sig); - }; - sigset_t blocking_mask; sigemptyset(&blocking_mask); - auto quitSignals = { SIGTERM, SIGINT, SIGQUIT, SIGHUP, SIGABRT, SIGSEGV }; + auto quitSignals = { SIGTERM, SIGINT, SIGQUIT, SIGHUP, SIGABRT }; for (auto sig : quitSignals) { sigaddset(&blocking_mask, sig); } struct sigaction sa{}; - sa.sa_handler = handler; + sa.sa_handler = [](int sig) -> void { + cleanAndExit(128 + sig); + }; sa.sa_mask = blocking_mask; sa.sa_flags = 0; @@ -119,58 +95,6 @@ void handleSig() noexcept } } -void applyPatches(ocppi::runtime::config::types::Config &config) noexcept -{ - const auto &builtins = linglong::generator::builtin_generators(); - for (const auto &[name, gen] : builtins) { - if (!gen->generate(config)) { - std::cerr << "generator " << name << " failed" << std::endl; - } - } -} - -[[nodiscard]] bool prepareRootfs(std::filesystem::path baseDir, - ocppi::runtime::config::types::Config &config) noexcept -{ - if (baseDir.empty()) { - baseDir = "/"; - - // this is used to skipping some oci-cfg-generators - config.annotations.value()["org.deepin.linglong.onlyApp"] = "true"; - } - - std::error_code ec; - auto fsIter = std::filesystem::directory_iterator{ baseDir, ec }; - if (ec) { - std::cerr << "couldn't get directory iterator:" << ec.message() << std::endl; - return false; - } - - auto mounts = config.mounts.value_or(std::vector{}); - for (const auto &file : fsIter) { - auto path = file.path(); - std::vector options{ "rbind" }; - if (std::filesystem::is_symlink(path, ec)) { - options.emplace_back("copy-symlink"); - } - - if (ec) { - std::cerr << "filesystem error:" << ec.message() << std::endl; - return false; - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = "/" / path.lexically_relative(baseDir), - .options = std::move(options), - .source = path, - .type = "bind", - }); - } - - config.mounts = std::move(mounts); - return true; -} - std::optional loadPackageInfoFromJson(const std::filesystem::path &json) noexcept { @@ -220,83 +144,78 @@ loadPackageInfoFromJson(const std::filesystem::path &json) noexcept return std::nullopt; } -bool processCaches(ocppi::runtime::config::types::Config &config, - const std::filesystem::path &extraDir, - bool onlyApp) noexcept +bool processLDConfig(linglong::generator::ContainerCfgBuilder &builder, + const std::string &arch) noexcept { - std::error_code ec; - auto cacheDir = containerBundle / "cache"; - auto ldCacheDir = cacheDir / "ld.so.cache.d"; - if (!std::filesystem::create_directories(ldCacheDir, ec)) { - std::cerr << "failed to create ld cache directory:" << ec.message() << std::endl; - return -1; + std::optional triplet; + if (arch == "x86_64") { + triplet = "x86_64-linux-gnu"; + } else if (arch == "arm64") { + triplet = "aarch64-linux-gnu"; + } else if (arch == "loong64" || arch == "loongarch64") { + triplet = "loongarch64-linux-gnu"; + } else if (arch == "sw64") { + triplet = "sw_64-linux-gnu"; + } else if (arch == "mips64") { + triplet = "mips64el-linux-gnuabi64"; + } + + if (!triplet) { + std::cerr << "unsupported architecture" << std::endl; + return false; } - config.mounts->push_back(ocppi::runtime::config::types::Mount{ - .destination = "/run/linglong/cache", - .options = { { "rbind", "rw" } }, - .source = ldCacheDir, - .type = "bind", - }); - - // append ld conf - auto ldConfDir = extraDir / "ld.conf.d"; - if (!std::filesystem::exists(ldConfDir, ec)) { - if (ec) { - std::cerr << "failed to check ld conf directory " << ldConfDir << ":" << ec.message() - << " code:" << ec.value() << std::endl; - return -1; + auto content = builder.ldConf(triplet.value()); + auto ldConf = builder.getBundlePath() / "ld.so.conf"; + { + std::ofstream stream{ ldConf }; + if (!stream.is_open()) { + std::cout << "failed to open " << ldConf.string() << std::endl; + return false; } - std::cerr << ldConfDir << " not exist." << std::endl; - return -1; + stream << content; } - config.mounts->push_back(ocppi::runtime::config::types::Mount{ - .destination = "/run/linglong/cache/ld.so.conf", - .options = { { "ro", "rbind" } }, - .source = ldConfDir / "zz_deepin-linglong-app.ld.so.conf", - .type = "bind", - }); - - auto hooks = config.hooks.value_or(ocppi::runtime::config::types::Hooks{}); - auto startHooks = - hooks.startContainer.value_or(std::vector{}); - startHooks.push_back(ocppi::runtime::config::types::Hook{ - .args = std::vector{ "/sbin/ldconfig", - "-f", - "/run/linglong/cache/ld.so.conf", - "-C", - "/run/linglong/cache/ld.so.cache" }, - .path = "/sbin/ldconfig", - }); - - if (!onlyApp) { - auto fontCacheDir = cacheDir / "fontconfig"; - if (!std::filesystem::create_directories(fontCacheDir, ec)) { - std::cerr << "failed to create font cache directory:" << ec.message() << std::endl; - return -1; + // trigger fixMount + auto randomFile = builder.getBundlePath() / genRandomString(); + { + std::ofstream stream{ randomFile }; + if (!stream.is_open()) { + std::cout << "failed to open " << ldConf.string() << std::endl; + return false; } - - config.mounts->push_back(ocppi::runtime::config::types::Mount{ - .destination = "/var/cache/fontconfig", - .options = { { "rbind", "rw" } }, - .source = fontCacheDir, - .type = "bind", - }); - - startHooks.push_back(ocppi::runtime::config::types::Hook{ - .args = std::vector{ "/bin/fc-cache", "-f" }, - .path = "/bin/fc-cache", - }); } - hooks.startContainer = std::move(startHooks); - config.hooks = std::move(hooks); + builder.addExtraMounts({ { + .destination = "/etc/" + randomFile.filename().string(), + .options = { { "ro", "rbind" } }, + .source = randomFile, + .type = "bind", + }, + { + .destination = "/etc/ld.so.conf.d/zz_deepin-linglong.ld.so.conf", + .options = { { "ro", "rbind" } }, + .source = ldConf, + .type = "bind", + } }); + + builder.setStartContainerHooks( + { { + .args = std::vector{ "/sbin/ldconfig", "-C", "/tmp/ld.so.cache" }, + .path = "/sbin/ldconfig", + }, + { + .args = + std::vector{ "/bin/sh", "-c", "cat /tmp/ld.so.cache > /etc/ld.so.cache" }, + .path = "/bin/sh", + } }); return true; } +} // namespace + // DO NOT USE LOADER DIRECTLY int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT { @@ -368,21 +287,6 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT return -1; } - const auto &baseStr = appInfo->base; - auto splitSlash = std::find(baseStr.cbegin(), baseStr.cend(), '/'); - auto splitColon = std::find(baseStr.cbegin(), baseStr.cend(), ':'); - auto baseID = - baseStr.substr(std::distance(baseStr.cbegin(), splitColon) + 1, splitSlash - splitColon - 1); - - std::string runtimeID; - if (appInfo->runtime) { - const auto &runtimeStr = appInfo->runtime.value(); - auto splitSlash = std::find(runtimeStr.cbegin(), runtimeStr.cend(), '/'); - auto splitColon = std::find(runtimeStr.cbegin(), runtimeStr.cend(), ':'); - runtimeID = runtimeStr.substr(std::distance(runtimeStr.cbegin(), splitColon) + 1, - splitSlash - splitColon - 1); - } - auto containerID = genRandomString(); auto containerBundleDir = bundleDir.parent_path().parent_path() / containerID; if (!std::filesystem::create_directories(containerBundleDir, ec) && ec) { @@ -392,7 +296,48 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT } containerBundle = std::move(containerBundleDir); - defer removeContainerBundleDir{ cleanResource }; + + if (std::atexit(cleanResource) != 0) { + std::cerr << "failed register exit handler" << std::endl; + return 1; + } + + std::set_terminate([]() { + cleanResource(); + std::abort(); + }); + + auto uid = ::getuid(); + auto gid = ::getgid(); + linglong::generator::ContainerCfgBuilder builder; + + auto runtimeLD = containerBundle / "ld.so.cache"; + { + std::ofstream stream{ runtimeLD }; + if (!stream) { + std::cerr << "failed to open file " << runtimeLD << std::endl; + return -1; + } + } + + builder.setBundlePath(containerBundle) + .setBasePath("/") + .enableSelfAdjustingMount() + .forwardEnv() + .addUIdMapping(uid, uid, 1) + .addGIdMapping(gid, gid, 1) + .addExtraMounts({ { + .destination = "/etc/ld.so.cache", + .options = { { "rbind" } }, + .source = runtimeLD, + .type = "bind", + }, + { + .destination = "/tmp", + .options = { { "rbind" } }, + .source = "/tmp", + .type = "bind", + } }); auto extraDir = bundleDir / "extra"; if (!std::filesystem::exists(extraDir, ec)) { @@ -418,16 +363,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT return -1; } - ocppi::runtime::config::types::Config config; - try { - auto content = nlohmann::json::parse(linglong::generator::initConfig); - config = content.get(); - } catch (std::exception &e) { - std::cerr << "catch an exception:" << e.what() << std::endl; - return -1; - } - - auto compatibleFilePath = [&bundleDir](std::string_view layerID) -> std::string { + auto compatibleFilePath = [&bundleDir](std::string_view layerID) -> std::filesystem::path { std::error_code ec; auto layerDir = bundleDir / "layers" / layerID; if (!std::filesystem::exists(layerDir, ec)) { @@ -442,11 +378,11 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT } // ignore error code when directory doesn't exist - if (auto runtime = layerDir / "runtime/files"; std::filesystem::exists(runtime, ec)) { + if (auto runtime = layerDir / "runtime" / "files"; std::filesystem::exists(runtime, ec)) { return runtime.string(); } - if (auto binary = layerDir / "binary/files"; std::filesystem::exists(binary, ec)) { + if (auto binary = layerDir / "binary" / "files"; std::filesystem::exists(binary, ec)) { return binary.string(); } @@ -460,27 +396,31 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT return -1; } - config.root->path = rootfs; - config.root->readonly = true; + const auto &appID = appInfo->id; + builder.setAppId(appID); + + std::string runtimeID; + if (appInfo->runtime) { + const auto &runtimeStr = appInfo->runtime.value(); + + std::size_t begin{ 0 }; + auto splitColon = std::find(runtimeStr.cbegin(), runtimeStr.cend(), ':'); + if (splitColon != runtimeStr.cend()) { + begin = std::distance(runtimeStr.cbegin(), splitColon) + 1; + } - auto appID = appInfo->id; - auto annotations = config.annotations.value_or(std::map{}); - annotations["org.deepin.linglong.appID"] = appID; + auto splitSlash = std::find(runtimeStr.cbegin(), runtimeStr.cend(), '/'); + auto len = std::distance(runtimeStr.cbegin(), splitSlash) - begin; - bool onlyApp = ::getenv("LINGLONG_UAB_LOADER_ONLY_APP") != nullptr; - std::string baseLayerFilesDir; - if (!onlyApp) { - baseLayerFilesDir = compatibleFilePath(baseID); - if (baseLayerFilesDir.empty()) { - std::cerr << "couldn't get compatiblePath of base" << std::endl; + if (begin + len > runtimeStr.size()) { + std::cerr << "runtime may not valid: " << runtimeStr << std::endl; return -1; } - annotations["org.deepin.linglong.baseDir"] = - std::filesystem::path{ baseLayerFilesDir }.parent_path(); + runtimeID = runtimeStr.substr(begin, len); } - std::string runtimeLayerFilesDir; + std::filesystem::path runtimeLayerFilesDir; if (!runtimeID.empty()) { runtimeLayerFilesDir = compatibleFilePath(runtimeID); if (runtimeLayerFilesDir.empty()) { @@ -488,8 +428,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT return -1; } - annotations["org.deepin.linglong.runtimeDir"] = - std::filesystem::path{ runtimeLayerFilesDir }.parent_path(); + builder.setRuntimePath(runtimeLayerFilesDir); } auto appLayerFilesDir = compatibleFilePath(appID); @@ -497,52 +436,50 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT std::cerr << "couldn't get compatiblePath of application" << std::endl; return -1; } - auto appDir = std::filesystem::path{ appLayerFilesDir }.parent_path(); - - annotations["org.deepin.linglong.appDir"] = appDir.string(); - annotations["org.deepin.linglong.bundleDir"] = containerBundle.string(); - config.annotations = std::move(annotations); - - if (!prepareRootfs(baseLayerFilesDir, config)) { - std::cerr << "couldn't prepare rootfs" << std::endl; - return -1; - } - - // replace commands - if (!appInfo->command || appInfo->command->empty()) { - std::cerr << "couldn't find command of application" << std::endl; - return -1; - } - config.process->args = appInfo->command.value(); - - applyPatches(config); - - auto env = config.process->env.value_or(std::vector{}); - std::string curPath = ::getenv("PATH"); - auto appBin = std::string{ "/opt/apps/" + appID + "/files/bin:" }; - curPath.insert(curPath.begin(), appBin.begin(), appBin.end()); - env.push_back("PATH=" + curPath); - config.process->env = std::move(env); + builder.setAppPath(appLayerFilesDir); // generate ld.so.cache and font cache at runtime - if (!processCaches(config, extraDir, onlyApp)) { + if (!processLDConfig(builder, appInfo->arch[0])) { + std::cerr << "failed to processing ld config" << std::endl; return -1; } // dump to bundle auto bundleCfg = containerBundle / "config.json"; - std::ofstream cfgStream{ bundleCfg.string() }; - if (!cfgStream.is_open()) { - std::cerr << "couldn't create bundle config.json" << std::endl; - return -1; - } + nlohmann::json json; + { + std::ofstream cfgStream{ bundleCfg.string() }; + if (!cfgStream.is_open()) { + std::cerr << "couldn't create bundle config.json" << std::endl; + return -1; + } + + if (!builder.build()) { + std::cerr << "failed to generate OCI config:" << builder.getError().reason << std::endl; + return -1; + } + + // for only-App, we need adjust some config + json = builder.getConfig(); + auto process = json["process"].get(); + process.terminal = (::isatty(STDOUT_FILENO) == 1); + process.user = ocppi::runtime::config::types::User{ .gid = getgid(), .uid = getuid() }; + process.args = appInfo->command.value_or(std::vector{ "bash" }); + json["process"] = std::move(process); + + auto linux_ = json["linux"].get(); + linux_.namespaces = std::vector{ + { .type = ocppi::runtime::config::types::NamespaceType::User }, + { .type = ocppi::runtime::config::types::NamespaceType::Mount } + }; + json["linux"] = std::move(linux_); - nlohmann::json json = config; - cfgStream << json.dump() << std::endl; - cfgStream.close(); + cfgStream << json.dump() << std::endl; + cfgStream.close(); + } if (::getenv("LINGLONG_UAB_DEBUG") != nullptr) { - std::cout << "dump container:" << std::endl; + std::cout << "dump container config:" << std::endl; std::cout << json.dump(4) << std::endl; } @@ -554,6 +491,8 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT } if (pid == 0) { + std::cout << "run container" << boxBin.string() << " " << bundleArg << " " << containerID + << std::endl; return ::execl(boxBin.c_str(), boxBin.c_str(), "--cgroup-manager=disabled", @@ -564,11 +503,22 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT nullptr); } - int wstatus{ -1 }; + int wstatus{ 0 }; if (auto ret = ::waitpid(pid, &wstatus, 0); ret == -1) { std::cerr << "waitpid() err:" << ::strerror(errno) << std::endl; return -1; } - return WEXITSTATUS(wstatus); + if (WIFEXITED(wstatus)) { + std::cerr << "loader: container exit: " << WEXITSTATUS(wstatus) << std::endl; + return WEXITSTATUS(wstatus); + } + + if (WIFSIGNALED(wstatus)) { + std::cerr << "loader: container exit with signal: " << WTERMSIG(wstatus) << std::endl; + return WTERMSIG(wstatus) + 128; + } + + std::cerr << "unknow exit status" << std::endl; + return -1; } diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 12cc1a5e7..9b3f7088f 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -12,7 +12,6 @@ #include "linglong/utils/command/env.h" #include "linglong/utils/error/error.h" #include "linglong/utils/file.h" -#include "linglong/utils/serialize/json.h" #include #include @@ -27,7 +26,7 @@ #include #include -#include +#include #include namespace linglong::package { @@ -294,6 +293,100 @@ utils::error::Result UABPackager::packIcon() noexcept return LINGLONG_OK; } +utils::error::Result> +prepareSymlink(const std::filesystem::path &sourceRoot, + const std::filesystem::path &destinationRoot, + const std::filesystem::path &fileName, + long maxDepth) noexcept +{ + LINGLONG_TRACE("prepare symlink") + + auto source = sourceRoot / fileName; + auto destination = destinationRoot / fileName; + + std::error_code ec; + while (maxDepth >= 0) { + auto status = std::filesystem::symlink_status(source, ec); + if (ec) { + if (ec == std::errc::no_such_file_or_directory) { + break; + } + + return LINGLONG_ERR( + QString{ "symlink_status error:%1" }.arg(QString::fromStdString(ec.message()))); + } + + if (status.type() != std::filesystem::file_type::symlink) { + break; + } + + auto target = std::filesystem::read_symlink(source, ec); + if (ec) { + return LINGLONG_ERR( + QString{ "read_symlink error:%1" }.arg(QString::fromStdString(ec.message()))); + } + + // ensure parent directory of destination + if (!std::filesystem::create_directories(destination.parent_path(), ec) && ec) { + return LINGLONG_ERR( + "couldn't create directories " + % QString::fromStdString(destination.parent_path().string() + ":" + ec.message())); + } + + std::filesystem::create_symlink(target, destination, ec); + while (ec) { + if (ec != std::errc::file_exists) { + return LINGLONG_ERR( + QString{ "create_symlink error:%1" }.arg(QString::fromStdString(ec.message()))); + } + + // check symlink target is the same as the original target + auto status = std::filesystem::symlink_status(destination, ec); + if (ec) { + return LINGLONG_ERR( + QString{ "symlink_status %1 error: %2" }.arg(destination.string().c_str(), + ec.message().c_str())); + } + + // destination already exists and is not a symlink + if (status.type() != std::filesystem::file_type::symlink) { + break; + } + + auto curTarget = std::filesystem::read_symlink(destination, ec); + if (ec) { + return LINGLONG_ERR( + QString{ "read_symlink %1 error: %2" }.arg(destination.string().c_str(), + ec.message().c_str())); + } + + if (curTarget != target) { + return LINGLONG_ERR( + QString{ "symlink target is not the same as the original target" } + % "original target: " % QString::fromStdString(target.string()) + % "current target: " % QString::fromStdString(curTarget.string())); + } + + break; + } + + if (target.is_absolute()) { + source = target; + break; + } + + source = (source.parent_path() / target).lexically_normal(); + destination = (destination.parent_path() / target).lexically_normal(); + --maxDepth; + } + + if (maxDepth < 0) { + return LINGLONG_ERR(QString{ "resolve symlink %1 too deep" }.arg(source.string())); + } + + return std::make_pair(std::move(source), std::move(destination)); +} + utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, bool onlyApp) noexcept { LINGLONG_TRACE("prepare layers for make a bundle") @@ -315,7 +408,9 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo base = *it; it = this->layers.erase(it); continue; - } else if (info.kind == "runtime") { + } + + if (info.kind == "runtime") { // if use custom loader, only app layer will be exported if (!this->loader.isEmpty()) { it = this->layers.erase(it); @@ -398,82 +493,91 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo QString::fromStdString(ec.message()))); } + auto symlinkCount = sysconf(_SC_SYMLOOP_MAX); + if (symlinkCount < 0) { + symlinkCount = 40; + } + if (!files.empty()) { - struct stat moduleFilesDirStat{}; - struct stat filesStat{}; + struct statvfs moduleFilesDirStat{}; + struct statvfs filesStat{}; - if (stat(moduleFilesDir.c_str(), &moduleFilesDirStat) == -1) { + if (statvfs(moduleFilesDir.c_str(), &moduleFilesDirStat) == -1) { return LINGLONG_ERR("couldn't stat module files directory: " + QString::fromStdString(moduleFilesDir)); } - if (stat((*files.begin()).c_str(), &filesStat) == -1) { + if (statvfs((*files.begin()).c_str(), &filesStat) == -1) { return LINGLONG_ERR("couldn't stat files directory: " + QString::fromStdString(layer.filesDirPath().toStdString())); } - const bool shouldCopy = moduleFilesDirStat.st_dev != filesStat.st_dev; + const bool shouldCopy = moduleFilesDirStat.f_fsid != filesStat.f_fsid; + for (std::filesystem::path source : files) { + auto sourceFile = source.lexically_relative(basePath); + auto ret = prepareSymlink(basePath, moduleFilesDir, sourceFile, symlinkCount); + if (!ret) { + return LINGLONG_ERR(ret); + } - for (const auto &source : files) { - auto destination = - moduleFilesDir / std::filesystem::path{ source }.lexically_relative(basePath); + const auto &[realSource, realDestination] = *ret; + auto status = std::filesystem::symlink_status(realSource, ec); + if (ec) { + // if the source file is a broken symlink, just skip it + if (ec == std::errc::no_such_file_or_directory) { + continue; + } - // Ensure that the parent directory exists - if (!std::filesystem::create_directories(destination.parent_path(), ec) && ec) { - return LINGLONG_ERR("couldn't create directories " - % QString::fromStdString(destination.parent_path().string() - + ":" + ec.message())); + return LINGLONG_ERR(QString{ "symlink_status error:%1" }.arg( + QString::fromStdString(ec.message()))); } - if (std::filesystem::is_symlink(source, ec)) { - std::filesystem::copy_symlink(source, destination, ec); + if (std::filesystem::is_directory(realSource)) { + std::filesystem::create_directories(realDestination, ec); if (ec) { - return LINGLONG_ERR("couldn't copy symlink from " - % QString::fromStdString(source) % " to " - % QString::fromStdString(destination.string()) % " " - % QString::fromStdString(ec.message())); + return LINGLONG_ERR(QString{ "create_directories error:%1" }.arg( + QString::fromStdString(ec.message()))); } + } + // check destination exists or not + // 1. multiple symlinks point to the same file + // 2. the destination also is a symlink + status = std::filesystem::symlink_status(realDestination, ec); + if (!ec) { + // no need to check the destination symlink point to which file, just skip it continue; } - if (ec) { - return LINGLONG_ERR( - QString{ "is_symlink error:%1" }.arg(QString::fromStdString(ec.message()))); - } - - if (std::filesystem::is_directory(source, ec)) { - if (!std::filesystem::create_directories(destination, ec) && ec) { - return LINGLONG_ERR( - QString{ "couldn't create directory: %1, error: %2" }.arg( - QString::fromStdString(destination.string()), - QString::fromStdString(ec.message()))); - } - continue; + if (ec && ec != std::errc::no_such_file_or_directory) { + return LINGLONG_ERR(QString{ "get symlink status of %1 failed: %2" }.arg( + QString::fromStdString(realDestination.string()), + QString::fromStdString(ec.message()))); } - if (ec) { + + if (!std::filesystem::create_directories(realDestination.parent_path(), ec) && ec) { return LINGLONG_ERR( - QString{ "is_directory error:%1" }.arg(QString::fromStdString(ec.message()))); + "couldn't create directories " + % QString::fromStdString(realDestination.parent_path().string() + ":" + + ec.message())); } if (shouldCopy) { - std::filesystem::copy(source, - destination, - std::filesystem::copy_options::overwrite_existing, - ec); + std::filesystem::copy(realSource, realDestination, ec); if (ec) { return LINGLONG_ERR("couldn't copy from " % QString::fromStdString(source) - % " to " % QString::fromStdString(destination.string()) - % " " % QString::fromStdString(ec.message())); + % " to " + % QString::fromStdString(realDestination.string()) % " " + % QString::fromStdString(ec.message())); } continue; } - std::filesystem::create_hard_link(source, destination, ec); + std::filesystem::create_hard_link(realSource, realDestination, ec); if (ec) { - return LINGLONG_ERR("couldn't link from " % QString::fromStdString(source) - % " to " % QString::fromStdString(destination.string()) + return LINGLONG_ERR("couldn't link from " % QString::fromStdString(realSource) + % " to " % QString::fromStdString(realDestination.string()) % " " % QString::fromStdString(ec.message())); } } @@ -523,12 +627,14 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo QString{ "files directory %1 doesn't exist" }.arg(filesDir.absolutePath())); } - for (const auto &fileStr : this->neededFiles) { - std::filesystem::path file{ fileStr }; - std::filesystem::path source = - filesDir.absoluteFilePath(QString::fromStdString(file)).toStdString(); - auto destination = moduleFilesDir / file; + auto curArch = Architecture::currentCPUArchitecture(); + if (!curArch) { + return LINGLONG_ERR("couldn't get current architecture"); + } + const auto fakePrefix = + moduleFilesDir / "lib" / std::filesystem::path{ curArch->getTriplet().toStdString() }; + for (std::filesystem::path file : this->neededFiles) { auto fileName = file.filename().string(); auto it = std::find_if(this->blackList.begin(), this->blackList.end(), @@ -540,53 +646,36 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo continue; } - int resolveDepth{ 10 }; - while (resolveDepth > 0) { - // ensure parent directory exist. - auto parent = destination.parent_path(); - if (!std::filesystem::create_directories(parent, ec) && ec) { - return LINGLONG_ERR( - QString{ "failed to create parent path of destination file: %1" }.arg( - parent.c_str())); - } - - auto status = std::filesystem::symlink_status(source, ec); - if (ec) { - return LINGLONG_ERR("symlink_status error:" - + QString::fromStdString(ec.message())); - } - if (status.type() != std::filesystem::file_type::symlink) { - break; - } + auto ret = prepareSymlink(filesDir.absolutePath().toStdString(), + moduleFilesDir, + file, + symlinkCount); + if (!ret) { + return LINGLONG_ERR(ret); + } - auto target = std::filesystem::read_symlink(source, ec); + auto [source, destination] = std::move(ret).value(); + if (!std::filesystem::exists(source, ec)) { if (ec) { - return LINGLONG_ERR("read_symlink error:" - + QString::fromStdString(ec.message())); - } - - std::filesystem::create_symlink(target, destination, ec); - if (ec && ec != std::errc::file_exists) { - return LINGLONG_ERR("couldn't create symlink from " - % QString::fromStdString(source) % " to " - % QString::fromStdString(destination.string()) % " " - % QString::fromStdString(ec.message())); + return LINGLONG_ERR( + QString{ "couldn't check file %1 exists: %2" }.arg(source.string(), + ec.message().c_str())); } - if (target.is_relative()) { - target = std::filesystem::canonical(source.parent_path() / target) - .lexically_relative(filesDir.absolutePath().toStdString()); - } + // source file must exist, it must be a regular file + return LINGLONG_ERR(QString{ "file %1 doesn't exist" }.arg(source.string())); + } - source = - filesDir.absoluteFilePath(QString::fromStdString(target)).toStdString(); - destination = moduleFilesDir / target; - --resolveDepth; + auto relative = destination.lexically_relative(fakePrefix); + if (relative.empty() || relative.string().rfind("..", 0) == 0) { + // override the destination file + destination = fakePrefix / source.filename(); } - if (resolveDepth == 0) { - return LINGLONG_ERR( - QString{ "resolve symlink %1 too deep" }.arg(source.c_str())); + if (!std::filesystem::create_directories(destination.parent_path(), ec) && ec) { + return LINGLONG_ERR("couldn't create directories " + % QString::fromStdString(destination.parent_path().string() + + ":" + ec.message())); } std::filesystem::copy(source, @@ -655,30 +744,6 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo return LINGLONG_ERR(QString{ "couldn't create directory %1" }.arg(extraDir.absolutePath())); } - // generate ld configs - auto arch = Architecture::currentCPUArchitecture(); - auto ldConfsDir = QDir{ extraDir.absoluteFilePath("ld.conf.d") }; - if (!ldConfsDir.mkpath(".")) { - return LINGLONG_ERR( - QString{ "couldn't create directory %1" }.arg(ldConfsDir.absolutePath())); - } - - auto ldConf = QFile{ ldConfsDir.absoluteFilePath("zz_deepin-linglong-app.ld.so.conf") }; - if (!ldConf.open(QIODevice::WriteOnly | QIODevice::Text)) { - return LINGLONG_ERR(ldConf); - } - - QTextStream stream{ &ldConf }; - stream << "/runtime/usr/lib/" << Qt::endl; // for only-app - stream << "/runtime/lib/" << Qt::endl; - stream << "/runtime/lib/" + arch->getTriplet() << Qt::endl; - stream << "/opt/apps/" + appID + "/files/lib" << Qt::endl; - stream << "/opt/apps/" + appID + "/files/lib/" + arch->getTriplet() << Qt::endl; - if (onlyApp) { - stream << "include /etc/ld.so.conf" << Qt::endl; - } - stream.flush(); - // copy ll-box auto boxBin = !defaultBox.isEmpty() ? defaultBox : QStandardPaths::findExecutable("ll-box"); if (boxBin.isEmpty()) { @@ -799,14 +864,19 @@ UABPackager::filteringFiles(const LayerDir &layer) const noexcept for (const auto &originalEntry : originalFiles) { auto entry = prefix / originalEntry.substr(1); - if (!std::filesystem::exists(entry, ec)) { + auto status = std::filesystem::symlink_status(entry, ec); + if (ec) { + return LINGLONG_ERR(QString::fromStdString(ec.message())); + } + + if (!std::filesystem::exists(status)) { if (ec) { return LINGLONG_ERR(QString::fromStdString(ec.message())); } continue; } - if (std::filesystem::is_regular_file(entry, ec)) { + if (status.type() == std::filesystem::file_type::regular) { expandFiles.insert(entry); continue; } @@ -814,13 +884,21 @@ UABPackager::filteringFiles(const LayerDir &layer) const noexcept return LINGLONG_ERR(QString::fromStdString(ec.message())); } - if (std::filesystem::is_directory(entry, ec)) { + if (status.type() == std::filesystem::file_type::directory) { auto iterator = std::filesystem::recursive_directory_iterator(entry, ec); if (ec) { return LINGLONG_ERR(QString::fromStdString(ec.message())); } for (const auto &file : iterator) { + if (file.is_directory(ec)) { + continue; + } + + if (ec) { + return LINGLONG_ERR(QString::fromStdString(ec.message())); + } + expandFiles.insert(file.path().string()); } } @@ -859,30 +937,37 @@ UABPackager::filteringFiles(const LayerDir &layer) const noexcept bool minified{ false }; std::unordered_set allFiles; - for (const std::filesystem::path &file : iterator) { - auto fileName = file.filename().string(); + for (const auto &file : iterator) { + // only process regular file and symlink + // relay on the short circuit evaluation, do not change the order of the conditions + if (!(file.is_symlink(ec) || file.is_regular_file(ec))) { + continue; + } + + if (ec) { + return LINGLONG_ERR( + QString{ "failed to check file %1 type: %2" }.arg(file.path().string(), + ec.message().c_str())); + } + + const auto &filePath = file.path(); + auto fileName = filePath.filename().string(); auto it = std::find_if(this->blackList.begin(), this->blackList.end(), [&fileName](const std::string &entry) { return entry.rfind(fileName, 0) == 0 || fileName.rfind(entry, 0) == 0; }); - auto status = std::filesystem::symlink_status(file, ec); - if (ec) { - return LINGLONG_ERR( - QString{ "failed to get file %1 status %2" }.arg(file.c_str(), ec.message().c_str())); - } - - if (it != this->blackList.end() && status.type() == std::filesystem::file_type::regular) { + if (it != this->blackList.end()) { continue; } - if (expandedExcludes.find(file) != expandedExcludes.cend()) { + if (expandedExcludes.find(filePath) != expandedExcludes.cend()) { minified = true; continue; } - allFiles.insert(file); + allFiles.insert(filePath); } // append all files from include From 62baa65f89789f75654f4f3a26f1ac4ae0e18f15 Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 10 Jun 2025 19:25:38 +0800 Subject: [PATCH 037/366] fix: add MIPS-specific compiler flag to avoid GOT overflow MIPS architecture and globally applies the `-mxgot` flag to compiler settings to address potential GOT overflow issues caused by the architecture's strict limitations on GOT size. --- CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb6c540a5..0e256dde1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,7 @@ set(LINGLONG_EXPORT_PATH if(NOT LINGLONG_EXPORT_PATH MATCHES ".*share$") message( WARNING - "LINGLONG_EXPORT_PATH '${LINGLONG_EXPORT_PATH}' must end with 'share'" - ) + "LINGLONG_EXPORT_PATH '${LINGLONG_EXPORT_PATH}' must end with 'share'") set(LINGLONG_EXPORT_PATH "share") endif() @@ -131,6 +130,17 @@ endif() set(linglong_EXTERNALS "ytj ytj::ytj") +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips" OR CMAKE_SYSTEM_PROCESSOR MATCHES + "^MIPS") + message( + STATUS + "MIPS architecture detected. Globally adding -mxgot to CMAKE_CXX_FLAGS.") + + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -mxgot" + CACHE STRING "C++ compiler flags" FORCE) +endif() + # NOTE: UOS v20 do not have tl-expected packaged. find_package(tl-expected 1.0.0 QUIET) if(NOT tl-expected_FOUND) From bab96b9d4e8e45e564b43e4036deda2def068a1a Mon Sep 17 00:00:00 2001 From: ComixHe Date: Wed, 11 Jun 2025 16:45:08 +0800 Subject: [PATCH 038/366] fix: building failed when using Qt5 Signed-off-by: ComixHe --- libs/linglong/src/linglong/package/uab_packager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 9b3f7088f..4a6636bbd 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -381,7 +381,7 @@ prepareSymlink(const std::filesystem::path &sourceRoot, } if (maxDepth < 0) { - return LINGLONG_ERR(QString{ "resolve symlink %1 too deep" }.arg(source.string())); + return LINGLONG_ERR(QString{ "resolve symlink %1 too deep" }.arg(source.c_str())); } return std::make_pair(std::move(source), std::move(destination)); @@ -658,12 +658,12 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo if (!std::filesystem::exists(source, ec)) { if (ec) { return LINGLONG_ERR( - QString{ "couldn't check file %1 exists: %2" }.arg(source.string(), + QString{ "couldn't check file %1 exists: %2" }.arg(source.c_str(), ec.message().c_str())); } // source file must exist, it must be a regular file - return LINGLONG_ERR(QString{ "file %1 doesn't exist" }.arg(source.string())); + return LINGLONG_ERR(QString{ "file %1 doesn't exist" }.arg(source.c_str())); } auto relative = destination.lexically_relative(fakePrefix); @@ -946,7 +946,7 @@ UABPackager::filteringFiles(const LayerDir &layer) const noexcept if (ec) { return LINGLONG_ERR( - QString{ "failed to check file %1 type: %2" }.arg(file.path().string(), + QString{ "failed to check file %1 type: %2" }.arg(file.path().c_str(), ec.message().c_str())); } From 355ea9d268e9eb77f2ec5ee14fa42da9539ff00c Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:36:41 +0800 Subject: [PATCH 039/366] [linyaps] Updates for project Linyaps (#1209) * i18n: Translate po/en_US.po in es 93% of minimum 50% translated source file: 'po/en_US.po' on 'es'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in ca 93% of minimum 50% translated source file: 'po/en_US.po' on 'ca'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pt_BR 93% of minimum 50% translated source file: 'po/en_US.po' on 'pt_BR'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in fi 93% of minimum 50% translated source file: 'po/en_US.po' on 'fi'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in en_GB 75% of minimum 50% translated source file: 'po/en_US.po' on 'en_GB'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in sq 77% of minimum 50% translated source file: 'po/en_US.po' on 'sq'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 93% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in uk 93% of minimum 50% translated source file: 'po/en_US.po' on 'uk'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 93% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in ca 98% of minimum 50% translated source file: 'po/en_US.po' on 'ca'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in ca 100% translated source file: 'po/en_US.po' on 'ca'. * i18n: Translate po/en_US.po in fi 95% of minimum 50% translated source file: 'po/en_US.po' on 'fi'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in fi 97% of minimum 50% translated source file: 'po/en_US.po' on 'fi'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in fi 98% of minimum 50% translated source file: 'po/en_US.po' on 'fi'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in fi 100% translated source file: 'po/en_US.po' on 'fi'. * i18n: Translate po/en_US.po in zh_CN 94% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 94% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 95% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 97% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 99% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 100% translated source file: 'po/en_US.po' on 'zh_CN'. * i18n: Translate po/en_US.po in es 96% of minimum 50% translated source file: 'po/en_US.po' on 'es'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in es 98% of minimum 50% translated source file: 'po/en_US.po' on 'es'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in es 100% translated source file: 'po/en_US.po' on 'es'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- po/ca.po | 485 ++++++++++++++++++++++++++------------------------ po/en_GB.po | 474 +++++++++++++++++++++++++------------------------ po/es.po | 501 ++++++++++++++++++++++++++++------------------------ po/fi.po | 486 ++++++++++++++++++++++++++------------------------ po/pl.po | 485 +++++++++++++++++++++++++------------------------- po/pt_BR.po | 485 +++++++++++++++++++++++++------------------------- po/sq.po | 471 ++++++++++++++++++++++++------------------------ po/uk.po | 484 +++++++++++++++++++++++++------------------------- po/zh_CN.po | 484 ++++++++++++++++++++++++++------------------------ 9 files changed, 2251 insertions(+), 2104 deletions(-) diff --git a/po/ca.po b/po/ca.po index eb51a66d2..6d266e0b4 100644 --- a/po/ca.po +++ b/po/ca.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Davidmp , 2025\n" "Language-Team: Catalan (https://app.transifex.com/linuxdeepin/teams/3976/ca/)\n" @@ -22,44 +22,48 @@ msgstr "" "Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Se n'ha denegat el permís. Comproveu si s'executa com a arrel." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Per instal·lar el mòdul, primer cal instal·lar l'aplicació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "El mòdul ja està instal·lat.." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Ha fallat la instal·lació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "No s'ha pogut trobar el mòdul remotament." + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Ha fallat la desinstal·lació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "Ha fallat l'actualització." -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "L'aplicació no està instal·lada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "La darrera versió ja està instal·lada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -69,7 +73,7 @@ msgstr "" "1. Comproveu la connexió a Internet.\n" "2. Verifiqueu la configuració del servidor intermediari de xarxa, si n'hi ha." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -77,15 +81,15 @@ msgstr "" "L'aplicació ja està instal·lada, si la voleu substituir, proveu d'usar \"ll-" "cli install %1 --force\"." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "L'aplicació %1 no es troba al repositori remot." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "No es pot especificar una versió en instal·lar un mòdul." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -93,14 +97,14 @@ msgstr "" "Se n'ha instal·lat la darrera versió. Si la voleu substituir, proveu d'usar " "'ll-cli install %1/version --force'." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "La generació de la memòria cau ha fallat, desinstal·leu i torneu a " "instal·lar l'aplicació." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -108,19 +112,19 @@ msgstr "" "CLI de linyaps\n" "Un programa de línia d'ordres per executar aplicacions i gestionar l'aplicació i el temps d'execució\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Imprimeix aquest missatge d'ajuda i surt." -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Expandeix tota l'ajuda." -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Ús: ll-cli [OPCIONS] [SUBORDRE]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -130,11 +134,11 @@ msgstr "" "https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Mostra'n la versió." -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -142,47 +146,47 @@ msgstr "" "Usa DBus d'igual a igual. Només s'usa en cas que el dimoni de DBus no " "estigui disponible." -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Usa el format json per generar el resultat." -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "El paràmetre d'entrada és buit; introduïu un paràmetre vàlid." -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Mostra la informació de depuració (registres detallats)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Gestió d'aplicacions instal·lades i entorns d'execució" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Gestió d'aplicacions en execució" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Trobar aplicacions i entorns d'execució" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Gestió de repositoris remots" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Executa una aplicació" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Especifiqueu l'ID de l'aplicació." -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -204,73 +208,73 @@ msgstr "" "ll-cli executa org.deepin.demo -- bash\n" "ll-cli executa org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "" "Passa el fitxer a les aplicacions que s'executen en un entorn de prova." -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Passa l'URL a les aplicacions que s'executen en un entorn de prova." -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Executa ordres en un entorn de prova en execució." #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Llista les aplicacions en execució." -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Ús: ll-cli ps [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Executa les ordres a l'entorn de prova que s'executa actualment." -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Especifiqueu la instància de l'aplicació que s'executa (la podeu obtenir " "mitjançant l'ordre ps)." -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Especifiqueu el directori de treball" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Introduïu l'espai de noms on s'executa l'aplicació." -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Ús: ll-cli enter [OPCIONS] INSTÀNCIA [ORDRE...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Atura les aplicacions en execució." -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Ús: ll-cli kill [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Especifiqueu el senyal que voleu enviar a l'aplicació." -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Especifiqueu l'aplicació en execució." -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Instal·lació d'una aplicació o d'un entorn d'execució" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -306,57 +310,61 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Especifiqueu l'ID de l'aplicació. També pot ser un fitxer .uab o .layer." -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Instal·la un mòdul específic." -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "Instal·lació des d'un repositori específic" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Força la instal·lació de l'aplicació." -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Respon automàticament sí a totes les preguntes." -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Desinstal·la l'aplicació o els entorns d'execució." -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Ús: ll-cli uninstall [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Especifiqueu els ID de les aplicacions." -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Desinstal·la un mòdul específic." #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Elimina tots els mòduls no usats." -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Desinstal·la tots els mòduls." -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Actualitza l'aplicació o els entorns d'execució." -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Ús: ll-cli upgrade [OPCIONS] [APLICACIÓ]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" @@ -364,7 +372,7 @@ msgstr "" "Especifiqueu l'ID de l'aplicació. Si no s'especifica, s'actualitzaran totes " "les aplicacions." -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -372,61 +380,69 @@ msgstr "" "Cerca les aplicacions / entorns d'execució que contenen el text especificat " "del repositori remot." -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" "Ús: ll-cli search [OPCIONS] PARAULES CLAU\n" "\n" "Exemple:\n" -"# cerca l'aplicació de forma remota pel nom\n" +"# cerca remotament aplicacions, bases o temps d'execució per paraules clau\n" "ll-cli search org.deepin.demo\n" -"# cerca l'entorn d'execució de manera remota pel nom\n" +"# cerca remotament temps d'execució per nom\n" "ll-cli search org.deepin.base --type=runtime\n" -"# cerca tota aplicació fora del remot\n" +"# cerca totes les aplicacions de la ubicació remota\n" "ll-cli search .\n" -"# cerca tot entorn d'execució fora del remot\n" +"# cerca totes les bases de la ubicació remota\n" +"ll-cli search . --type=base\n" +"# cerca tots els temps d'execució de la ubicació remota\n" "ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Especifiqueu les paraules clau." -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" -"Filtreu el resultat amb el tipus especificat: \"entorn d'execució\", " -"\"aplicació\" o \"tots\"." +"Filtra el resultat amb el tipus especificat: \"runtime\", \"base\", \"app\" " +"o \"all\"." -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "inclou aplicacions de desenvolupament al resultat" +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "Especifiqueu el repositori" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Mostra tots els resultats." +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "Inclou l'aplicació de desenvolupament al resultat." -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Llista les aplicacions o els entorns d'execució instal·lats." +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "Mostra totes les versions d'una aplicació, base o temps d'execució." -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "Llista les aplicacions, bases o temps d'execució instal·lats." + +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" @@ -435,239 +451,255 @@ msgstr "" "Ús: ll-cli list [OPCIONS]\n" "\n" "Exemple:\n" -"# mostra les aplicacions instal·lades\n" +"# mostra les aplicacions, bases o temps d'execució instal·lats\n" "ll-cli list\n" -"# mostra els entorns d'execució instal·lats\n" +"# mostra les bases instal·lades\n" +"ll-cli list --type=base\n" +"# mostra els temps d'execució instal·lats\n" "ll-cli list --type=runtime\n" "# mostra la llista de versions més recents de les aplicacions instal·lades actualment\n" "ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Mostra la llista de la darrera versió de les aplicacions instal·lades " -"actualment, només funciona per a l'aplicació" +"Mostra la llista de les darreres versions de les aplicacions, bases o temps " +"d'execució instal·lats actualment." -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Mostra o modifica la informació del repositori que s'usa actualment." -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Ús: ll-cli repo SUBORDRE [OPCIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Afegeix un repositori nou." -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Ús: ll-cli repo add [OPCIONS] NOM DE L'URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Especifiqueu el nom del repositori." -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "URL del repositori" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Àlies del nom del repositori" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Modifica l'URL del repositori" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Elimina un repositori" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Ús: ll-cli repo remove [OPCIONS] NOM" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Actualitza l'URL del repositori." -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Ús: ll-cli repo update [OPCIONS] NOM D'URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Estableix un nom de repositori per defecte." -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Ús: ll-cli repo set-default [OPCIONS] NOM" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Mostra la informació del repositori." -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Ús: ll-cli repo show [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Estableix la prioritat del repositori." -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Ús: ll-cli repo set-priority PRIORITAT DE L'ÀLIES" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Prioritat del repositori" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "" "Mostra informació sobre aplicacions instal·lades o entorns d'execució." -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Ús: ll-cli info [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Especifiqueu l'ID de l'aplicació. També pot ser un fitxer .layer." -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Mostra els fitxers exportats de l'aplicació instal·lada." -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Ús: ll-cli content [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Especifiqueu l'ID de l'aplicació instal·lada." #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Elimina la base o l'entorn d'execució no usat." -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Ús: ll-cli prune [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Mostra la informació de l'aplicació instal·lada." -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Ús: ll-cli inspect [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Especifiqueu l'identificador del procés." -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Identificador de procés no vàlid" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Format pid no vàlid" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Especifiqueu l'aplicació instal·lada (base o entorn d'execució)." -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "Versió CLI de linyaps" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Nom" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "versió" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Canal" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Mòdul" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Descripció" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "No s'han trobat paquets al repositori remot." + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "Repositori" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "No hi ha contenidors en execució." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Aplicació" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ID del contenidor" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "PID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "URL" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Àlies" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Prioritat" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "No hi ha cap aplicació disponible per actualitzar." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Instal·lada" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Nova" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -675,11 +707,11 @@ msgstr "" "CLI del constructor de linyaps \n" "Un programa CLI per crear una aplicació de linyaps.\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Ús: ll-builder [OPCIONS] [SUBORDRE]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -688,42 +720,38 @@ msgstr "" "podeu informar d'errors a l'equip de linyaps en aquest projecte: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Crea un projecte de plantilla de compilació de linyaps." -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Ús: ll-builder create [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Nom del projecte" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Construeix un projecte de linyaps." -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Ús: ll-builder build [OPCIONS] [ORDRE...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Camí del fitxer linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Estableix l'arc de construcció." - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Entreu al contenidor per executar l'ordre en lloc de construir aplicacions." -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -731,198 +759,197 @@ msgstr "" "Usa només fitxers locals. Això implica que s'establiran --skip-fetch-source " "i --skip-pull-depend." -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Crea paquets de desenvolupament complets, cal entorn d'execució." -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Omet fonts d'obtenció." -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Omet la dependència de l'ordre pull." -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Omet el contenidor d'execució." -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Omet la sortida d'enviament de la compilació." -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Omet la comprovació de sortida." -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Omet els símbols de depuració." -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Construeix en un entorn de xarxa aïllat." -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Executa l'aplicació de linyaps creada." -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Ús: ll-builder run [OPCIONS] [ORDRE..]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Usa només fitxers locals." - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Executa el mòdul especificat. Ex.: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" "Entreu al contenidor per executar l'ordre en lloc d'executar l'aplicació." -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Executa en mode de depuració (activa el mòdul de desenvolupament)." -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Llista les aplicacions de linyaps creades." -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Ús: ll-builder list [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Elimina l'aplicació de linyaps creada." -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Ús: ll-builder remove [OPCIONS] [APLICACIÓ...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Exporta a la capa linyaps o uab." -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Ús: ll-builder export [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Icona d'uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Exporta uab completament." -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Exporta al fitxer de capa linyaps." +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "Exporta a un fitxer de capa de Linyaps (obsolet)" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Usa un carregador personalitzat." -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "No exportis el mòdul de desenvolupament." -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Fitxer de sortida" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Envieu l'aplicació linyaps al repositori remot." -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Ús: ll-builder push [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "URL del repositori remot" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Nom del repositori remot" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Envia un mòdul únic." -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Importa la capa de linyaps al repositori de construcció." -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Ús: ll-builder import [OPCIONS] CAPA" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Camí del fitxer de la capa" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "" "Importa el directori de la capa de linyaps al repositori de construcció." -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Camí del directori de la capa" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Extreu la capa de linyaps al directori." -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Ús: ll-builder extract [OPCIONS] DIRECTORI DE CAPES" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Directori de destinació" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Mostra i gestiona els repositoris." -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Ús: ll-builder repo [OPCIONS] SUBORDRES" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Ús: ll-builder repo add [OPCIONS] NOM D'URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Ús: ll-builder repo remove [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Ús: ll-builder repo update [OPCIONS] NOM D'URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Ús: ll-builder repo set-default [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Ús: ll-builder repo show [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "Versió de l'eina de construcció de linyaps" diff --git a/po/en_GB.po b/po/en_GB.po index 30ee69990..df49a2490 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Gary Wang , 2025\n" "Language-Team: English (United Kingdom) (https://app.transifex.com/linuxdeepin/teams/3976/en_GB/)\n" @@ -21,77 +21,81 @@ msgstr "" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "The cache generation failed, please uninstall and reinstall the application." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -99,19 +103,19 @@ msgstr "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Print this help message and exit" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Expand all help" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -120,11 +124,11 @@ msgstr "" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Show version" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -132,47 +136,47 @@ msgstr "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Use json format to output result" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Input parameter is empty, please input valid parameter instead" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Managing installed applications and runtimes" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Managing running applications" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Finding applications and runtimes" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Managing remote repositories" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Run an application" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Specify the application ID" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -194,71 +198,71 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Pass file to applications running in a sandbox" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Pass url to applications running in a sandbox" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Run commands in a running sandbox" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "List running applications" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Usage: ll-cli ps [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Execute commands in the currently running sandbox" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Specify the application running instance(you can get it by ps command)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Specify working directory" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Enter the namespace where the application is running" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Stop running applications" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Usage: ll-cli kill [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Specify the signal to send to the application" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Specify the running application" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Installing an application or runtime" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -294,62 +298,66 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "Specify the application ID, and it can also be a .uab or .layer file" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Install a specify module" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Force install the application" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Automatically answer yes to all questions" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Uninstall the application or runtimes" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Usage: ll-cli uninstall [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Specify the applications ID" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Uninstall a specify module" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Upgrade the application or runtimes" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Usage: ll-cli upgrade [OPTIONS] [APP]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" msgstr "" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -357,288 +365,297 @@ msgstr "" "Search the applications/runtimes containing the specified text from the " "remote repository" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Specify the Keywords" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "include develop application in result" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Show all results" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "List installed applications or runtimes" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -"Usage: ll-cli list [OPTIONS]\n" -"\n" -"Example:\n" -"# show installed application(s)\n" -"ll-cli list\n" -"# show installed runtime(s)\n" -"ll-cli list --type=runtime\n" -"# show the latest version list of the currently installed application(s)\n" -"ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Display or modify information of the repository currently using" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Add a new repository" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo add [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Specify the repo name" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "Url of the repository" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias of the repo name" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Modify repository URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Remove a repository" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Usage: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Update the repository URL" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Set a default repository name" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Usage: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Show repository information" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Usage: ll-cli repo show [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Display information about installed apps or runtimes" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Usage: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specify the application ID, and it can also be a .layer file" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Display the exported files of installed application" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Usage: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Specify the installed application ID" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Remove the unused base or runtime" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Usage: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Display the information of installed application" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Usage: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Specify the process id" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "linyaps CLI version " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Name" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "Version" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Channel" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Module" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Description" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "App" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ContainerID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "Pid" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Installed" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "New" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -646,11 +663,11 @@ msgstr "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -658,42 +675,38 @@ msgstr "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Create linyaps build template project" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Usage: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Project name" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Build a linyaps project" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "File path of the linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Set the build arch" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Enter the container to execute command instead of building applications" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -701,196 +714,195 @@ msgstr "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Build full develop packages, runtime requires" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Skip fetch sources" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Skip pull dependency" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Skip run container" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Skip commit build output" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Skip output check" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Skip strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Only use local files" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Run specified module. eg: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "Enter the container to execute command instead of running application" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Run in debug mode (enable develop module)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Usage: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Usage: ll-builder remove [OPTIONS] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Export to linyaps layer or uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Usage: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Uab icon (optional)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Export uab fully" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Export to linyaps layer file" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Push linyaps app to remote repo" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Usage: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "Remote repo url" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Remote repo name" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Push single module" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Import linyaps layer to build repo" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Usage: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Layer file path" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Import linyaps layer dir to build repo" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Layer dir path" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Extract linyaps layer to dir" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Usage: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Destination directory" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Display and manage repositories" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Usage: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Usage: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Usage: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "linyaps build tool version " diff --git a/po/es.po b/po/es.po index db0396b63..0a00451f2 100644 --- a/po/es.po +++ b/po/es.po @@ -5,17 +5,17 @@ # # Translators: # Gary Wang , 2025 -# Zaraza, 2025 # Isaías Gätjens M , 2025 +# Zaraza, 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" -"Last-Translator: Isaías Gätjens M , 2025\n" +"Last-Translator: Zaraza, 2025\n" "Language-Team: Spanish (https://app.transifex.com/linuxdeepin/teams/3976/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,44 +23,48 @@ msgstr "" "Language: es\n" "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Permiso denegado, verifique si está ejecutando como root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Para instalar el módulo, primero debe instalar la aplicación." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "El módulo ya está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "La instalación falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "No se pudo encontrar el módulo de forma remota." + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "La desinstalación falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "La actualización falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "La aplicación no está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "La última versión ya está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -70,7 +74,7 @@ msgstr "" "1. Verifique su conexión a internet.\n" "2. Verifique la configuración del proxy de red, si lo utiliza." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -78,15 +82,15 @@ msgstr "" "Aplicación instalada, si desea reemplazarla intente usar 'll-cli install %1 " "--force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "La aplicación %1 no se encuentra en el repositorio remoto." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "No se puede especificar la versión al instalar un módulo" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -94,14 +98,14 @@ msgstr "" "Se ha instalado la última versión. Si desea reemplazarla, pruebe con «ll-cli" " install %1/version --force»." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "La generación de la caché falló, por favor desinstala y reinstala la " "aplicación." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -109,19 +113,19 @@ msgstr "" "linyaps CLI\n" "Un programa CLI para ejecutar aplicaciones y gestionar aplicaciones y entornos de ejecución\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Imprimir este mensaje de ayuda y salir" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Expandir toda la ayuda" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-cli [OPCIONES] [SUBCOMANDO]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -130,11 +134,11 @@ msgstr "" "puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Mostrar versión" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -142,48 +146,48 @@ msgstr "" "Usar DBus de igual a igual, esto solo se usa en caso de que el demonio de " "DBus no esté disponible" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Usar formato json para mostrar el resultado" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" "El parámetro de entrada está vacío, por favor ingrese un parámetro válido." -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Mostrar información de depuración (registros detallados)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Gestionar aplicaciones instaladas y tiempos de ejecución" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Gestionar aplicaciones en ejecución" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Buscar aplicaciones y tiempos de ejecución" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Gestionar repositorios remotos" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Ejecutar una aplicación" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Especificar el ID de la aplicación" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -205,74 +209,74 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "" "Pasar archivo a las aplicaciones que se ejecutan en un entorno aislado" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Pasar URL a las aplicaciones que se ejecutan en un entorno aislado" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Ejecutar comandos en un entorno aislado en ejecución" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Listar aplicaciones en ejecución" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Uso: ll-cli ps [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Ejecutar comandos en el entorno aislado actualmente en ejecución" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Especifique la instancia de la aplicación en ejecución (puede obtenerla con " "el comando ps)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Especificar la carpeta de trabajo" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "" "Entrar en el espacio de nombres donde se está ejecutando la aplicación" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Uso: ll-cli enter [OPCIONES] INSTANCE [COMANDO...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Detener aplicaciones en ejecución" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Uso: ll-cli kill [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Especificar el ID de la aplicación instalada" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Especifique la aplicación en ejecución" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Instalando una aplicación o tiempo de ejecución" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -308,58 +312,62 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Especificar el ID de la aplicación, también puede ser un archivo .uab o " ".layer" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Instalar un módulo especificado" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "Instalar desde un repositorio específico" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Forzar la instalación de la aplicación" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Responder automáticamente sí a todas las preguntas" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Desinstalar la aplicación o entornos de ejecución" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Uso: ll-cli uninstall [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Especificar el ID de las aplicaciones" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Desinstalar un módulo especificado" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Eliminar todos los módulos no utilizados" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Desinstalar todos los módulos" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Actualizar la aplicación o entornos de ejecución" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Uso: ll-cli upgrade [OPCIONES] [APP]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" @@ -367,7 +375,7 @@ msgstr "" "Especificar el ID de la aplicación. Si no se especifica, se actualizarán " "todas las aplicaciones" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -375,295 +383,329 @@ msgstr "" "Buscar las aplicaciones/entornos de ejecución que contengan el texto " "especificado desde el repositorio remoto" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -"Uso: ll-cli search [OPCIONES] PALABRAS CLAVEEjemplo:# buscar aplicación " -"remota por nombrell-cli search org.deepin.demo# buscar tiempo de ejecución " -"remota por nombrell-cli search org.deepin.base --type=runtime# buscar todas " -"las aplicaciones del control remotoll-cli search .# buscar todo el tiempo de" -" ejecución del control remotoll-cli search . --type=runtime" +"Uso: ll-cli search [OPCIONES] PALABRAS CLAVE\n" +"\n" +"Ejemplo:\n" +"# Buscar aplicaciones, bases o entornos de ejecución de forma remota por palabras clave\n" +"ll-cli search org.deepin.demo\n" +"# Buscar entornos de ejecución de forma remota por nombre\n" +"ll-cli search org.deepin.base --type=runtime\n" +"# Buscar todas las aplicaciones del sistema remoto\n" +"ll-cli search .\n" +"# Buscar todas las bases del sistema remoto\n" +"ll-cli search . --type=base\n" +"# Buscar todos los entornos de ejecución del sistema remoto\n" +"ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Especificar las Palabras Clave" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "Filtrar resultado con tipo especificado. Uno de \"runtime\", \"app\" o \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "" +"Filtrar resultados especificando el tipo: \"tiempo de ejecución\", \"base\"," +" \"aplicación\" o \"todos\"." + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "Especificar el repositorio" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" msgstr "incluir aplicación en desarrollo en el resultado" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Mostrar todos los resultados" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" +"Mostrar todas las versiones de una(s) aplicaciónes, bases o entornos de " +"ejecución" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Listar aplicaciones o entornos de ejecución instalados" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" +"Listar las aplicaciones instaladas, las bases o los entornos de ejecución" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" "Uso: ll-cli list [OPCIONES]\n" -"\n" "Ejemplo:\n" -"# mostrar aplicación(es) instalada(s)\n" +"# Mostrar las aplicaciones, bases o entornos de ejecución instalados\n" "ll-cli list\n" -"# mostrar entorno(s) de ejecución instalado(s)\n" +"# Mostrar las bases instaladas\n" +"ll-cli list --type=base\n" +"# Mostrar los entornos de ejecución instalados\n" "ll-cli list --type=runtime\n" -"# mostrar la lista de la última versión de las aplicaciones actualmente instaladas\n" +"# Mostrar la lista de las últimas versiones de las aplicaciones instaladas\n" "ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Mostrar la lista de la última versión de las aplicaciones actualmente " -"instaladas, solo funciona para aplicaciones" +"Mostrar la lista de las últimas versiones de las aplicaciones, bases o " +"tiempos de ejecución instalados actualmente" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Mostrar o modificar la información del repositorio actualmente en uso" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Uso: ll-cli repo SUBCOMANDO [OPCIONES]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Añadir un nuevo repositorio" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo add [OPCIONES] NOMBRE URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Especificar el nombre del repositorio" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "URL del repositorio" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Especificar el nombre del repositorio" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Modificar la URL del repositorio" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Eliminar un repositorio" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Uso: ll-cli repo remove [OPCIONES] NOMBRE" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Actualizar la URL del repositorio" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo update [OPCIONES] NOMBRE URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Establecer un nombre de repositorio predeterminado" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Uso: ll-cli repo set-default [OPCIONES] NOMBRE" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Mostrar información del repositorio" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Uso: ll-cli repo show [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Establecer prioridad del repositorio" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Usage: ll-cli repo set-priority ALIAS PRIORITY" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Prioridad del repositorio" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "" "Mostrar información sobre aplicaciones o entornos de ejecución instalados" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Uso: ll-cli info [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "" "Especificar el ID de la aplicación, también puede ser un archivo .layer" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Mostrar los archivos exportados de la aplicación instalada" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Uso: ll-cli content [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Especificar el ID de la aplicación instalada" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Eliminar la base o el entorno de ejecución no utilizado" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Uso: ll-cli prune [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Mostrar la información de la aplicación instalada." -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Uso: ll-cli inspect [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Especifica el ID del proceso" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "ID de proceso no válido" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Formato de PID no válido" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Especifique la aplicación instalada (base o tiempo de ejecución)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "versión de linyaps CLI " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Nombre" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "Versión" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Canal" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Módulo" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Descripción" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "No se encontraron paquetes en el repositorio remoto." + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "Repo" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "No hay ningún contenedor en ejecución." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "App" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ContainerID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "Pid" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "Url" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Prioridad" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "No hay aplicaciones para actualizar." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Instalado" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Nuevo" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -671,11 +713,11 @@ msgstr "" "linyaps builder CLI \n" "Un programa CLI para construir aplicaciones linyaps\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-builder [OPCIONES] [SUBCOMANDO]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -683,43 +725,39 @@ msgstr "" "Si encuentras algún problema durante el uso\n" "Puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Crear proyecto de plantilla de compilación de linyaps" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Uso: ll-builder create [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Nombre del proyecto" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Construir un proyecto de linyaps" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder build [OPCIONES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Ruta del archivo de linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Establecer la arquitectura de construcción" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Entrar en el contenedor para ejecutar comandos en lugar de construir " "aplicaciones" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -727,199 +765,198 @@ msgstr "" "Usar solo archivos locales. Esto implica que se configurarán --skip-fetch-" "source y --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "" "Construir paquetes de desarrollo completos, se requiere tiempo de ejecución" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Omitir la obtención de fuentes" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Omitir la dependencia de extracción" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Omitir la ejecución del contenedor" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Omitir la confirmación de la salida de la compilación" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Omitir la comprobación de la salida" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Omitir el despojo de los símbolos de depuración" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Construir en un entorno de red aislado" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Ejecutar la aplicación Linyaps creada" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder run [OPCIONES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Usar solo archivos locales" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Ejecutar módulo especificado. ej: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" "Entrar en el contenedor para ejecutar comandos en lugar de ejecutar la " "aplicación" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Ejecutar en modo depuración (habilitar módulo de desarrollo)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Lista de aplicaciones de Linyaps creadas" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Uso: ll-builder list [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Eliminar la aplicación Linyaps creada" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Uso: ll-builder remove [OPCIONES] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Exportar a la capa o uab de linyaps" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Uso: ll-builder export [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Icono de uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Exportar uab completamente" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Exportar al archivo de capa de linyaps" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "Exportar a archivo de capa linyaps (obsoleto)" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Utilice un cargador personalizado" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "No exportar el módulo de desarrollo" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Archivo de salida" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Enviar la aplicación linyaps al repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Uso: ll-builder push [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "URL del repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Nombre del repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Enviar módulo único" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Importar la capa de linyaps para construir el repositorio" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Uso: ll-builder import [OPCIONES] CAPA" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Ruta del archivo de la capa" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Importar carpeta de capa linyaps al repositorio de compilación" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Uso: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Ruta de la carpeta de capa" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Extraer la capa de linyaps a la carpeta" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Uso: ll-builder extract [OPCIONES] CAPA DIR" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Carpeta de destino" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Mostrar y gestionar repositorios" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Uso: ll-builder repo [OPCIONES] SUBCOMANDO" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo add [OPCIONES] NOMBRE URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Uso: ll-builder repo remove [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo update [OPCIONES] NOMBRE URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Uso: ll-builder repo set-default [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Uso: ll-builder repo show [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "versión de la herramienta de construcción de linyaps " diff --git a/po/fi.po b/po/fi.po index 92eff3747..8dce6baef 100644 --- a/po/fi.po +++ b/po/fi.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Kimmo Kujansuu , 2025\n" "Language-Team: Finnish (https://app.transifex.com/linuxdeepin/teams/3976/fi/)\n" @@ -21,44 +21,48 @@ msgstr "" "Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Lupa evätty. Tarkista oletko root-käyttäjänä." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Moduulin asentamiseksi on ensin asennettava sovellus." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "Moduuli on jo asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Asennus epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "Moduulia ei löytynyt palvelimelta." + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Poistaminen epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "Päivitys epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "Sovellusta ei ole asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "Uusin versio on jo asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -68,7 +72,7 @@ msgstr "" "1. Tarkista internetyhteys\n" "2. Tarkista välityspalvelimen asetukset, jos niitä käytetään" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -76,15 +80,15 @@ msgstr "" "Sovellus on jo asennettu. Jos haluat vaihtaa sen, kokeile \"ll-cli install " "%1 --force\"" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "Sovellusta %1 ei löydy palvelimelta." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "Moduulia asennettaessa ei voitu määrittää versiota." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -92,13 +96,13 @@ msgstr "" "Uusin versio on asennettu. Jos haluat vaihtaa sen, kokeile \"ll-cli install " "%1/version --force\"" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "Välimuistin luonti epäonnistui, poista sovellus ja asenna se uudelleen." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -106,19 +110,19 @@ msgstr "" "linyaps CLI\n" "Ohjelma sovellusten suorittamiseen ja ajoympäristön hallintaan\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Tulosta tämä ohje ja poistu" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Kaikki ohjeet" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Käyttö: ll-cli [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -127,11 +131,11 @@ msgstr "" "Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Näytä versio" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -139,47 +143,47 @@ msgstr "" "Käytä peer to peer DBus, tätä käytetään vain jos DBus-palvelua ei ole " "saatavilla" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Käytä json-formaattia tuloksiin" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Parametri on tyhjä, anna kelvollinen parametri" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Näytä virhesanomat (sanalliset lokit)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Sovellusten ja suoritusaikojen hallinta" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Käynnissä olevien sovellusten hallinta" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Sovellusten ja ajoympäristön etsiminen" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Arkistojen hallinta palvelimelta" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Suorita sovellus" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Määritä sovelluksen id-tunnus" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -201,70 +205,70 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Siirrä tiedosto kontissa toimiville sovelluksille" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Välitä verkko-osoite hiekkalaatikossa toimiville sovelluksille" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Suorita komennot käynnissä olevassa kontissa" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Luettelo käynnissä olevista sovelluksista" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Käyttö: ll-cli ps [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Suorita komennot käynnissä olevassa kontissa" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "Määritä käynnissä oleva sovellus (saat sen ps-komennolla)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Määritä työhakemisto" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Anna nimiavaruus, jossa sovellus on käynnissä" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Käyttö: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Lopeta sovelluksen käyttö" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Käyttö: ll-cli kill [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Määritä signaali, joka lähetetään sovellukselle" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Määritä käynnissä oleva sovellus" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Sovelluksen tai ajoympäristön asentaminen" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -300,57 +304,61 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Määritä sovelluksen id-tunnus. Voi olla myös .uab- tai .layer-tiedosto" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Asenna tietty moduuli" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "Asenna tietystä arkistosta" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Pakota sovelluksen asennus" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Vastaa kyllä ​​kaikkiin kysymyksiin" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Poista sovellus tai ajoympäristö" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Käyttö: ll-cli uninstall [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Määritä sovellusten id-tunnus" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Poista tietyn moduulin asennus" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Poista kaikki käyttämättömät moduulit" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Poista kaikki moduulit" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Päivitä sovellus tai ajoympäristö" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Käyttö: ll-cli upgrade [OPTIONS] [APP]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" @@ -358,7 +366,7 @@ msgstr "" "Määritä sovelluksen id-tunnus. Jos ei määritetä, kaikki sovellukset " "päivitetään" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -366,61 +374,70 @@ msgstr "" "Etsi palvelimen arkistosta tietyn tekstin sisältävät " "sovellukset/ajoympäristöt" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" "Käyttö: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Esimerkki:\n" -"# etsi sovellus palvelimelta nimen perusteella\n" +"# etsi palvelimelta sovellukse(t), alusta(t) tai ajoympäristö(t) hakusanoilla\n" "ll-cli search org.deepin.demo\n" -"# etsi ajoympäristö palvelimelta nimen perusteella\n" +"# etsi ajoympäristö palvelimelta nimellä\n" "ll-cli search org.deepin.base --type=runtime\n" -"# etsi kaikki palvelimen sovellukset\n" +"# etsi kaikki sovellukset palvelimelta\n" "ll-cli search .\n" -"# etsi kaikki palvelimen ajoympäristöt\n" +"# etsi alusta(t) palvelimelta\n" +"ll-cli search . --type=base\n" +"# etsi ajoympäristö(t) palvelimelta\n" "ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Määrittele hakusanat" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" -"Suodata tulos tietyllä tyypillä. Joku seuraavista: \"runtime\", \"app\" tai " -"\"all\"" +"Suodata tulokset tyypillä. Joku seuraavista: \"runtime\", \"base\", \"app\" " +"tai \"all\"" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "sisällyttää tulokseen kehitteillä olevan sovelluksen" +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "Määritä arkisto" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Näytä kaikki tulokset" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "Sisällytä tuloksiin kehitteillä olevat sovellukset" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Luettele asennetut sovellukset tai ajoympäristöt" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" +"Näytä kaikki versiot (sovelluksita), (alustoista) tai (ajoympäristöistä)" + +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "Luettele asennetut sovellukse(t), alusta(t) tai ajoympäristö(t)" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" @@ -429,238 +446,254 @@ msgstr "" "Käyttö: ll-cli list [OPTIONS]\n" "\n" "Esimerkki:\n" -"# näytä (asennetut) sovellukset\n" +"# näytä asennetut sovellukse(t), alusta(t) tai ajoympäristö(t)\n" "ll-cli list\n" -"# näytä (asennetut) ajoympäristöt\n" +"# näytä asennetut alusta(t)\n" +"ll-cli list --type=base\n" +"# näytä asennetut ajoympäristö(t)\n" "ll-cli list --type=runtime\n" "# näytä asennettujen sovellusten (uusin) versioluettelo\n" "ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Näytä luettelo asennettujen sovellusten uusimmista versioista. Toimii vain " -"sovelluksille" +"Näytä luettelo asennettujen uusimmista versioista. Sovellukse(t), alusta(t) " +"tai ajoympäristö(t)" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Näytä tai muokkaa käytössä olevan ohjelma-arkiston tietoja" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Käyttö: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Lisää uusi ohjelma-arkisto" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Käyttö: ll-cli repo add [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Määritä arkiston nimi" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "Arkiston verkko-osoite" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias arkiston nimelle" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Muokkaa arkiston verkko-osoitetta" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Poista ohjelma-arkisto" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Käyttö: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Päivitä arkiston verkko-osoite" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Käyttö: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Aseta oletusarkiston nimi" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Käyttö: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Näytä ohjelma-arkiston tiedot" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Käyttö: ll-cli repo show [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Aseta arkiston prioriteetti" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Käyttö: ll-cli repo set-priority ALIAS PRIORITY" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Arkiston prioriteetti" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Näytä tiedot sovelluksista tai ajoympäristöistä" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Käyttö: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Määritä sovelluksen id-tunnus. Voi olla myös .layer-tiedosto" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Näytä asennetun sovelluksen viedyt tiedostot" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Käyttö: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Määritä sovelluksen id-tunnus" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Poista käyttämätön alusta tai ajoympäristö" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Käyttö: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Näytä sovelluksen tiedot" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Käyttö: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Määritä prosessin id-tunnus" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Väärä prosessin id-tunnus" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Väärä pid formaatti" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Määritä asennettu sovellus (base tai runtime)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "linyaps CLI versio " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Nimi" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "versio" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Kanava" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Moduuli" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Kuvaus" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "Paketteja ei löytynyt palvelimen arkistosta." + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "Arkisto" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "Kontteja ei ole käynnissä." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Sovellus" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "Kontti-id" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "Pid" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "Osoite" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Prioriteetti" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "Päivitettäviä sovelluksia ei ole." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Asennettu" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Uusi" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -668,11 +701,11 @@ msgstr "" "linyaps builder CLI \n" "Ohjelma jolla linyaps-sovellukset käännetään\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Käyttö: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -680,42 +713,38 @@ msgstr "" "Jos havaitset ongelmia käytön aikana,\n" "Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Rakenna linyaps malliprojekti" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Käyttö: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Projektin nimi" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Rakenna linyaps projekti" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Käyttö: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Tiedoston linglong.yaml tiedostopolku" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Aseta build arch" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Kirjoita kontin nimi, suorittaaksesi komento sovelluksen rakentamisen sijaan" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -723,197 +752,196 @@ msgstr "" "Käytä vain paikallisia tiedostoja. Tarkoittaa, että --skip-fetch-source ja " "--skip-pull-depend asetetaan" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Rakenna kehityspaketteja kokonaan, ajoympäristö tarvitaan" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Ohita fetch sources" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Ohita pull dependency" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Ohita run container" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Ohita commit build output" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Ohita output check" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Ohita strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Rakenna eristettyyn verkkoympäristöön" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Suorita rakennettu linyaps sovellus" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Käyttö: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Käytä vain paikallisia tiedostoja" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Suorita tiettyjä moduuleja, kuten: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" "Kirjoita kontin nimi, suorittaaksesi komento sovelluksen suorittamiseksi" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Suorita vikasietotilassa (ottaa käyttöön kehitysmoduulit)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Luettelo rakennetuista linyaps sovelluksista" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Käyttö: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Poista rakennettu linyaps sovellus" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Käyttö: ll-builder remove [OPTIONS] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Vie linyaps kerrokseen tai uab:iin" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Käyttö: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Uab kuvake (valinnainen)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Vie uab kokonaan" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Vie linyaps tiedosto-kerrokseen" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "Vie linyaps tiedosto-kerrokseen (vanhentunut)" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Käytä mukautettua lataajaa" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Älä vie kehitysmoduulia" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Tulostustiedosto" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Siirrä linyaps sovellus palvelimen arkistoon" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Käyttö: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "Arkiston verkko-osoite" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Arkiston nimi" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Lähetä yksittäinen moduuli" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Tuo linyaps kerros rakennus-arkistoon" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Käyttö: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Tason tiedostopolku" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Tuo linyaps kerroshakemisto rakennus-arkistoon" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Käyttö: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Tason hakemistopolku" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Pura linyaps kerros hakemistoon" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Käyttö: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Kohdehakemisto" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Näytä ja hallitse ohjelma-arkistoja" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Käyttö: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Käyttö: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Käyttö: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Käyttö: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Käyttö: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Käyttö: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "linyaps build tool versio " diff --git a/po/pl.po b/po/pl.po index 1702c0a8b..c88ede485 100644 --- a/po/pl.po +++ b/po/pl.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Janusz Ruchała, 2025\n" "Language-Team: Polish (https://app.transifex.com/linuxdeepin/teams/3976/pl/)\n" @@ -21,44 +21,48 @@ msgstr "" "Language: pl\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Odmowa dostępu, sprawdź, czy uruchamiasz jako root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Aby zainstalować moduł, najpierw zainstaluj aplikację." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "Moduł jest już zainstalowany." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Nie udało się zainstalować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Nie udało się odinstalować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "Nie udało się zaktualizować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "Aplikacja nie jest zainstalowana." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "Najnowsza wersja jest już zainstalowana." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -68,7 +72,7 @@ msgstr "" "1. Sprawdzić swoje połączenie sieciowe\n" "2. Jeśli korzystasz, sprawdzić ustawienia proxy" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -76,15 +80,15 @@ msgstr "" "Aplikacja jest już zainstalowana. Jeśli chcesz ją zastąpić, spróbuj 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "Aplikacja %1 nie została znaleziona w zdalnym repozytorium" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "Nie można ustawić wersji podczas instalowania modułu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -92,14 +96,14 @@ msgstr "" "Najnowsza wersja jest już zainstalowana. Jeśli chcesz ją zastąpić, spróbuj " "'ll-cli install %1/version --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "Nie udało się wygenerować pamięci Cache, spróbuj ponownie zainstalować " "aplikację." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -107,19 +111,19 @@ msgstr "" "linyaps CLI\n" "Aplikacja wiersza poleceń do uruchamiania i zarządzania aplikacjami oraz środowiskami wykonawczymi\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Wyświetl tę wiadomość i zakończ" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Rozwiń pomoc" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Polecenie: ll-cli [OPCJE] [PODKOMENDA]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -129,11 +133,11 @@ msgstr "" "https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Pokaż wersję" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -141,47 +145,47 @@ msgstr "" "Użyj połączenia peer-to-peer DBus, zalecane, gdy daemon DBus nie jest " "dostępny" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Użyj formatu JSON do wyświetlenia wyniku." -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Parametr wejściowy jest pusty, wprowadź prawidłowy parametr" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Wyświetl informacje debug (poszerzone logi)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Zarządzanie zainstalowanymi aplikacjami i środowiskami wykonawczymi" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Zarządzanie uruchomionymi aplikacjami" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Poszukiwanie aplikacji i środowisk wykonawczych" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Zarządzanie zdalnymi repozytoriami" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Uruchom aplikację" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Wprowadź ID aplikacji" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -203,70 +207,70 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Przekaż pliki aplikacji działającej w piaskownicy" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Przekaż adres URL aplikacji działającej w piaskownicy" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Uruchom komendy w działającej piaskownicy" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Wyświetl listę uruchomionych aplikacji" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Polecenie: ll-cli ps [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Uruchom komendy w działającej piaskownicy" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "Podaj instancję aplikacji (znajdziesz ją za pomocą komendy ps)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Podaj katalog roboczy" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Wprowadź namespace, w której jest uruchomiona aplikacja" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Polecenie: ll-cli enter [OPCJE] INSTANCJA [KOMENDA...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Zatrzymaj uruchomione aplikacje" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Polecenie: ll-cli kill [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Podaj sygnał do wysłania aplikacji" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Podaj nazwę uruchomionej aplikacji" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Zainstaluj aplikację lub środowisko wykonawcze" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -302,56 +306,60 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "Podaj ID aplikacji, może być to również plik .uab lub .layer" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Zainstaluj moduł" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Wymuś instalację aplikacji" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Automatycznie odpowiedz tak dla wszystkich pytań" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Odinstaluj aplikację lub środowisko wykonawcze" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Polecenie: ll-cli uninstall [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Podaj ID aplikacji" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Odinstaluj określony moduł" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Usuń wszystkie nieużywane moduły" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Odinstaluj wszystkie moduły" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Zaktualizuj aplikację lub środowisko wykonawcze" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Polecenie: ll-cli upgrade [OPCJE] [APLIKACJA]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" @@ -359,7 +367,7 @@ msgstr "" "Podaj ID aplikacji. Jeśli nie podasz, wszystkie aplikacje zostaną " "zaktualizowane." -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -367,300 +375,298 @@ msgstr "" "Szukaj aplikacji/środowisk wykonawczych zawierających wpisany tekst w " "zdalnym repozytorium" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -"Polecenie: ll-cli search [OPCJE] SŁOWA KLUCZOWE\n" -"\n" -"Przykład:\n" -"# znajdź zdalnie aplikację po nazwie\n" -"ll-cli search org.deepin.demo\n" -"# znajdź zdalnie środowisko wykonawcze po nazwie\n" -"ll-cli search org.deepin.base --type=runtime\n" -"# wyświetl wszystkie aplikacje repozytorium\n" -"ll-cli search .\n" -"# wyświetl wszystkie środowiska wykonawcze repozytorium\n" -"ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Podaj słowa kluczowe" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "Filtruj wyniki konkretnego typu. Na przykład \"runtime\", \"app\" lub \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "Uwzględnij aplikacje w trakcie rozwoju w wynikach wyszukiwania" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Pokaż wszystkie wyniki" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Wyświetl listę zainstalowanych aplikacji lub środowisk wykonawczych" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -"Polecenie: ll-cli list [OPCJE]\n" -"\n" -"Przykład:\n" -"# pokaż zainstalowane aplikacje\n" -"ll-cli list\n" -"# pokaż zainstalowane środowiska wykonawcze\n" -"ll-cli list --type=runtime\n" -"# pokaż najnowsze wersje zainstalowanych aplikacji\n" -"ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Wyświetl listę najnowszych wersji dla zainstalowanych aplikacji (pokazuje " -"tylko aplikacje)" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Pokaż lub zmień informacje używanego repozytorium" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Polecenie: ll-cli repo PODKOMENDA [OPCJE]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Dodaj nowe repozytorium" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Polecenie: ll-cli repo add [OPCJE] NAZWA URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Podaj nazwę repozytorium" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "Adres URL repozytorium" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias repozytorium" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Zmień adres URL repozytorium" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Usuń repozytorium" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Polecenie: ll-cli repo remove [OPCJE] NAZWA" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Zaktualizuj adres URL repozytorium" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Polecenie: ll-cli repo update [OPCJE] NAZWA URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Ustaw domyślną nazwę repozytorium" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Polecenie: ll-cli repo set-default [OPCJE] NAZWA" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Pokaż informacje repozytorium" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Polecenie: ll-cli repo show [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Ustaw priorytet repozytorium" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Polecenie: ll-cli repo set-priority ALIAS PRIORYTET" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Priorytet repozytorium" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "" "Pokaż informacje o zainstalowanych aplikacjach i środowiskach wykonawczych" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Polecenie: ll-cli info [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Podaj ID aplikacji, może być to również plik .layer" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Pokaż wyeksportowane pliki zainstalowanych aplikacji" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Polecenie: ll-cli content [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Podaj ID zainstalowanej aplikacji" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Usuń nieużywaną bazę lub środowisko wykonawcze" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Polecenie: ll-cli prune [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Pokaż informacje zainstalowanej aplikacji" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Polecenie: ll-cli inspect [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Podaj ID procesu" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Nieprawidłowe ID procesu" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Nieprawidłowy format PID" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Podaj zainstalowaną aplikację (baza lub środowisko wykonawcze)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "Wersja linyaps CLI " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Nazwa" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "wersja" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Kanał" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Moduł" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Opis" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "Brak uruchomionych kontenerów." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Aplikacja" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ID kontenera" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "PID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "URL" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Priorytet" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "Brak aplikacji do zaktualizowania." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Zainstalowana" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Nowa" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -668,11 +674,11 @@ msgstr "" "linyaps builder CLI \n" "Aplikacja wiersza poleceń do budowania aplikacji\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Polecenie: ll-builder [OPCJE] [PODKOMENDA]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -681,42 +687,38 @@ msgstr "" "Możesz zgłosić błąd do zespołu linyaps klikając ten link: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Utwórz szablon budowania projektu linyaps" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Polecenie: ll-builder create [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Nazwa projektu" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Zbuduj projekt linyaps" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Polecenie: ll-builder build [OPCJE] [KOMENDA...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Ścieżka pliku linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Ustaw architekturę budowania" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Wykonuj polecenia wewnątrz kontenera, zamiast ciągle przebudowywać aplikacje" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -724,198 +726,197 @@ msgstr "" "Korzystaj tylko z plików lokalnych. To oznacza, że flagi --skip-fetch-source" " i --skip-pull-depend będą ustawione" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "" "Zbuduj ze wszystkimi pakietami dewelopera, wymagane przez środowisko " "wykonawcze" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Pomiń pobieranie źródeł" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Pomiń pobieranie zależności" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Pomiń uruchamianie kontenera" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Pomiń dane commitów buildu" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Pomiń kontrolę danych wyjściowych" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Pomiń usuwanie symboli debug" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Zbuduj w izolowanym środowisku sieciowym" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Uruchom zbudowaną aplikację linyaps" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Polecenie: ll-builder run [OPCJE] [KOMENDA...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Korzystaj tylko z plików lokalnych" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Uruchom określony moduł. np. --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "Wykonuj polecenia wewnątrz kontenera, zamiast włączać aplikację" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Uruchom w trybie debug (włącz moduł develop)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Wyświetl listę zbudowanych aplikacji linyaps" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Polecenie: ll-builder list [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Usuń zbudowaną aplikację linyaps" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Polecenie: ll-builder remove [OPCJE] [APLIKACJA...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Eksportuj do warstwy linyaps lub uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Polecenie: ll-builder export [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Ikona uab (opcjonalne)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Eksportuj uab całkowicie" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Eksportuj do pliku warstwy linyaps" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Użyj własnego loadera" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Nie eksportuj modułu develop" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Plik wyjściowy" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Wyślij aplikację linyaps do zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Polecenie: ll-builder push [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "Adres URL zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Nazwa zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Wyślij pojedynczy moduł" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Importuj warstwę linyaps do repozytorium build" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Polecenie: ll-builder import [OPCJE] WARSTWA" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Ścieżka pliku layer" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Importuj katalog warstw linyaps do repozytorium build" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Polecenie: ll-builder import-dir ŚCIEŻKA" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Ścieżka katalogu layer" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Wypakuj warstwy linyaps do katalogu" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Polecenie: ll-builder extract [OPCJE] WARSTWA KATALOG" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Katalog docelowy" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Wyświetl i zarządzaj repozytoriami" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Polecenie: ll-builder repo [OPCJE] PODKOMENDA" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Polecenie: ll-builder repo add [OPCJE] NAZWA URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Polecenie: ll-builder repo remove [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Polecenie: ll-builder repo update [OPCJE] NAZWA URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Polecenie: ll-builder repo set-default [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Polecenie: ll-builder repo show [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "Wersja narzędzia budowania linyaps " diff --git a/po/pt_BR.po b/po/pt_BR.po index f478ddddd..8af842f45 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: keven doria, 2025\n" "Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/teams/3976/pt_BR/)\n" @@ -23,44 +23,48 @@ msgstr "" "Language: pt_BR\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "Permissão negada, verifique se você está executando como root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Para instalar o módulo, primeiro é necessário instalar o aplicativo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "O módulo já está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Falha na instalação" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Falha na desinstalação" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "A atualização falhou" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "O aplicativo não está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "A versão mais recente já está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -70,7 +74,7 @@ msgstr "" "1. Verifique sua conexão com a internet.\n" "2. Verifique as configurações de proxy da rede, se utilizadas." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -78,15 +82,15 @@ msgstr "" "Aplicativo já instalado. Se você quiser substituí-lo, tente usar 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "O aplicativo %1 não foi encontrado no repositório remoto." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "Não é possível especificar uma versão ao instalar um módulo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -94,13 +98,13 @@ msgstr "" "A versão mais recente foi instalada. Se quiser substituí-la, tente usar 'll-" "cli install %1/version --force'." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "A criação do Cache falhou, por favor desinstale e reinstale o aplicativo." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -108,19 +112,19 @@ msgstr "" "linyaps CLI\n" "Um programa em CLI para executar aplicativos e gerenciar aplicativos e runtimes\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Exibir esta mensagem de ajuda e sair" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Expandir toda a ajuda" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-cli [OPÇÕES] [SUBCOMANDO]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -129,11 +133,11 @@ msgstr "" "Você pode reportar erros para o time linyaps sob este projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Mostrar versão" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -141,48 +145,48 @@ msgstr "" "Usar DBus peer-to-peer, isto é usado somente em caso onde DBus daemon não " "está disponível" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Usar o formato json para o resultado de saída" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" "Parâmetro de entrada está vazio, por favor informe um parâmetro válido" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Mostrar informações de depuração (registros detalhados)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Gerenciando aplicativos instalados e runtimes" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Gerenciando aplicativos em execução" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Encontrando aplicativos e runtimes" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Gerenciando repositórios remotos" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Executar um aplicativo" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Especifique o ID do aplicativo" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -204,72 +208,72 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "PAssar arquivos para aplicativos rodando em uma sandbox" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Passar url para aplicativos rodando em uma sandbox" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Executar comandos em uma sandbox em execução" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Listar aplicativos em execução" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Uso: ll-cli ps [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Executar comandos na sandbox atualmente em execução" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Especificar a instância de execução do aplicativo (você pode obter isto pelo" " comando ps)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Especificar o diretório de trabalho" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Informe o namespace onde o aplicativo está em execução" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Uso: ll-cli enter [OPÇÕES] INSTÂNCIA [COMANDO...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Parar os aplicativos em execução" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Uso: ll-cli kill [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Especificar o sinal para enviar ao aplicativo em execução" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Especificar o aplicativo em execução" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Instalando um aplicativo ou runtime" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -304,58 +308,62 @@ msgstr "" "# instalar aplicativo por referência detalhada\n" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64" -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Especifique o ID do aplicativo, que também pode ser um arquivo .uab ou " ".layer" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Instalar um módulo específico" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Forçar a instalação do aplicativo" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Responda automaticamente sim a todas as perguntas" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Desinstale o aplicativo ou os tempos de execução" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Uso: ll-cli uninstall [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Especifique o ID do aplicativo" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Desinstalar um módulo específico" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Remova todos os módulos não utilizados" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Desinstalar todos os módulos." -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Atualizar o aplicativo ou os tempos de execução" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Uso: ll-cli upgrade [OPÇÕES] [APP]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" @@ -363,7 +371,7 @@ msgstr "" "Especifique o ID do aplicativo. Caso não seja especificado, todos os " "aplicativos serão atualizados." -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -371,299 +379,297 @@ msgstr "" "Pesquisar os aplicativos/tempos de execução que contêm o texto especificado " "no repositório remoto" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -"Use: ll-cli search [OPÇÕES] PALAVRAS-CHAVE\n" -"\n" -"Exemplo:\n" -"# encontrar aplicativo remotamente pelo nome\n" -"ll-cli search org.deepin.demo\n" -"# encontrar tempo de execução remotamente pelo nome\n" -"ll-cli search org.deepin.base --type=runtime\n" -"# encontrar todos os aplicativos remotos\n" -"ll-cli search .\n" -"# encontrar todo o tempo de execução remoto\n" -"ll-cli search. --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Especifique as palavras-chave" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "Filtrar resultado com o tipo especificado. \"runtime\", \"app\" ou \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "incluir desenvolvimento de aplicação no resultado" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Mostrar todos os resultados" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Listar aplicativos ou tempos de execução instalados" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -"Uso: ll-cli list [OPÇÕES]\n" -"\n" -"Exemplo:\n" -"# mostrar aplicativos instalado(s)\n" -"ll-cli list\n" -"# mostrar tempos de execução instalado(s)\n" -"ll-cli list --type=runtime\n" -"# mostrar a lista de versões mais recentes dos aplicativos instalado(s)\n" -"ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Exibe a lista das versões mais recentes dos aplicativos instalados " -"atualmente, funciona apenas para aplicativos" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Exibir ou modificar informações do repositório atualmente em uso" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Uso: ll-cli repo SUBCOMANDO [OPÇÕES]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Adicionar um novo repositório" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo add [OPÇÕES] NOME URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Especifique o nome do repositório" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "URL do repositório" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias ​​do nome do repositório" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Modificar URL do repositório" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr " Remover um repositório" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Uso: ll-cli repo remove [OPÇÕES] NOME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Atualizar a URL do repositório" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo update [OPÇÕES] NOME URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Defina um nome padrão para o repositório" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Uso: ll-cli repo set-default [OPÇÕES] NOME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Mostrar informações do repositório" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Uso: ll-cli repo show [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Defina a prioridade do repositório" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Uso: ll-cli repo set-priority ALIAS PRIORITY" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Prioridade do repositório" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Exibir informações sobre aplicativos instalados ou tempos de execução" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Uso: ll-cli info [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Especifique o ID do aplicativo, que também pode ser um arquivo .layer" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Exibir os arquivos exportados do aplicativo instalado" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Uso: ll-cli content [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Especifique o ID do aplicativo instalado" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Remova a base ou o tempo de execução não utilizado" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Uso: ll-cli prune [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Exibir as informações do aplicativo instalado" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Uso: ll-cli inspect [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Especifique o ID do processo" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "ID de processo inválido" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Formato PID inválido" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Especifique o aplicativo instalado (base ou tempo de execução)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "Versão CLI do linyaps" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Nome" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "versão" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Canal" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Módulo" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Descrição" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "Nenhum contêiner está em execução." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Aplicativo" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "ID do contêiner" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "Pid" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "Url" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Prioridade" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "Nenhum aplicativo disponível para ser atualizado." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Instalado" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Novo" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -671,11 +677,11 @@ msgstr "" "construtor linyaps CLI \n" "Um programa CLI para construir um aplicativo Linyaps\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-builder [OPÇÕES] [SUBCOMANDO]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -683,42 +689,38 @@ msgstr "" "Se você encontrar algum problema durante o uso,\n" "Você pode reportar bugs para a equipe linyaps neste projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Criar projeto de modelo de construção linyaps" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Uso: ll-builder create [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Nome do projeto" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Crie um projeto linyaps" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder build [OPÇÕES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Caminho do arquivo linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Defina o arco de construção" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Entre no contêiner para executar o comando em vez de construir aplicativos" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -726,197 +728,196 @@ msgstr "" "Use apenas arquivos locais. Isso implica que --skip-fetch-source e --skip-" "pull-depend serão definidos" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Crie pacotes de desenvolvimento completos, o tempo de execução requer" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Pular busca de fontes" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Pular dependência de pull" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Pular execução do contêiner" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Pular saída de confirmação de compilação" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Pular verificação de saída" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Símbolos de depuração de faixa de salto" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Construir em um ambiente de rede isolado" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Execute o aplicativo Linyaps criado" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder run [OPÇÕES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Use apenas arquivos locais" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Execute o módulo especificado. Por exemplo: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" "Entre no contêiner para executar o comando em vez de executar o aplicativo" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Executar em modo de depuração (habilitar módulo de desenvolvimento)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Lista de aplicativos Linyaps criados" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Uso: ll-builder list [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Remover aplicativo linyaps construído" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Uso: ll-builder remove [OPÇÕES] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Exportar para camada linyaps ou uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Uso: ll-builder export [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Ícone Uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Exportar uab completamente" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Exportar para arquivo de camada linyaps" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Usar carregador personalizado" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Não exporte o módulo de desenvolvimento" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Arquivo de saída" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Enviar aplicativo Linyaps para repositório remoto" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Uso: ll-builder push [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "URL do repositório remoto" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Nome do repositório remoto" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Empurre um único módulo" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Importar camada linyaps para construir repositório" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Uso: ll-builder import [OPÇÕES] CAMADA" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Caminho do arquivo de camada" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Importar diretório da camada linyaps para construir repositório" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Uso: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Caminho do diretório da camada" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Extrair camada linyaps para diretório" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Uso: ll-builder extract [OPÇÕES] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Diretório de destino" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Exibir e gerenciar repositórios" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Uso: ll-builder repo [OPÇÕES] SUBCOMANDO" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo add [OPÇÕES] NOME URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Uso: ll-builder repo remove [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo update [OPÇÕES] NOME URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Uso: ll-builder repo set-default [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Uso: ll-builder repo show [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "versão da ferramenta de construção linyaps" diff --git a/po/sq.po b/po/sq.po index 16255b530..a24cd17ae 100644 --- a/po/sq.po +++ b/po/sq.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Besnik Bleta , 2025\n" "Language-Team: Albanian (https://app.transifex.com/linuxdeepin/teams/3976/sq/)\n" @@ -21,78 +21,82 @@ msgstr "" "Language: sq\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "Prodhimi i fshehtinës dështoi, ju lutemi, çinstalojeni dhe riinstalojeni " "aplikacionin." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -100,19 +104,19 @@ msgstr "" "linyaps CLI\n" "Një program CLI për të xhiruar dhe administruar aplikacion dhe “runtime”\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Shtyp këtë mesazh ndihme dhe dil" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Zgjero krejt ndihmën" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Përdorimi: ll-cli [MUNDËSI] [NËNURDHRA]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -121,59 +125,59 @@ msgstr "" "mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Shfaq versionin" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" msgstr "" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Përdor formatin json për të dhënë përfundimin" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" "Parametri që u dha është i zbrazët, ju lutemi, në vend të tij, jepni një " "parametër të vlefshëm" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Po administrohen aplikacionesh të instaluar dhe “runtimes”" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Po përditësohen aplikacione që xhirojnë" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Po gjenden aplikacione dhe “runtimes”" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Po administrohen depo të largëta" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Xhironi një aplikacion" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Jepni ID-në e aplikacionit" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -195,72 +199,72 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /shteg/për/te/programth/bash-i" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Kalojuni kartelë aplikacioneve që xhirojnë nën bankëprovë" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Kalojuni URL aplikacioneve që xhirojnë nën bankëprovë" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Ekzekutoni urdhra në një bankëprovë në funksionim" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Shfaq aplikacione që xhirojnë" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Përdorimi: ll-cli ps [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Ekzekutoni urdhra te bankëprova e tanishme funksionale" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Specifikoni instancën e xhirimit të aplikacionit (mund ta merrni përmes " "urdhrit ps)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Jepni drejtori pune" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Përdorimi: ll-cli enter [MUNDËSI] INSTANCË [URDHËR…]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Ndal aplikacione që janë duke xhiruar" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Përdorimi: ll-cli kill [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Specifikoni sinjalin për t’u dërguar te aplikacioni" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Përcaktoni aplikacionin në xhirim e sipër" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Po instalohet një aplikacione ose “runtime”" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -296,351 +300,363 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Jepni ID-në e aplikacionit dhe mund të jetë edhe një kartelë .uab ose .layer" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Instaloje me detyrim aplikacionin" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Përgjigju automatikisht po për krejt pyetjet" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Çinstalo aplikacionin ose “runtimes”" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Përdorimi: ll-cli uninstall [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Specifikoni ID aplikacioni" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Hiq krejt modulet e papërdorur" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Çinstalo krejt modulet" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Përmirësoni aplikacionin ose “runtimes”" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Përdorimi: ll-cli upgrade [MUNDËSI] [APLIKACION]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" msgstr "" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" msgstr "" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Jepni Fjalëkyçet" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" -"Filtro përfundimet me llojin e dhënë. Një nga “runtime”, “app”, ose “all”" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Shfaqi krejt përfundimet" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Shfaq aplikacione të instaluar ose “runtimes”" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -"Përdorimi: ll-cli list [MUNDËSI]\n" -"\n" -"Shembull:\n" -"# shfaq aplikacion(e) të instaluar\n" -"ll-cli list\n" -"# shfaq runtime(-e) të instaluar\n" -"ll-cli list --type=runtime\n" -"# shfaq listë versionesh më të rinj të aplikacionit(eve) të instaluar aktualisht\n" -"ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" msgstr "" -"Shfaq listën e versionit më të ri të aplikacioneve aktualisht të instaluara," -" funksionon vetëm për aplikacion" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Shfaqni ose ndryshoni hollësi të depos aktualisht në përdorim" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Përdorimi: ll-cli repo NËNURDHËR [MUNDËSI]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Shtoni depo të re" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Përdorimi: ll-cli repo add [MUNDËSI] EMËR URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Jepni emrin e depos" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "URL e depos" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Alias i emrit të depos" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Ndryshoni URL depo" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Hiqni një depo" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Përdorimi: ll-cli repo remove [MUNDËSI] EMËR" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Përditësoni URL-në e depos" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Përdorimi: ll-cli repo update [MUNDËSI] EMËR URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Caktoni një emër depoje parazgjedhje" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Përdorimi: ll-cli repo set-default [MUNDËSI] EMËR" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Shfaq hollësi depoje" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Përdorimi: ll-cli repo show [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Caktoni përparësinë e depos" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "Përdorimi: ll-cli repo set-priority ALIAS PËRPARËSI" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Përparësi e depos" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Shfaq hollësi rreth aplikacionesh të instaluar ose runtime-sh" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Përdorimi: ll-cli info [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specifikoni ID-në e aplikacionit dhe mund të jetë një kartelë .layer" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Shfaq kartelat e eksportuara të aplikacionit të instaluar" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Përdorimi: ll-cli content [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Specifikoni ID aplikacioni të instaluar" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Hiq bazën ose runtime-n e papërdorur" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Përdorimi: ll-cli prune [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Shfaq hollësitë e aplikacionit të instaluar" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Përdorimi: ll-cli inspect [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Jepni ID procesi" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "ID e pavlefshme procesi" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Format i pavlefshëm PID" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Specifikoni aplikacionin e instaluar (bazë ose “runtime”)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "Version CLI linyaps " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Emër" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "Version" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Kanal" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Modul" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Përshkrim" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "S’ka kontejnerë në xhirim e sipër." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Aplikacion" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "PID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "URL" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Alias" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Përparësi" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "S’ka aplikacione për përditësim." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Të instaluar" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "I ri" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -648,11 +664,11 @@ msgstr "" "linyaps builder CLI \n" "Një program CLI për montim aplikacionesh linyaps\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Përdorimi: ll-builder [MUNDËSI] [NËNURDHËR]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -660,43 +676,39 @@ msgstr "" "Nëse gjetët çfarëdo problemi gjatë përdorimit\n" "mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Krijoni projekt gjedhe montimi linyaps" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Përdorimi: ll-builder create [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Emër projekti" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Ndërtoni një projekt linyaps" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Përdorimi: ll-builder build [MUNDËSI] [URDHËR…]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Shteg kartele linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "" "Jepni kontejnerin ku të ekzekutohet urdhri, në vend se të montohen " "aplikacione" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -704,198 +716,197 @@ msgstr "" "Përdor vetëm kartela vendore. Kjo nënkupton se do të përdoren --skip-fetch-" "source dhe --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Monto paketa të plota zhvillimi, lyp “runtime”" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Anashkalo sjellje burimesh" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Anashkalo marrje varësish" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Anashkalo xhirim kontejneri" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Anashkalo kontroll të ç’jepet si përfundim" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Anashkalo heqje simbolesh diagnostikimi" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Montoni në një mjedis të izoluar rrjeti" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Përdorimi: ll-builder run [MUNDËSI] [URDHËR…]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Përdor vetëm kartela vendore" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Xhiro modulin e treguar. P. sh.: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "" "Për ekzekutimin e urdhrit hyr në kontejner, në vend të xhirimit të " "aplikacionit" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Xhiroje nën mënyrën diagnostikim (aktivizoni modulin “develop”)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Përdorimi: ll-builder list [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Përdorimi: ll-builder remove [MUNDËSI] [APLIKACION…]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Eksportoje te shtresë linyaps, ose uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Përdorimi: ll-builder export [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Ikonë uab (opsionale)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Eksportoje te kartelë shtrese linyaps" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Përdor ngarkues vetjak" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Mos eksporto modulin e zhvillimit" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Kaloje aplikacionin linyaps te depoja e largët" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Përdorimi: ll-builder push [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "URL depoje të largët" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Emër depoje të largët" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Përdorimi: ll-builder import [MUNDËSI] SHTRESË" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Shteg kartele shtrese" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Përdorimi: ll-builder import-dir SHTEG" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Shteg drejtorie shtrese" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Përfto shtresë linyaps te drejtoria" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Përdorimi: ll-builder extract [MUNDËSI] SHTRESË DREJTORI" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Drejtori vendmbërritje" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Shfaqni dhe administroni depo" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Përdorimi: ll-builder repo [MUNDËSI] NËNURDHËR" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Përdorimi: ll-builder repo add [MUNDËSI] EMËR URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Përdorimi: ll-builder repo remove [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Përdorimi: ll-builder repo update [MUNDËSI] EMËR URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Përdorimi: ll-builder repo set-default [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Përdorimi: ll-builder repo show [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "version mjeti montimesh linyaps" diff --git a/po/uk.po b/po/uk.po index 071c0b34f..e4f805a86 100644 --- a/po/uk.po +++ b/po/uk.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Yuri Chornoivan , 2025\n" "Language-Team: Ukrainian (https://app.transifex.com/linuxdeepin/teams/3976/uk/)\n" @@ -21,46 +21,50 @@ msgstr "" "Language: uk\n" "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "" "Відмовлено у доступі. Будь ласка, перевірте, чи запущено програму від імені " "користувача root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "Для встановлення модуля слід спочатку встановити програму." -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "Модуль вже встановлено." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "Не вдалося встановити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "Не вдалося вилучити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "Не вдалося оновити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "Програму не встановлено." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "Вже встановлено найсвіжішу версію." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -70,7 +74,7 @@ msgstr "" "1. Перевірте працездатність з'єднання з інтернетом\n" "2. Перевірте параметри проксі-сервера, якщо такий використано" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -78,15 +82,15 @@ msgstr "" "Програму вже встановлено. Якщо ви хочете її замінити, спробуйте команду «ll-" "cli install %1 --force»" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "У віддаленому сховищі не знайдено програми %1." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "Не можна вказувати версію, якщо встановлюється модуль." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -94,14 +98,14 @@ msgstr "" "Вже встановлено найсвіжішу версію. Якщо ви хочете її замінити, спробуйте " "команду «ll-cli install %1/version --force»" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" "Не вдалося створити кеш. Будь ласка, вилучіть і повторно встановіть " "програму." -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -109,19 +113,19 @@ msgstr "" "linyaps CLI\n" "Інтерфейс командного рядка для запуску програм і керування програмами та середовищами виконання програм\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "Вивести це довідкове повідомлення і завершити роботу" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "Розгорнути довідку" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "Користування: ll-cli [ПАРАМЕТРИ] [ПІДКОМАНДА]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -130,11 +134,11 @@ msgstr "" "ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "Показати дані щодо версії" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" @@ -142,47 +146,47 @@ msgstr "" "Скористатися міжвузловим DBus, використовується лише у випадку, коли фонова " "служба DBus є недоступною" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "Використати формат json для виведення результату" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Вхідний параметр є порожнім. Будь ласка, вкажіть чинний параметр" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "Показати діагностичні дані (докладний журнал)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "Керування встановленими програмами і середовищами виконання" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "Керування запущеними програмами" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "Пошук програм і середовищ виконання" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "Керування віддаленими сховищами" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "Запустити програму" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "Вказати ідентифікатор програми" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -204,72 +208,72 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "Передати файл програмам, які запущено у пісочниці" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "Передати адресу програмам, які запущено у пісочниці" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "Запустити команди у запущеній пісочниці" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "Вивести список запущених програм" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "Користування: ll-cli ps [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "Виконати команди у поточній запущеній пісочниці" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" "Вказати запущений екземпляр програми (отримати його можна за допомогою " "команди ps)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "Вказати робочий каталог" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "Введіть простір назв, у якому запущено програму" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "Користування: ll-cli enter [ПАРАМЕТРИ] ЕКЗЕМПЛЯР [КОМАНДА...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "Зупинити запущені програми" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "Користування: ll-cli kill [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "Вказати сигнал для надсилання програмі" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "Вказати запущену програму" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "Встановлення програми або середовища виконання" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -305,65 +309,69 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" "Вказати за ідентифікатором програми, також можна вказати файл .uab або " ".layer" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "Встановити вказаний модуль" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "Примусово встановити програму" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "Автоматично відповідати «так» на усі питання" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "Вилучити програму або середовища виконання" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "Користування: ll-cli uninstall [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "Вказати ідентифікатори програм" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "Вилучити вказаний модуль" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "Вилучити усі невикористані модулі" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "Деінсталювати усі модулі" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "Оновити програму або середовища виконання" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "Користування: ll-cli upgrade [ПАРАМЕТРИ] [ПРОГРАМА]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" msgstr "" "Вказати ідентифікатор програми. Якщо не вказано, буде оновлено усі програми" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" @@ -371,299 +379,298 @@ msgstr "" "Шукати у віддаленому сховищі програми або середовища виконання, назви яких " "містять вказаний текст" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" -"Користування: ll-cli search [ПАРАМЕТРИ] КЛЮЧОВІ СЛОВА\n" -"\n" -"Приклад:\n" -"# знайти віддалену програму за назвою\n" -"ll-cli search org.deepin.demo\n" -"# знайти віддалене середовище виконання за назвою\n" -"ll-cli search org.deepin.base --type=runtime\n" -"# знайти усі програми у віддаленому сховищі\n" -"ll-cli search .\n" -"# знайти усі середовища виконання у віддаленому сховищі\n" -"ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "Вказати ключові слова" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" msgstr "" -"Фільтрувати результат за типом. Одне зі значень, «runtime», «app» або «all»" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "Включити до результату програми у розробці" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "Показати усі результати" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "Вивести список встановлених програм або середовищ виконання" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" -"Користування: ll-cli list [ПАРАМЕТРИ]\n" -"\n" -"Приклад:\n" -"# вивести список встановлених програм\n" -"ll-cli list\n" -"# вивести список встановлених середовищ виконання\n" -"ll-cli list --type=runtime\n" -"# вивести список найсвіжіших версій поточних встановлених програм\n" -"ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" -msgstr "Вивести список найсвіжіших встановлених програм, працює лише програм" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" +msgstr "" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "Вивести або змінити дані поточного використаного сховища" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Користування: ll-cli repo ПІДКОМАНДА [ПАРАМЕТРИ]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "Додати новий запис сховища" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Користування: ll-cli repo add [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "Вказати назву сховища" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "Адреса сховища" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "Альтернативна назва сховища" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "Змінити адресу сховища" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "Вилучити запис сховища" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "Користування: ll-cli repo remove [ПАРАМЕТРИ] НАЗВА" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "Оновити адресу сховища" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Користування: ll-cli repo update [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "Встановити назву типового сховища" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Користування: ll-cli repo set-default [ПАРАМЕТРИ] НАЗВА" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "Вивести дані сховища" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "Користування: ll-cli repo show [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "Встановити пріоритетність сховища" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "" "Користування: ll-cli repo set-priority АЛЬТЕРНАТИВНА_НАЗВА ПРІОРИТЕТНІСТЬ" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "Пріоритетність сховища" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "Вивести дані щодо встановлених програм або середовищ виконання" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Користування: ll-cli info [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Вказати за ідентифікатором програми, також можна вказати файл .layer" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "Показати експортовані файли встановленої програми" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Користування: ll-cli content [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "Вказати ідентифікатор встановленої програми" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "Вилучити невикористану основу або середовище виконання" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Користування: ll-cli prune [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "Вивести дані щодо встановленої програми" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Користування: ll-cli inspect [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "Вказати ідентифікатор процесу" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "Некоректний ідентифікатор процесу" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "Некоректний формат PID" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "Вказати встановлену програму (основу або середовище виконання)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "Командний інтерфейс linyaps, версія " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "Ід." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "Назва" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "Версія" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "Канал" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "Модуль" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "Опис" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "Не запущено жодного контейнера." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "Програма" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "Ід. контейнера" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "PID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "Адреса" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "Інша назва" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "Пріоритетність" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "Немає програм для оновлення." -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "Встановлено" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "Створити" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -671,11 +678,11 @@ msgstr "" "Командний інтерфейс збиральника linyaps \n" "Командний інтерфейс для збирання програм linyaps\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Користування: ll-builder [ПАРАМЕТРИ] [ПІДКОМАНДА]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -683,41 +690,37 @@ msgstr "" "Якщо під час користування у вас виникнуть якісь проблеми,\n" "ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "Створити проєкт шаблону збирання linyaps" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Користування: ll-builder create [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "Назва проєкту" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "Зібрати проєкт linyaps" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Користування: ll-builder build [ПАРАМЕТРИ] [КОМАНДА...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "Шлях до файла linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "Встановити архітектуру збирання" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "Введіть контейнер для виконання команди замість збирання програм" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -725,196 +728,195 @@ msgstr "" "Використовувати лише локальні файли. Неявно припускає, що буде встановлено " "--skip-fetch-source і --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "Зібрати повні пакунки для розробки, потрібне середовище виконання" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "Пропустити отримання початкового коду" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "Пропустити отримання залежності" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "Пропустити запуск контейнера" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "Пропустити внесення результатів збирання" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "Пропустити перевірку результатів" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "Пропустити вилучення діагностичних символів" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "Зібрати у ізольованому середовищі у мережі" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "Запустити зібрану програму linyaps" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Користування: ll-builder run [ПАРАМЕТРИ] [КОМАНДА...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "Використовувати лише локальні файли" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "Запустити вказаний модуль. Приклад: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "Введіть контейнер для виконання команди замість запуску програми" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "Запустити у діагностичному режимі (увімкнути модуль розробки)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "Вивести список зібраних програм linyaps" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Користування: ll-builder list [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "Вилучити зібрану програму linyaps" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Користування: ll-builder remove [ПАРАМЕТРИ] [ПРОГРАМА...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "Експортувати до шару або uab linyaps" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Користування: ll-builder export [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Піктограма uab (необов'язкова)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "Експортувати uab повністю" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "Експортувати до файла шару linyaps" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "Використати нетиповий завантажувач" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "Не експортувати модуль розробки" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "Файл результатів" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "Записати програму linyaps до віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Користування: ll-builder push [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "Адреса віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "Назва віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "Записати окремий модуль" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "Імпортувати шар linyaps для побудови сховища" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Користування: ll-builder import [ПАРАМЕТРИ] ШАР" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "Шлях до файла шару" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "Імпортувати каталог шару linyaps для побудови сховища" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "Користування: ll-builder import-dir ШЛЯХ" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "Шлях до каталогу шару" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "Видобути шар linyaps до каталогу" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Користування: ll-builder extract [ПАРАМЕТРИ] ШАР КАТАЛОГ" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "Каталог призначення" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "Показати сховища і керувати ними" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Користування: ll-builder repo [ПАРАМЕТРИ] ПІДКОМАНДА" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Користування: ll-builder repo add [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Користування: ll-builder repo remove [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Користування: ll-builder repo update [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Користування: ll-builder repo set-default [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Користування: ll-builder repo show [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "Інструмент збирання linyaps, версія " diff --git a/po/zh_CN.po b/po/zh_CN.po index d94b213d7..aa178f1eb 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-16 13:06+0800\n" +"POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: chang Gao, 2025\n" "Language-Team: Chinese (China) (https://app.transifex.com/linuxdeepin/teams/3976/zh_CN/)\n" @@ -22,44 +22,48 @@ msgstr "" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:58 +#: ../libs/linglong/src/linglong/cli/cli.cpp:67 msgid "Permission denied, please check whether you are running as root." msgstr "权限被拒绝,请检查是否以 root 身份运行。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:437 +#: ../libs/linglong/src/linglong/cli/cli.cpp:443 msgid "To install the module, one must first install the app." msgstr "要安装该模块,必须先安装此应用程序。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:440 +#: ../libs/linglong/src/linglong/cli/cli.cpp:446 msgid "Module is already installed." msgstr "模块已经安装" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1295 +#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 msgid "Install failed" msgstr "安装失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1733 +#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +msgid "The module could not be found remotely." +msgstr "远程无法找到该模块" + +#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Uninstall failed" msgstr "卸载失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 +#: ../libs/linglong/src/linglong/cli/cli.cpp:458 msgid "Upgrade failed" msgstr "升级失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1656 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1729 +#: ../libs/linglong/src/linglong/cli/cli.cpp:461 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 msgid "Application is not installed." msgstr "应用未安装。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 +#: ../libs/linglong/src/linglong/cli/cli.cpp:464 msgid "Latest version is already installed." msgstr "已安装最新版本。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1269 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1518 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -69,32 +73,32 @@ msgstr "" "1. 检查您的互联网连接\n" "2. 如使用代理,请确认网络代理设置" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1275 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "应用已安装。如需覆盖安装,请尝试使用命令:ll-cli install %1 --force" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1281 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 msgid "Application %1 is not found in remote repo." msgstr "远程仓库中未找到应用 %1" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1285 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 msgid "Cannot specify a version when installing a module." msgstr "安装模块时不允许指定版本。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1289 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "当前已安装最新版本。如需覆盖安装,请尝试使用命令:ll-cli install %1/version --force" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2732 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "缓存生成失败,请卸载并重新安装该应用程序。" -#: ../apps/ll-cli/src/main.cpp:148 +#: ../apps/ll-cli/src/main.cpp:149 msgid "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" @@ -102,19 +106,19 @@ msgstr "" "如意玲珑 CLI\n" "一个用于运行应用程序和管理应用程序和运行时的命令行工具\n" -#: ../apps/ll-cli/src/main.cpp:160 ../apps/ll-builder/src/main.cpp:172 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 msgid "Print this help message and exit" msgstr "打印帮助信息并退出" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:173 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 msgid "Expand all help" msgstr "展开所有帮助" -#: ../apps/ll-cli/src/main.cpp:162 +#: ../apps/ll-cli/src/main.cpp:163 msgid "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" msgstr "用法: ll-cli [选项] [子命令]" -#: ../apps/ll-cli/src/main.cpp:163 +#: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -123,57 +127,57 @@ msgstr "" "您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:170 ../apps/ll-builder/src/main.cpp:194 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 msgid "Show version" msgstr "显示版本" -#: ../apps/ll-cli/src/main.cpp:174 +#: ../apps/ll-cli/src/main.cpp:175 msgid "" "Use peer to peer DBus, this is used only in case that DBus daemon is not " "available" msgstr "使用点对点 DBus,仅在 DBus 守护程序不可用时使用" -#: ../apps/ll-cli/src/main.cpp:178 +#: ../apps/ll-cli/src/main.cpp:179 msgid "Use json format to output result" msgstr "使用json格式输出结果" -#: ../apps/ll-cli/src/main.cpp:185 ../apps/ll-cli/src/main.cpp:541 -#: ../apps/ll-builder/src/main.cpp:185 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "输入参数为空,请输入有效参数" -#: ../apps/ll-cli/src/main.cpp:210 +#: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" msgstr "显示调试信息(详细日志)" #. groups -#: ../apps/ll-cli/src/main.cpp:213 +#: ../apps/ll-cli/src/main.cpp:212 msgid "Managing installed applications and runtimes" msgstr "管理已安装的应用程序和运行时" -#: ../apps/ll-cli/src/main.cpp:214 +#: ../apps/ll-cli/src/main.cpp:213 msgid "Managing running applications" msgstr "管理正在运行的应用程序" -#: ../apps/ll-cli/src/main.cpp:215 +#: ../apps/ll-cli/src/main.cpp:214 msgid "Finding applications and runtimes" msgstr "查找应用程序和运行时" -#: ../apps/ll-cli/src/main.cpp:216 +#: ../apps/ll-cli/src/main.cpp:215 msgid "Managing remote repositories" msgstr "管理仓库" #. add sub command run -#: ../apps/ll-cli/src/main.cpp:219 +#: ../apps/ll-cli/src/main.cpp:218 msgid "Run an application" msgstr "运行应用程序" #. add sub command run options -#: ../apps/ll-cli/src/main.cpp:224 +#: ../apps/ll-cli/src/main.cpp:223 msgid "Specify the application ID" msgstr "指定应用程序名" -#: ../apps/ll-cli/src/main.cpp:227 +#: ../apps/ll-cli/src/main.cpp:226 msgid "" "Usage: ll-cli run [OPTIONS] APP [COMMAND...]\n" "\n" @@ -195,70 +199,70 @@ msgstr "" "ll-cli run org.deepin.demo -- bash\n" "ll-cli run org.deepin.demo -- bash -x /path/to/bash/script" -#: ../apps/ll-cli/src/main.cpp:237 +#: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" msgstr "将文件传递到沙盒中运行的应用程序" -#: ../apps/ll-cli/src/main.cpp:241 +#: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" msgstr "将URL传递到沙盒中运行的应用程序" -#: ../apps/ll-cli/src/main.cpp:244 ../apps/ll-cli/src/main.cpp:266 -#: ../apps/ll-cli/src/main.cpp:283 +#: ../apps/ll-cli/src/main.cpp:243 ../apps/ll-cli/src/main.cpp:265 +#: ../apps/ll-cli/src/main.cpp:282 msgid "Run commands in a running sandbox" msgstr "在正在运行的沙盒中运行命令" #. add sub command ps -#: ../apps/ll-cli/src/main.cpp:247 +#: ../apps/ll-cli/src/main.cpp:246 msgid "List running applications" msgstr "列出正在运行的应用程序" -#: ../apps/ll-cli/src/main.cpp:250 +#: ../apps/ll-cli/src/main.cpp:249 msgid "Usage: ll-cli ps [OPTIONS]" msgstr "用法: ll-cli ps [选项]" -#: ../apps/ll-cli/src/main.cpp:254 +#: ../apps/ll-cli/src/main.cpp:253 msgid "Execute commands in the currently running sandbox" msgstr "在当前运行的沙盒中执行命令。" -#: ../apps/ll-cli/src/main.cpp:260 ../apps/ll-cli/src/main.cpp:278 +#: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "指定正在运行的应用程序实例(可以通过 ps 命令获取)" -#: ../apps/ll-cli/src/main.cpp:263 ../apps/ll-cli/src/main.cpp:280 +#: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" msgstr "指定工作目录" -#: ../apps/ll-cli/src/main.cpp:271 +#: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" msgstr "进入应用程序正在运行的命名空间" -#: ../apps/ll-cli/src/main.cpp:274 +#: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" msgstr "用法: ll-cli enter [选项] 实例 [命令...]" #. add sub command kill -#: ../apps/ll-cli/src/main.cpp:286 +#: ../apps/ll-cli/src/main.cpp:285 msgid "Stop running applications" msgstr "停止运行的应用程序" -#: ../apps/ll-cli/src/main.cpp:289 +#: ../apps/ll-cli/src/main.cpp:288 msgid "Usage: ll-cli kill [OPTIONS] APP" msgstr "用法: ll-cli kill [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:293 +#: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" msgstr "指定要发送到应用程序的信号" -#: ../apps/ll-cli/src/main.cpp:295 +#: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" msgstr "指定正在运行的应用程序名" -#: ../apps/ll-cli/src/main.cpp:301 +#: ../apps/ll-cli/src/main.cpp:300 msgid "Installing an application or runtime" msgstr "安装应用程序或运行时" -#: ../apps/ll-cli/src/main.cpp:304 +#: ../apps/ll-cli/src/main.cpp:303 msgid "" "Usage: ll-cli install [OPTIONS] APP\n" "\n" @@ -294,119 +298,132 @@ msgstr "" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" " " -#: ../apps/ll-cli/src/main.cpp:323 +#: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "指定应用名,也可以是 .uab 或 .layer 文件" -#: ../apps/ll-cli/src/main.cpp:326 +#: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" msgstr "安装指定模块" -#: ../apps/ll-cli/src/main.cpp:329 +#: ../apps/ll-cli/src/main.cpp:328 +msgid "Install from a specific repo" +msgstr "从指定的仓库安装" + +#: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" msgstr "强制安装指定版本的应用程序" -#: ../apps/ll-cli/src/main.cpp:330 +#: ../apps/ll-cli/src/main.cpp:332 msgid "Automatically answer yes to all questions" msgstr "自动对所有问题回答是" -#: ../apps/ll-cli/src/main.cpp:336 +#: ../apps/ll-cli/src/main.cpp:338 msgid "Uninstall the application or runtimes" msgstr "卸载应用程序或运行时" -#: ../apps/ll-cli/src/main.cpp:339 +#: ../apps/ll-cli/src/main.cpp:341 msgid "Usage: ll-cli uninstall [OPTIONS] APP" msgstr "用法: ll-cli uninstall [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:340 +#: ../apps/ll-cli/src/main.cpp:342 msgid "Specify the applications ID" msgstr "指定应用程序名" -#: ../apps/ll-cli/src/main.cpp:343 +#: ../apps/ll-cli/src/main.cpp:345 msgid "Uninstall a specify module" msgstr "卸载指定模块" #. below options are used for compatibility with old ll-cli -#: ../apps/ll-cli/src/main.cpp:348 +#: ../apps/ll-cli/src/main.cpp:350 msgid "Remove all unused modules" msgstr "移除所有不使用的模块" -#: ../apps/ll-cli/src/main.cpp:352 +#: ../apps/ll-cli/src/main.cpp:354 msgid "Uninstall all modules" msgstr "卸载所有模块" -#: ../apps/ll-cli/src/main.cpp:358 +#: ../apps/ll-cli/src/main.cpp:360 msgid "Upgrade the application or runtimes" msgstr "升级应用程序或运行时" -#: ../apps/ll-cli/src/main.cpp:361 +#: ../apps/ll-cli/src/main.cpp:363 msgid "Usage: ll-cli upgrade [OPTIONS] [APP]" msgstr "用法: ll-cli upgrade [选项] [应用]" -#: ../apps/ll-cli/src/main.cpp:365 +#: ../apps/ll-cli/src/main.cpp:367 msgid "" "Specify the application ID. If it not be specified, all applications will be" " upgraded" msgstr "指定应用程序名。如果未指定,将升级所有可升级的应用程序" -#: ../apps/ll-cli/src/main.cpp:372 +#: ../apps/ll-cli/src/main.cpp:374 msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" msgstr "从远程仓库中搜索包含指定关键词的应用程序/运行时" -#: ../apps/ll-cli/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:378 msgid "" "Usage: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Example:\n" -"# find remotely app by name\n" +"# find remotely application(s), base(s) or runtime(s) by keywords\n" "ll-cli search org.deepin.demo\n" -"# find remotely runtime by name\n" -"ll-cli search org.deepin.base --type=runtime\n" "# find all of app of remote\n" "ll-cli search .\n" -"# find all of runtime of remote\n" +"# find all of base(s) of remote\n" +"ll-cli search . --type=base\n" +"# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" "用法: ll-cli search [选项] 关键词\n" +"\n" "示例:\n" -"# 通过应用名从远程仓库搜索应用程序\n" +"# 按照名称搜索远程的 application(s), base(s) 或 runtime(s)\n" "ll-cli search org.deepin.demo\n" -"# 从远程仓库里搜索指定类型的应用程序\n" +"# 按名称搜索远程 runtime\n" "ll-cli search org.deepin.base --type=runtime\n" -"# 从远程仓库搜索所有应用程序\n" +"# 搜索远程所有软件包\n" "ll-cli search .\n" -"# 从远程仓库搜索所有运行时\n" +"# 搜索远程所有的base\n" +"ll-cli search . --type=base\n" +"# 搜索远程所有的runtime\n" "ll-cli search . --type=runtime" -#: ../apps/ll-cli/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" msgstr "指定搜索关键词" -#: ../apps/ll-cli/src/main.cpp:393 ../apps/ll-cli/src/main.cpp:418 -msgid "Filter result with specify type. One of \"runtime\", \"app\" or \"all\"" -msgstr "使用指定类型过滤结果。“runtime”、“app”或“all”之一" +#: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "按指定类型过滤结果。可选类型:\"runtime\"、\"base\"、\"app\"或 \"all\"。" + +#: ../apps/ll-cli/src/main.cpp:400 +msgid "Specify the repo" +msgstr "指定仓库" -#: ../apps/ll-cli/src/main.cpp:397 -msgid "include develop application in result" -msgstr "搜索结果中包括应用调试包" +#: ../apps/ll-cli/src/main.cpp:403 +msgid "Include develop application in result" +msgstr "结果包括应用调试包" -#: ../apps/ll-cli/src/main.cpp:398 -msgid "Show all results" -msgstr "显示所有结果" +#: ../apps/ll-cli/src/main.cpp:406 +msgid "Show all versions of an application(s), base(s) or runtime(s)" +msgstr "显示应用,base或runtime的所有版本" -#: ../apps/ll-cli/src/main.cpp:402 -msgid "List installed applications or runtimes" -msgstr "列出已安装的应用程序或运行时" +#: ../apps/ll-cli/src/main.cpp:411 +msgid "List installed application(s), base(s) or runtime(s)" +msgstr "列出已安装的 应用, base或runtime" -#: ../apps/ll-cli/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:414 msgid "" "Usage: ll-cli list [OPTIONS]\n" "\n" "Example:\n" -"# show installed application(s)\n" +"# show installed application(s), base(s) or runtime(s)\n" "ll-cli list\n" +"# show installed base(s)\n" +"ll-cli list --type=base\n" "# show installed runtime(s)\n" "ll-cli list --type=runtime\n" "# show the latest version list of the currently installed application(s)\n" @@ -415,236 +432,252 @@ msgstr "" "用法: ll-cli list [选项]\n" "\n" "示例:\n" -"# 显示已安装的应用程序\n" +"# 显示已安装的应用, base(s) 或 runtime(s)\n" "ll-cli list\n" -"# 显示已安装的运行时\n" +"#显示已安装的 base(s)\n" +"ll-cli list --type=base\n" +"# 显示已安装的 runtime(s)\n" "ll-cli list --type=runtime\n" -"# 显示当前已安装应用程序的最新版本列表\n" +"# 显示当前已安装应用的最新版本列表\n" "ll-cli list --upgradable\n" -#: ../apps/ll-cli/src/main.cpp:424 +#: ../apps/ll-cli/src/main.cpp:436 msgid "" -"Show the list of latest version of the currently installed applications, it " -"only works for app" -msgstr "显示当前已安装应用程序的最新版本列表,仅适用于应用程序" +"Show the list of latest version of the currently installed application(s), " +"base(s) or runtime(s)" +msgstr "显示当前已安装的应用(application)、基础环境(base)或运行时(runtime)的最新版本" -#: ../apps/ll-cli/src/main.cpp:431 +#: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" msgstr "显示或修改当前使用的仓库信息" -#: ../apps/ll-cli/src/main.cpp:433 +#: ../apps/ll-cli/src/main.cpp:445 msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "用法: ll-cli repo [选项] 子命令" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:437 ../apps/ll-builder/src/main.cpp:374 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 msgid "Add a new repository" msgstr "添加新的仓库" -#: ../apps/ll-cli/src/main.cpp:438 +#: ../apps/ll-cli/src/main.cpp:450 msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "用法: ll-cli repo add [选项] 名称 URL" -#: ../apps/ll-cli/src/main.cpp:439 ../apps/ll-cli/src/main.cpp:452 -#: ../apps/ll-builder/src/main.cpp:376 +#: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 +#: ../apps/ll-builder/src/main.cpp:894 msgid "Specify the repo name" msgstr "指定仓库名称" -#: ../apps/ll-cli/src/main.cpp:442 ../apps/ll-cli/src/main.cpp:455 -#: ../apps/ll-cli/src/main.cpp:473 ../apps/ll-builder/src/main.cpp:379 -#: ../apps/ll-builder/src/main.cpp:399 +#: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 +#: ../apps/ll-builder/src/main.cpp:920 msgid "Url of the repository" msgstr "仓库URL" -#: ../apps/ll-cli/src/main.cpp:445 ../apps/ll-cli/src/main.cpp:462 -#: ../apps/ll-cli/src/main.cpp:470 ../apps/ll-cli/src/main.cpp:481 -#: ../apps/ll-cli/src/main.cpp:493 ../apps/ll-builder/src/main.cpp:382 -#: ../apps/ll-builder/src/main.cpp:389 ../apps/ll-builder/src/main.cpp:396 -#: ../apps/ll-builder/src/main.cpp:407 +#: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 +#: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 +#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 +#: ../apps/ll-builder/src/main.cpp:929 msgid "Alias of the repo name" msgstr "仓库别名" -#: ../apps/ll-cli/src/main.cpp:451 +#: ../apps/ll-cli/src/main.cpp:463 msgid "Modify repository URL" msgstr "修改仓库URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:460 ../apps/ll-builder/src/main.cpp:387 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 msgid "Remove a repository" msgstr "移除仓库" -#: ../apps/ll-cli/src/main.cpp:461 +#: ../apps/ll-cli/src/main.cpp:473 msgid "Usage: ll-cli repo remove [OPTIONS] NAME" msgstr "用法: ll-cli repo remove [选项] 名称" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:468 ../apps/ll-builder/src/main.cpp:394 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 msgid "Update the repository URL" msgstr "更新仓库URL" -#: ../apps/ll-cli/src/main.cpp:469 +#: ../apps/ll-cli/src/main.cpp:481 msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "用法: ll-cli repo update [选项] 名称 URL" -#: ../apps/ll-cli/src/main.cpp:479 ../apps/ll-builder/src/main.cpp:405 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 msgid "Set a default repository name" msgstr "设置默认仓库名称" -#: ../apps/ll-cli/src/main.cpp:480 +#: ../apps/ll-cli/src/main.cpp:492 msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "用法: ll-cli repo set-default [选项] 名称" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:486 ../apps/ll-builder/src/main.cpp:412 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 msgid "Show repository information" msgstr "显示仓库信息" -#: ../apps/ll-cli/src/main.cpp:487 +#: ../apps/ll-cli/src/main.cpp:499 msgid "Usage: ll-cli repo show [OPTIONS]" msgstr "用法: ll-cli repo show [选项]" -#: ../apps/ll-cli/src/main.cpp:491 +#: ../apps/ll-cli/src/main.cpp:503 msgid "Set the priority of the repo" msgstr "设置仓库优先级" -#: ../apps/ll-cli/src/main.cpp:492 +#: ../apps/ll-cli/src/main.cpp:504 msgid "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgstr "用法:ll-cli repo set-priority ALIAS PRIORITY" -#: ../apps/ll-cli/src/main.cpp:497 +#: ../apps/ll-cli/src/main.cpp:509 msgid "Priority of the repo" msgstr "仓库优先级" -#: ../apps/ll-cli/src/main.cpp:504 +#: ../apps/ll-cli/src/main.cpp:516 msgid "Display information about installed apps or runtimes" msgstr "显示已安装的应用程序或运行时的信息" -#: ../apps/ll-cli/src/main.cpp:507 +#: ../apps/ll-cli/src/main.cpp:519 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "用法: ll-cli info [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:511 +#: ../apps/ll-cli/src/main.cpp:523 msgid "Specify the application ID, and it can also be a .layer file" msgstr "指定应用程序名,也可以是如意玲珑.layer文件" -#: ../apps/ll-cli/src/main.cpp:518 +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display the exported files of installed application" msgstr "显示已安装应用导出的文件" -#: ../apps/ll-cli/src/main.cpp:521 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "用法: ll-cli content [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:522 +#: ../apps/ll-cli/src/main.cpp:534 msgid "Specify the installed application ID" msgstr "指定已安装应用程序名" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:527 +#: ../apps/ll-cli/src/main.cpp:539 msgid "Remove the unused base or runtime" msgstr "移除未使用的最小系统或运行时" -#: ../apps/ll-cli/src/main.cpp:529 +#: ../apps/ll-cli/src/main.cpp:541 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "用法: ll-cli prune [选项]" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:546 msgid "Display the information of installed application" msgstr "显示已安装应用导出的文件" -#: ../apps/ll-cli/src/main.cpp:536 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "用法: ll-cli inspect [选项]" -#: ../apps/ll-cli/src/main.cpp:538 +#: ../apps/ll-cli/src/main.cpp:550 msgid "Specify the process id" msgstr "指定进程id" -#: ../apps/ll-cli/src/main.cpp:547 +#: ../apps/ll-cli/src/main.cpp:559 msgid "Invalid process id" msgstr "无效的进程id" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Invalid pid format" msgstr "无效的pid格式" -#: ../apps/ll-cli/src/main.cpp:560 +#: ../apps/ll-cli/src/main.cpp:572 msgid "Specify the installed app(base or runtime)" msgstr "指定已安装的应用(base或runtime)" -#: ../apps/ll-cli/src/main.cpp:571 +#: ../apps/ll-cli/src/main.cpp:583 msgid "linyaps CLI version " msgstr "如意玲珑CLI版本 " -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:71 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:249 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:135 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:330 msgid "ID" msgstr "ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:72 -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:176 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:136 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:254 msgid "Name" msgstr "名称" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:73 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:137 msgid "Version" msgstr "版本" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:74 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:138 msgid "Channel" msgstr "渠道" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:75 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:139 msgid "Module" msgstr "模块" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:76 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:77 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:141 msgid "Description" msgstr "描述" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:106 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 +msgid "No packages found in the remote repo." +msgstr "远程仓库中未找到软件包" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 +msgid "Repo" +msgstr "仓库" + +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." msgstr "没有正在运行的容器" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:110 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 msgid "App" msgstr "应用" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:111 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:180 msgid "ContainerID" msgstr "容器ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:112 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:181 msgid "Pid" msgstr "进程ID" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:177 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:255 msgid "Url" msgstr "地址" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:178 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:256 msgid "Alias" msgstr "别名" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:179 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:257 msgid "Priority" msgstr "优先级" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:237 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:318 msgid "No apps available for update." msgstr "没有可更新的应用" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:250 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:331 msgid "Installed" msgstr "已安装" -#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:251 +#: ../libs/linglong/src/linglong/cli/cli_printer.cpp:332 msgid "New" msgstr "新版本" -#: ../apps/ll-builder/src/main.cpp:170 +#: ../apps/ll-builder/src/main.cpp:698 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -652,11 +685,11 @@ msgstr "" "如意玲珑构建工具 CLI\n" "一个用于构建如意玲珑应用的命令行工具\n" -#: ../apps/ll-builder/src/main.cpp:175 +#: ../apps/ll-builder/src/main.cpp:703 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "用法: ll-builder [选项] [子命令]" -#: ../apps/ll-builder/src/main.cpp:177 +#: ../apps/ll-builder/src/main.cpp:705 msgid "" "If you found any problems during use\n" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" @@ -664,236 +697,231 @@ msgstr "" "如果在使用过程中遇到任何问题,\n" "您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:199 +#: ../apps/ll-builder/src/main.cpp:729 msgid "Create linyaps build template project" msgstr "创建如意玲珑构建模板" -#: ../apps/ll-builder/src/main.cpp:200 +#: ../apps/ll-builder/src/main.cpp:730 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "用法: ll-builder create [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:201 +#: ../apps/ll-builder/src/main.cpp:731 msgid "Project name" msgstr "项目名称" -#: ../apps/ll-builder/src/main.cpp:213 +#: ../apps/ll-builder/src/main.cpp:739 msgid "Build a linyaps project" msgstr "构建如意玲珑项目" -#: ../apps/ll-builder/src/main.cpp:214 +#: ../apps/ll-builder/src/main.cpp:740 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "用法: ll-builder build [选项] [命令...]" -#: ../apps/ll-builder/src/main.cpp:215 ../apps/ll-builder/src/main.cpp:261 -#: ../apps/ll-builder/src/main.cpp:296 ../apps/ll-builder/src/main.cpp:327 +#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 +#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 msgid "File path of the linglong.yaml" msgstr "linglong.yaml的文件路径" -#: ../apps/ll-builder/src/main.cpp:219 -msgid "Set the build arch" -msgstr "设置构建架构" - -#: ../apps/ll-builder/src/main.cpp:225 ../apps/ll-builder/src/main.cpp:229 +#: ../apps/ll-builder/src/main.cpp:747 msgid "" "Enter the container to execute command instead of building applications" msgstr "进入容器执行命令而不是构建应用" -#: ../apps/ll-builder/src/main.cpp:233 +#: ../apps/ll-builder/src/main.cpp:750 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "仅使用本地文件。这意味着将设置--skip-fetch-source和--skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:238 +#: ../apps/ll-builder/src/main.cpp:755 msgid "Build full develop packages, runtime requires" msgstr "构建完整的开发包,binary是必须的" -#: ../apps/ll-builder/src/main.cpp:240 +#: ../apps/ll-builder/src/main.cpp:759 msgid "Skip fetch sources" msgstr "跳过获取源代码" -#: ../apps/ll-builder/src/main.cpp:241 +#: ../apps/ll-builder/src/main.cpp:762 msgid "Skip pull dependency" msgstr "跳过拉取依赖项" -#: ../apps/ll-builder/src/main.cpp:244 +#: ../apps/ll-builder/src/main.cpp:765 msgid "Skip run container" msgstr "跳过运行容器" -#: ../apps/ll-builder/src/main.cpp:247 +#: ../apps/ll-builder/src/main.cpp:768 msgid "Skip commit build output" msgstr "跳过提交构建输出" -#: ../apps/ll-builder/src/main.cpp:248 +#: ../apps/ll-builder/src/main.cpp:771 msgid "Skip output check" msgstr "跳过输出检查" -#: ../apps/ll-builder/src/main.cpp:251 +#: ../apps/ll-builder/src/main.cpp:774 msgid "Skip strip debug symbols" msgstr "跳过剥离调试符号" -#: ../apps/ll-builder/src/main.cpp:254 +#: ../apps/ll-builder/src/main.cpp:777 msgid "Build in an isolated network environment" msgstr "在隔离网络的环境中构建" -#: ../apps/ll-builder/src/main.cpp:259 +#. add builder run +#: ../apps/ll-builder/src/main.cpp:780 msgid "Run built linyaps app" msgstr "运行构建好的应用程序" -#: ../apps/ll-builder/src/main.cpp:260 +#: ../apps/ll-builder/src/main.cpp:781 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "用法: ll-builder run [选项] [命令...]" -#: ../apps/ll-builder/src/main.cpp:265 -msgid "Only use local files" -msgstr "仅使用本地文件" - -#: ../apps/ll-builder/src/main.cpp:269 +#: ../apps/ll-builder/src/main.cpp:788 msgid "Run specified module. eg: --modules binary,develop" msgstr "运行指定模块。例如: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:275 ../apps/ll-builder/src/main.cpp:279 +#: ../apps/ll-builder/src/main.cpp:794 msgid "Enter the container to execute command instead of running application" msgstr "进入容器执行命令而不是运行应用" -#: ../apps/ll-builder/src/main.cpp:281 +#: ../apps/ll-builder/src/main.cpp:797 msgid "Run in debug mode (enable develop module)" msgstr "在调试模式下运行(启用开发模块)" -#: ../apps/ll-builder/src/main.cpp:283 +#: ../apps/ll-builder/src/main.cpp:799 msgid "List built linyaps app" msgstr "列出已构建的应用程序" -#: ../apps/ll-builder/src/main.cpp:284 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Usage: ll-builder list [OPTIONS]" msgstr "用法: ll-builder list [选项]" -#: ../apps/ll-builder/src/main.cpp:286 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Remove built linyaps app" msgstr "删除已构建的应用程序" -#: ../apps/ll-builder/src/main.cpp:287 +#: ../apps/ll-builder/src/main.cpp:802 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "用法: ll-builder remove [OPTIONS] [APP...]" -#: ../apps/ll-builder/src/main.cpp:293 +#. build export +#: ../apps/ll-builder/src/main.cpp:806 msgid "Export to linyaps layer or uab" msgstr "导出如意玲珑layer或uab" -#: ../apps/ll-builder/src/main.cpp:294 +#: ../apps/ll-builder/src/main.cpp:807 msgid "Usage: ll-builder export [OPTIONS]" msgstr "用法: ll-builder export [选项]" -#: ../apps/ll-builder/src/main.cpp:306 +#: ../apps/ll-builder/src/main.cpp:819 msgid "Uab icon (optional)" msgstr "Uab图标(可选)" -#: ../apps/ll-builder/src/main.cpp:309 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Export uab fully" msgstr "全量导出uab" -#: ../apps/ll-builder/src/main.cpp:310 -msgid "Export to linyaps layer file" -msgstr "导出如意玲珑layer文件" +#: ../apps/ll-builder/src/main.cpp:827 +msgid "Export to linyaps layer file (deprecated)" +msgstr "导出如意玲珑layer文件(已弃用)" -#: ../apps/ll-builder/src/main.cpp:313 +#: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" msgstr "使用自定义的loader" -#: ../apps/ll-builder/src/main.cpp:317 +#: ../apps/ll-builder/src/main.cpp:837 msgid "Don't export the develop module" msgstr "不导出develop模块" -#: ../apps/ll-builder/src/main.cpp:320 +#: ../apps/ll-builder/src/main.cpp:839 msgid "Output file" msgstr "输出文件" -#: ../apps/ll-builder/src/main.cpp:325 +#: ../apps/ll-builder/src/main.cpp:845 msgid "Push linyaps app to remote repo" msgstr "推送如意玲珑应用到远程仓库" -#: ../apps/ll-builder/src/main.cpp:326 +#: ../apps/ll-builder/src/main.cpp:846 msgid "Usage: ll-builder push [OPTIONS]" msgstr "用法: ll-builder push [选项]" -#: ../apps/ll-builder/src/main.cpp:331 +#: ../apps/ll-builder/src/main.cpp:850 msgid "Remote repo url" msgstr "远程仓库URL" -#: ../apps/ll-builder/src/main.cpp:334 +#: ../apps/ll-builder/src/main.cpp:853 msgid "Remote repo name" msgstr "远程仓库名" -#: ../apps/ll-builder/src/main.cpp:337 +#: ../apps/ll-builder/src/main.cpp:856 msgid "Push single module" msgstr "推送单个模块" -#: ../apps/ll-builder/src/main.cpp:342 +#: ../apps/ll-builder/src/main.cpp:860 msgid "Import linyaps layer to build repo" msgstr "导入如意玲珑layer文件到构建仓库" -#: ../apps/ll-builder/src/main.cpp:343 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "用法: ll-builder import [选项] LAYER文件" -#: ../apps/ll-builder/src/main.cpp:344 ../apps/ll-builder/src/main.cpp:363 +#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 msgid "Layer file path" msgstr "layer文件路径" -#: ../apps/ll-builder/src/main.cpp:352 +#: ../apps/ll-builder/src/main.cpp:869 msgid "Import linyaps layer dir to build repo" msgstr "导入如意玲珑layer目录到构建仓库" -#: ../apps/ll-builder/src/main.cpp:354 +#: ../apps/ll-builder/src/main.cpp:871 msgid "Usage: ll-builder import-dir PATH" msgstr "用法: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:355 +#: ../apps/ll-builder/src/main.cpp:872 msgid "Layer dir path" msgstr "layer目录路径" -#: ../apps/ll-builder/src/main.cpp:361 +#. add build extract +#: ../apps/ll-builder/src/main.cpp:877 msgid "Extract linyaps layer to dir" msgstr "将如意玲珑layer文件解压到目录" -#: ../apps/ll-builder/src/main.cpp:362 +#: ../apps/ll-builder/src/main.cpp:878 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "用法: ll-builder extract [选项] LAYER文件 目录" -#: ../apps/ll-builder/src/main.cpp:366 +#: ../apps/ll-builder/src/main.cpp:882 msgid "Destination directory" msgstr "目标目录" #. add build repo -#: ../apps/ll-builder/src/main.cpp:369 +#: ../apps/ll-builder/src/main.cpp:887 msgid "Display and manage repositories" msgstr "显示和管理仓库" -#: ../apps/ll-builder/src/main.cpp:370 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "用法: ll-builder repo [选项] 子命令" -#: ../apps/ll-builder/src/main.cpp:375 +#: ../apps/ll-builder/src/main.cpp:893 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "用法: ll-builder repo add [选项] 名称 URL" -#: ../apps/ll-builder/src/main.cpp:388 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "用法: ll-builder repo remove [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:395 +#: ../apps/ll-builder/src/main.cpp:915 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "用法: ll-builder repo update [选项] 名称 URL" -#: ../apps/ll-builder/src/main.cpp:406 +#: ../apps/ll-builder/src/main.cpp:927 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "用法: ll-builder repo set-default [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:413 +#: ../apps/ll-builder/src/main.cpp:935 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "用法: ll-builder repo show [选项]" -#: ../apps/ll-builder/src/main.cpp:418 +#: ../apps/ll-builder/src/main.cpp:940 msgid "linyaps build tool version " msgstr "如意玲珑构建工具版本" From ef66dce8640ed5ad57c648993921fdc1c2fcc950 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 13 Jun 2025 09:56:46 +0800 Subject: [PATCH 040/366] [linyaps] Updates for project Linyaps (#1216) * i18n: Translate po/en_US.po in pl 96% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 97% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 98% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 98% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 98% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 99% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 100% translated source file: 'po/en_US.po' on 'pl'. * i18n: Translate po/en_US.po in pl 100% translated source file: 'po/en_US.po' on 'pl'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- po/pl.po | 57 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/po/pl.po b/po/pl.po index c88ede485..0ae5718d1 100644 --- a/po/pl.po +++ b/po/pl.po @@ -40,7 +40,7 @@ msgstr "Nie udało się zainstalować" #: ../libs/linglong/src/linglong/cli/cli.cpp:452 msgid "The module could not be found remotely." -msgstr "" +msgstr "Nie znaleziono modułu w zdalnym repozytorium." #: ../libs/linglong/src/linglong/cli/cli.cpp:455 #: ../libs/linglong/src/linglong/cli/cli.cpp:1659 @@ -129,7 +129,7 @@ msgid "" "You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jeśli znajdziesz jakieś problemy, \n" -"Możesz zgłosić błąd do zespołu linyaps w tym projekcie: \n" +"możesz zgłosić błąd do zespołu linyaps pod tym adresem: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags @@ -200,7 +200,7 @@ msgstr "" "Polecenie: ll-cli run [OPCJE] APLIKACJA [KOMENDA...]\n" "\n" "Przykład:\n" -"# uruchom aplikację po appid\n" +"# uruchom aplikację po ID aplikacji\n" "ll-cli run org.deepin.demo\n" "# uruchamiaj komendy wewnątrz kontenera zamiast obok aplikacji\n" "ll-cli run org.deepin.demo bash\n" @@ -260,7 +260,7 @@ msgstr "Polecenie: ll-cli kill [OPCJE] APLIKACJA" #: ../apps/ll-cli/src/main.cpp:292 msgid "Specify the signal to send to the application" -msgstr "Podaj sygnał do wysłania aplikacji" +msgstr "Podaj sygnał jaki wysłać aplikacji" #: ../apps/ll-cli/src/main.cpp:294 msgid "Specify the running application" @@ -292,15 +292,15 @@ msgstr "" "Polecenie: ll-cli install [OPCJE] APLIKACJA\n" "\n" "Przykład:\n" -"# zainstaluj aplikację po appid\n" +"# zainstaluj aplikację po ID aplikacji\n" "ll-cli install org.deepin.demo\n" "# zainstaluj aplikację po warstwie linyaps\n" "ll-cli install demo_0.0.0.1_x86_64_binary.layer\n" "# zainstaluj aplikację linyaps uab\n" "ll-cli install demo_x86_64_0.0.0.1_main.uab\n" -"# zainstaluj moduł po appid\n" +"# zainstaluj moduł po ID aplikacji\n" "ll-cli install org.deepin.demo --module=binary\n" -"# zainstaluj określoną wersję po appid\n" +"# zainstaluj określoną wersję po ID aplikacji\n" "ll-cli install org.deepin.demo/0.0.0.1\n" "# zainstaluj aplikację po szczegółowym odniesieniu\n" "ll-cli install stable:org.deepin.demo/0.0.0.1/x86_64\n" @@ -316,7 +316,7 @@ msgstr "Zainstaluj moduł" #: ../apps/ll-cli/src/main.cpp:328 msgid "Install from a specific repo" -msgstr "" +msgstr "Zainstaluj z wybranego repozytorium" #: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" @@ -389,6 +389,19 @@ msgid "" "# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" +"Polecenie: ll-cli search [OPCJE] SŁOWA KLUCZOWE\n" +"\n" +"Przykład:\n" +"# znajdź zdalnie aplikacje, bazy i środowiska wykonawcze\n" +"ll-cli search org.deepin.demo\n" +"# znajdź zdalnie środowisko wykonawcze\n" +"ll-cli search org.deepin.base --type=runtime\n" +"# znajdź wszystkie aplikacje repozytorium\n" +"ll-cli search .\n" +"# znajdź wszystkie bazy repozytorium\n" +"ll-cli search . --type=base\n" +"# znajdź wszystkie środowiska wykonawcze repozytorium\n" +"ll-cli search . --type=runtime" #: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" @@ -396,23 +409,24 @@ msgstr "Podaj słowa kluczowe" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" -msgstr "" +msgstr "Filtruj wyniki wybranego typu. Na przykład \"runtime\", \"base\", \"app\" lub \"all\"" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" -msgstr "" +msgstr "Podaj repozytorium" #: ../apps/ll-cli/src/main.cpp:403 msgid "Include develop application in result" -msgstr "" +msgstr "Uwzględnij aplikacje w trakcie rozwoju w wynikach wyszukiwania" #: ../apps/ll-cli/src/main.cpp:406 msgid "Show all versions of an application(s), base(s) or runtime(s)" -msgstr "" +msgstr "Pokaż wszystkie wersje aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:411 msgid "List installed application(s), base(s) or runtime(s)" msgstr "" +"Wyświetl listę zainstalowanych aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:414 msgid "" @@ -428,12 +442,25 @@ msgid "" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" +"Polecenie: ll-cli list [OPCJE]\n" +"\n" +"Przykład:\n" +"# pokaż zainstalowane aplikacje, bazy lub środowiska wykonawcze\n" +"ll-cli list\n" +"# pokaż zainstalowane bazy\n" +"ll-cli list --type=base\n" +"# pokaż zainstalowane środowiska wykonawcze\n" +"ll-cli list --type=runtime\n" +"# pokaż najnowsze wersje zainstalowanych aplikacji\n" +"ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" msgstr "" +"Wyświetl listę najnowszych wersji zainstalowanych aplikacji, baz i środowisk" +" wykonawczych" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -620,11 +647,11 @@ msgstr "Opis" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 msgid "No packages found in the remote repo." -msgstr "" +msgstr "Nie znaleziono pakietów w zdalnym repozytorium." #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 msgid "Repo" -msgstr "" +msgstr "Repozytorium" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." @@ -816,7 +843,7 @@ msgstr "Eksportuj uab całkowicie" #: ../apps/ll-builder/src/main.cpp:827 msgid "Export to linyaps layer file (deprecated)" -msgstr "" +msgstr "Eksportuj do pliku warstwy linyaps (brak wsparcia)" #: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" From a6fde49e9310917b436a4911e70f6213f257c13c Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 12 Jun 2025 21:06:50 +0800 Subject: [PATCH 041/366] feat: add sub directory to prevent export file conflicts Add sub directory using item commit to prevent export file conflicts. --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index bfdce8950..f107f5aba 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -2112,6 +2112,10 @@ OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, destination = rootEntriesDir / desktopExportPath; } + if (path == "share/deepin-elf-verify") { + destination = rootEntriesDir / "share/deepin-elf-verify" / item.commit; + } + // 检查源目录是否存在,跳过不存在的目录 exists = std::filesystem::exists(source, ec); if (ec) { From 29be0294c76abfeb3f647f8d9432bfc2df0a5b74 Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 12 Jun 2025 19:34:33 +0800 Subject: [PATCH 042/366] fix: failed to export uab use com.uniontech.foundation Adds support for recognizing com.uniontech.foundation. --- libs/linglong/src/linglong/package/uab_packager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 4a6636bbd..6cadb6ba5 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -402,9 +402,9 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo } const auto &info = *infoRet; - // the kind of old org.deepin.base and org.deepin.foundation is runtime + // the kind of old org.deepin.base,org.deepin.foundation and com.uniontech.foundation is runtime if (info.kind == "base" || info.id == "org.deepin.base" - || info.id == "org.deepin.foundation") { + || info.id == "org.deepin.foundation" || info.id == "com.uniontech.foundation") { base = *it; it = this->layers.erase(it); continue; From 1a0e639a7b13d64d9e13f3afc9386047f07fb0bf Mon Sep 17 00:00:00 2001 From: myml Date: Fri, 13 Jun 2025 17:07:07 +0800 Subject: [PATCH 043/366] fix: update size type to int64_t and initialize struct stat in UABPackager and Builder Changed the size type from int to int64_t in both Builder and UABPackager to ensure proper handling of larger values. Additionally, initialized struct stat variables to improve code clarity and maintainability. --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 2 +- libs/linglong/src/linglong/package/uab_packager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 6e209befc..7672a5d9f 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1371,7 +1371,7 @@ utils::error::Result Builder::commitToLocalRepo() noexcept if (!ret) { return LINGLONG_ERR(ret); } - info.size = static_cast(*ret); + info.size = static_cast(*ret); QFile infoFile{ moduleOutput.filePath("info.json") }; if (!infoFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 6cadb6ba5..195c78cc0 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -702,7 +702,7 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo if (!newSize) { return LINGLONG_ERR(newSize); } - info.size = static_cast(*newSize); + info.size = static_cast(*newSize); stream << nlohmann::json(info).dump(); layerInfoRef.info = info; From 9f7b2406ccaf60cc4a839a3833b43e4fe9d71cda Mon Sep 17 00:00:00 2001 From: dengbo Date: Fri, 13 Jun 2025 18:16:57 +0800 Subject: [PATCH 044/366] chore: revert LINGLONG_EXPORT_VERSION Revert LINGLONG_EXPORT_VERSION and do not fix export dirs. --- configure.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.h.in b/configure.h.in index e8b42a617..18d7b60d9 100644 --- a/configure.h.in +++ b/configure.h.in @@ -25,7 +25,7 @@ // The directory where the package install hooks reside. #define LINGLONG_INSTALL_HOOKS_DIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@/linglong/config.d" -#define LINGLONG_EXPORT_VERSION "1.0.0.2" +#define LINGLONG_EXPORT_VERSION "1.0.0.1" // The package's locale domain. #define PACKAGE_LOCALE_DOMAIN "@GETTEXT_DOMAIN_NAME@" From faf1be9bad3ef26d084e8f8dda8c25ba2bbe3317 Mon Sep 17 00:00:00 2001 From: dengbo Date: Mon, 16 Jun 2025 13:59:27 +0800 Subject: [PATCH 045/366] fix: dock application icons will lose when upgrading components If have a custom desktop export directory, you need to ensure compatibility and export the desktop files to both the old and new directories. --- .../src/linglong/repo/ostree_repo.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index f107f5aba..e16b51c61 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -2102,16 +2102,6 @@ OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, destination = rootEntriesDir / "lib/systemd/user"; } - auto desktopExportPath = std::string{ LINGLONG_EXPORT_PATH } + "/applications"; - - if (path == "share/applications") { - if (desktopExportPath != "share/applications") { - qInfo() << "destination update from " << destination.c_str() << " to " - << QString::fromStdString(rootEntriesDir / desktopExportPath); - } - destination = rootEntriesDir / desktopExportPath; - } - if (path == "share/deepin-elf-verify") { destination = rootEntriesDir / "share/deepin-elf-verify" / item.commit; } @@ -2128,6 +2118,23 @@ OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, if (!ret.has_value()) { return ret; } + + if (path == "share/applications") { + auto desktopExportPath = std::string{ LINGLONG_EXPORT_PATH } + "/applications"; + + // 如果存在自定义的desktop安装路径,则也需要将desktop文件导出到指定目录 + if (desktopExportPath != "share/applications") { + qInfo() << "destination update from " << destination.c_str() << " to " + << QString::fromStdString(rootEntriesDir / desktopExportPath); + + destination = rootEntriesDir / desktopExportPath; + + auto ret = this->exportDir(item.info.id, source, destination, 10); + if (!ret.has_value()) { + return ret; + } + } + } } return LINGLONG_OK; } From 51e373aa38269a8d6606190242b934a5ea72243d Mon Sep 17 00:00:00 2001 From: dengbo Date: Mon, 16 Jun 2025 13:07:10 +0800 Subject: [PATCH 046/366] fix: failed to export XDG_DATA_DIRS enviroment Path "/usr/local/share:/usr/share" must be set when XDG_DATA_DIRS is empty. --- misc/lib/linglong/generate-xdg-data-dirs.sh | 29 +++++++-------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/misc/lib/linglong/generate-xdg-data-dirs.sh b/misc/lib/linglong/generate-xdg-data-dirs.sh index 485bfe0d2..837942ba0 100644 --- a/misc/lib/linglong/generate-xdg-data-dirs.sh +++ b/misc/lib/linglong/generate-xdg-data-dirs.sh @@ -14,9 +14,7 @@ LINGLONG_ROOT="@LINGLONG_ROOT@" LINGLONG_EXPORT_PATH="@LINGLONG_EXPORT_PATH@" -# 规范化 LINGLONG_DATA_DIR:移除末尾可能存在的斜杠 LINGLONG_DATA_DIR="${LINGLONG_ROOT}/entries/share" -LINGLONG_DATA_DIR=${LINGLONG_DATA_DIR%/} # --- 辅助函数:安全地添加路径到 XDG_DATA_DIRS --- # 这个函数会检查路径是否已存在,如果不存在则添加。 @@ -26,9 +24,6 @@ _add_path_to_xdg_data_dirs() { local path_to_add="${1%/}" # 确保要添加的路径没有末尾斜杠 local position="${2:-start}" # 默认添加到开头 - # 确保 XDG_DATA_DIRS 变量已定义,如果未定义则初始化为空字符串 - : "${XDG_DATA_DIRS:=}" - # 检查路径是否已存在于 XDG_DATA_DIRS 中 # 在 XDG_DATA_DIRS 两端加上冒号,以确保精确匹配(无论路径在开头、中间还是结尾) if [[ ":${XDG_DATA_DIRS}:" == *":${path_to_add}:"* ]]; then @@ -36,11 +31,7 @@ _add_path_to_xdg_data_dirs() { return 0 fi - # 如果路径不存在,则根据指定位置添加 - if [[ -z "$XDG_DATA_DIRS" ]]; then - # 如果 XDG_DATA_DIRS 当前为空,直接赋值 - XDG_DATA_DIRS="$path_to_add" - elif [[ "$position" == "start" ]]; then + if [[ "$position" == "start" ]]; then # 添加到开头 XDG_DATA_DIRS="$path_to_add:$XDG_DATA_DIRS" elif [[ "$position" == "end" ]]; then @@ -49,21 +40,19 @@ _add_path_to_xdg_data_dirs() { fi } +# 如果 XDG_DATA_DIRS 为空,则先设置为 /usr/local/share:/usr/share +# 参考: https://specifications.freedesktop.org/basedir-spec/latest +_add_path_to_xdg_data_dirs "/usr/local/share" "end" +_add_path_to_xdg_data_dirs "/usr/share" "end" + +# 将 LINGLONG_DATA_DIR 添加到 XDG_DATA_DIRS 的末尾(如果不存在) +_add_path_to_xdg_data_dirs "$LINGLONG_DATA_DIR" "end" + # 如果有自定义 LINGLONG_EXPORT_PATH(默认为 "share"),将自定义路径添加到 XDG_DATA_DIRS if [ "$LINGLONG_EXPORT_PATH" != "share" ]; then - # 规范化 CUSTOM_DATA_DIR:移除末尾可能存在的斜杠 CUSTOM_DATA_DIR="${LINGLONG_ROOT}/entries/${LINGLONG_EXPORT_PATH}" - CUSTOM_DATA_DIR=${CUSTOM_DATA_DIR%/} _add_path_to_xdg_data_dirs "$CUSTOM_DATA_DIR" "start" fi -# 2. 处理 LINGLONG_DATA_DIR 的添加逻辑 -# 如果 XDG_DATA_DIRS 为空,则先设置为 /usr/local/share:/usr/share, -# 然后再将 LINGLONG_DATA_DIR 添加到末尾。 -: "${XDG_DATA_DIRS:=/usr/local/share:/usr/share}" - -# 然后,将 LINGLONG_DATA_DIR 添加到 XDG_DATA_DIRS 的末尾(如果不存在) -_add_path_to_xdg_data_dirs "$LINGLONG_DATA_DIR" "end" - # --- 清理辅助函数 --- unset -f _add_path_to_xdg_data_dirs From 61d7086dc621534b7fa8e87370f9564266304647 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 16 Jun 2025 16:57:57 +0800 Subject: [PATCH 047/366] chore: start 1.10.0 development Signed-off-by: ComixHe --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e256dde1..d458bb368 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.11.4) project( linglong - VERSION 1.9.0 + VERSION 1.10.0 DESCRIPTION "a container based application package manager for Linux desktop" HOMEPAGE_URL "https://github.com/OpenAtom-Linyaps/linyaps" LANGUAGES CXX C) From 19235c222ba2662f1f9b3c0b9312acead8063be3 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 16 Jun 2025 16:43:58 +0800 Subject: [PATCH 048/366] refacrtor: use our custom container init Signed-off-by: ComixHe --- CMakeLists.txt | 2 +- REUSE.toml | 8 +- apps/dumb-init/CMakeLists.txt | 18 -- apps/dumb-init/src/VERSION.h | 2 - apps/dumb-init/src/dumb-init.c | 335 --------------------------------- apps/ll-init/CMakeLists.txt | 13 ++ apps/ll-init/src/ll-init.cpp | 223 ++++++++++++++++++++++ configure.h.in | 2 +- 8 files changed, 239 insertions(+), 364 deletions(-) delete mode 100644 apps/dumb-init/CMakeLists.txt delete mode 100644 apps/dumb-init/src/VERSION.h delete mode 100644 apps/dumb-init/src/dumb-init.c create mode 100644 apps/ll-init/CMakeLists.txt create mode 100644 apps/ll-init/src/ll-init.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d458bb368..3bc4c81f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -288,7 +288,7 @@ pfl_add_libraries( linglong oci-cfg-generators APPS - dumb-init + ll-init ll-dialog ll-builder ll-cli diff --git a/REUSE.toml b/REUSE.toml index e563847a1..218de29e2 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -142,7 +142,7 @@ SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "CC0-1.0" [[annotations]] -path = "misc/share/linglong/**.json" +path = "misc/share/linglong/**.json" precedence = "aggregate" SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "CC0-1.0" @@ -195,12 +195,6 @@ precedence = "aggregate" SPDX-FileCopyrightText = "AppImageCommunity" SPDX-License-Identifier = "MIT" -[[annotations]] -path = "apps/dumb-init/src/*" -precedence = "aggregate" -SPDX-FileCopyrightText = "Yelp Inc." -SPDX-License-Identifier = "MIT" - [[annotations]] path = "apps/ll-builder-utils/patch/libfuse.patch" precedence = "aggregate" diff --git a/apps/dumb-init/CMakeLists.txt b/apps/dumb-init/CMakeLists.txt deleted file mode 100644 index 1edc4980b..000000000 --- a/apps/dumb-init/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -pfl_add_executable( - SOURCES - ./src/dumb-init.c - OUTPUT_NAME - dumb-init - LIBEXEC - linglong -) - -set(DUMB_INIT_TARGET) - -get_real_target_name(DUMB_INIT_TARGET linglong::dumb-init) - -target_link_options(${DUMB_INIT_TARGET} PRIVATE -static) diff --git a/apps/dumb-init/src/VERSION.h b/apps/dumb-init/src/VERSION.h deleted file mode 100644 index 2a4fbf0d9..000000000 --- a/apps/dumb-init/src/VERSION.h +++ /dev/null @@ -1,2 +0,0 @@ -unsigned char VERSION[] = { 0x31, 0x2e, 0x32, 0x2e, 0x35, 0x0a }; -unsigned int VERSION_len = 6; diff --git a/apps/dumb-init/src/dumb-init.c b/apps/dumb-init/src/dumb-init.c deleted file mode 100644 index 288159903..000000000 --- a/apps/dumb-init/src/dumb-init.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * dumb-init is a simple wrapper program designed to run as PID 1 and pass - * signals to its children. - * - * Usage: - * ./dumb-init python -c 'while True: pass' - * - * To get debug output on stderr, run with '-v'. - */ - -#include "VERSION.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PRINTERR(...) \ - do { \ - fprintf(stderr, "[dumb-init] " __VA_ARGS__); \ - } while (0) - -#define DEBUG(...) \ - do { \ - if (debug) { \ - PRINTERR(__VA_ARGS__); \ - } \ - } while (0) - -// Signals we care about are numbered from 1 to 31, inclusive. -// (32 and above are real-time signals.) -// TODO: this is likely not portable outside of Linux, or on strange architectures -#define MAXSIG 31 - -// Indices are one-indexed (signal 1 is at index 1). Index zero is unused. -// User-specified signal rewriting. -int signal_rewrite[MAXSIG + 1] = { [0 ... MAXSIG] = -1 }; -// One-time ignores due to TTY quirks. 0 = no skip, 1 = skip the next-received signal. -char signal_temporary_ignores[MAXSIG + 1] = { [0 ... MAXSIG] = 0 }; - -pid_t child_pid = -1; -char debug = 0; -char use_setsid = 1; - -int translate_signal(int signum) -{ - if (signum <= 0 || signum > MAXSIG) { - return signum; - } else { - int translated = signal_rewrite[signum]; - if (translated == -1) { - return signum; - } else { - DEBUG("Translating signal %d to %d.\n", signum, translated); - return translated; - } - } -} - -void forward_signal(int signum) -{ - signum = translate_signal(signum); - if (signum != 0) { - kill(use_setsid ? -child_pid : child_pid, signum); - DEBUG("Forwarded signal %d to children.\n", signum); - } else { - DEBUG("Not forwarding signal %d to children (ignored).\n", signum); - } -} - -/* - * The dumb-init signal handler. - * - * The main job of this signal handler is to forward signals along to our child - * process(es). In setsid mode, this means signaling the entire process group - * rooted at our child. In non-setsid mode, this is just signaling the primary - * child. - * - * In most cases, simply proxying the received signal is sufficient. If we - * receive a job control signal, however, we should not only forward it, but - * also sleep dumb-init itself. - * - * This allows users to run foreground processes using dumb-init and to - * control them using normal shell job control features (e.g. Ctrl-Z to - * generate a SIGTSTP and suspend the process). - * - * The libc manual is useful: - * https://www.gnu.org/software/libc/manual/html_node/Job-Control-Signals.html - * - */ -void handle_signal(int signum) -{ - DEBUG("Received signal %d.\n", signum); - - if (signal_temporary_ignores[signum] == 1) { - DEBUG("Ignoring tty hand-off signal %d.\n", signum); - signal_temporary_ignores[signum] = 0; - } else if (signum == SIGCHLD) { - int status, exit_status; - pid_t killed_pid; - while ((killed_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (WIFEXITED(status)) { - exit_status = WEXITSTATUS(status); - DEBUG("A child with PID %d exited with exit status %d.\n", killed_pid, exit_status); - } else { - assert(WIFSIGNALED(status)); - exit_status = 128 + WTERMSIG(status); - DEBUG("A child with PID %d was terminated by signal %d.\n", - killed_pid, - exit_status - 128); - } - - if (killed_pid == child_pid) { - forward_signal(SIGTERM); // send SIGTERM to any remaining children - DEBUG("Child exited with status %d. Goodbye.\n", exit_status); - exit(exit_status); - } - } - } else { - forward_signal(signum); - if (signum == SIGTSTP || signum == SIGTTOU || signum == SIGTTIN) { - DEBUG("Suspending self due to TTY signal.\n"); - kill(getpid(), SIGSTOP); - } - } -} - -void print_help(char *argv[]) -{ - fprintf(stderr, - "dumb-init v%.*s" - "Usage: %s [option] command [[arg] ...]\n" - "\n" - "dumb-init is a simple process supervisor that forwards signals to children.\n" - "It is designed to run as PID1 in minimal container environments.\n" - "\n" - "Optional arguments:\n" - " -c, --single-child Run in single-child mode.\n" - " In this mode, signals are only proxied to the\n" - " direct child and not any of its descendants.\n" - " -r, --rewrite s:r Rewrite received signal s to new signal r before proxying.\n" - " To ignore (not proxy) a signal, rewrite it to 0.\n" - " This option can be specified multiple times.\n" - " -v, --verbose Print debugging information to stderr.\n" - " -h, --help Print this help message and exit.\n" - " -V, --version Print the current version and exit.\n" - "\n" - "Full help is available online at https://github.com/Yelp/dumb-init\n", - VERSION_len, - VERSION, - argv[0]); -} - -void print_rewrite_signum_help() -{ - fprintf(stderr, - "Usage: -r option takes :, where " - "is between 1 and %d.\n" - "This option can be specified multiple times.\n" - "Use --help for full usage.\n", - MAXSIG); - exit(1); -} - -void parse_rewrite_signum(char *arg) -{ - int signum, replacement; - if (sscanf(arg, "%d:%d", &signum, &replacement) == 2 && (signum >= 1 && signum <= MAXSIG) - && (replacement >= 0 && replacement <= MAXSIG)) { - signal_rewrite[signum] = replacement; - } else { - print_rewrite_signum_help(); - } -} - -void set_rewrite_to_sigstop_if_not_defined(int signum) -{ - if (signal_rewrite[signum] == -1) { - signal_rewrite[signum] = SIGSTOP; - } -} - -char **parse_command(int argc, char *argv[]) -{ - int opt; - struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, { "single-child", no_argument, NULL, 'c' }, - { "rewrite", required_argument, NULL, 'r' }, { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 }, - }; - while ((opt = getopt_long(argc, argv, "+hvVcr:", long_options, NULL)) != -1) { - switch (opt) { - case 'h': - print_help(argv); - exit(0); - case 'v': - debug = 1; - break; - case 'V': - fprintf(stderr, "dumb-init v%.*s", VERSION_len, VERSION); - exit(0); - case 'c': - use_setsid = 0; - break; - case 'r': - parse_rewrite_signum(optarg); - break; - default: - exit(1); - } - } - - if (optind >= argc) { - fprintf(stderr, - "Usage: %s [option] program [args]\n" - "Try %s --help for full usage.\n", - argv[0], - argv[0]); - exit(1); - } - - char *debug_env = getenv("DUMB_INIT_DEBUG"); - if (debug_env && strcmp(debug_env, "1") == 0) { - debug = 1; - DEBUG("Running in debug mode.\n"); - } - - char *setsid_env = getenv("DUMB_INIT_SETSID"); - if (setsid_env && strcmp(setsid_env, "0") == 0) { - use_setsid = 0; - DEBUG("Not running in setsid mode.\n"); - } - - if (use_setsid) { - set_rewrite_to_sigstop_if_not_defined(SIGTSTP); - set_rewrite_to_sigstop_if_not_defined(SIGTTOU); - set_rewrite_to_sigstop_if_not_defined(SIGTTIN); - } - - return &argv[optind]; -} - -// A dummy signal handler used for signals we care about. -// On the FreeBSD kernel, ignored signals cannot be waited on by `sigwait` (but -// they can be on Linux). We must provide a dummy handler. -// https://lists.freebsd.org/pipermail/freebsd-ports/2009-October/057340.html -void dummy(int signum) { } - -int main(int argc, char *argv[]) -{ - char **cmd = parse_command(argc, argv); - sigset_t all_signals; - sigfillset(&all_signals); - sigprocmask(SIG_BLOCK, &all_signals, NULL); - - int i = 0; - for (i = 1; i <= MAXSIG; i++) { - signal(i, dummy); - } - - /* - * Detach dumb-init from controlling tty, so that the child's session can - * attach to it instead. - * - * We want the child to be able to be the session leader of the TTY so that - * it can do normal job control. - */ - if (use_setsid) { - if (ioctl(STDIN_FILENO, TIOCNOTTY) == -1) { - DEBUG("Unable to detach from controlling tty (errno=%d %s).\n", errno, strerror(errno)); - } else { - /* - * When the session leader detaches from its controlling tty via - * TIOCNOTTY, the kernel sends SIGHUP and SIGCONT to the process - * group. We need to be careful not to forward these on to the - * dumb-init child so that it doesn't receive a SIGHUP and - * terminate itself (#136). - */ - if (getsid(0) == getpid()) { - DEBUG("Detached from controlling tty, ignoring the first SIGHUP and SIGCONT we " - "receive.\n"); - signal_temporary_ignores[SIGHUP] = 1; - signal_temporary_ignores[SIGCONT] = 1; - } else { - DEBUG("Detached from controlling tty, but was not session leader.\n"); - } - } - } - - child_pid = fork(); - if (child_pid < 0) { - PRINTERR("Unable to fork. Exiting.\n"); - return 1; - } else if (child_pid == 0) { - /* child */ - sigprocmask(SIG_UNBLOCK, &all_signals, NULL); - if (use_setsid) { - if (setsid() == -1) { - PRINTERR("Unable to setsid (errno=%d %s). Exiting.\n", errno, strerror(errno)); - exit(1); - } - - if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) == -1) { - DEBUG("Unable to attach to controlling tty (errno=%d %s).\n", - errno, - strerror(errno)); - } - DEBUG("setsid complete.\n"); - } - execvp(cmd[0], &cmd[0]); - - // if this point is reached, exec failed, so we should exit nonzero - PRINTERR("%s: %s\n", cmd[0], strerror(errno)); - return 2; - } else { - /* parent */ - DEBUG("Child spawned with PID %d.\n", child_pid); - if (chdir("/") == -1) { - DEBUG("Unable to chdir(\"/\") (errno=%d %s)\n", errno, strerror(errno)); - } - for (;;) { - int signum; - sigwait(&all_signals, &signum); - handle_signal(signum); - } - } -} diff --git a/apps/ll-init/CMakeLists.txt b/apps/ll-init/CMakeLists.txt new file mode 100644 index 000000000..737070fcb --- /dev/null +++ b/apps/ll-init/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: LGPL-3.0-or-later + +pfl_add_executable(SOURCES ./src/ll-init.cpp OUTPUT_NAME ll-init LIBEXEC + linglong) + +set(LL_INIT_TARGET) + +get_real_target_name(LL_INIT_TARGET linglong::ll-init) + +target_link_options(${LL_INIT_TARGET} PRIVATE -static -static-libgcc + -static-libstdc++) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp new file mode 100644 index 000000000..5b94a14c2 --- /dev/null +++ b/apps/ll-init/src/ll-init.cpp @@ -0,0 +1,223 @@ +// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +// no need to block these signals +constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS, + SIGTRAP, SIGXCPU, SIGXFSZ, SIGTTIN, SIGTTOU }; + +struct sig_conf +{ + sigset_t cur_set{}; + sigset_t old_set{}; + struct sigaction ttin_action{}; + struct sigaction ttou_action{}; +}; + +namespace { + +void print_sys_error(std::string_view msg) noexcept +{ + std::cerr << msg << ": " << ::strerror(errno) << std::endl; +} + +void print_info(std::string_view msg) noexcept +{ + std::cout << msg << std::endl; +} + +using sig_result = std::variant; + +sig_result handle_signals() noexcept +{ + sig_conf conf; + ::sigfillset(&conf.cur_set); + for (auto signal : unblock_signals) { + ::sigdelset(&conf.cur_set, signal); + } + + auto ret = ::sigprocmask(SIG_SETMASK, &conf.cur_set, &conf.old_set); + if (ret == -1) { + print_sys_error("Failed to set signal mask"); + return -1; + } + + // background process will be suspended by SIGTTIN and SIGTTOU if it try to read/write from/to + // terminal, so we need to ignore these signals. + struct sigaction ignore{}; + ignore.sa_handler = SIG_IGN; + ignore.sa_flags = 0; + + if (::sigaction(SIGTTIN, &ignore, &conf.ttin_action) == -1) { + print_sys_error("Failed to ignore SIGTTIN"); + return -1; + } + + if (::sigaction(SIGTTOU, &ignore, &conf.ttou_action) == -1) { + print_sys_error("Failed to ignore SIGTTOU"); + return -1; + } + + return conf; +} + +std::vector parse_args(int argc, char *argv[]) noexcept +{ + std::vector args; + int idx{ 1 }; + while (idx < argc) { + args.emplace_back(argv[idx++]); + } + + return args; +} + +pid_t run(std::vector args, const sig_conf &conf) noexcept +{ + auto pid = ::fork(); + if (pid == -1) { + print_sys_error("Failed to fork"); + return -1; + } + + if (pid == 0) { + auto ret = ::setpgid(0, 0); + if (ret == -1) { + print_sys_error("Failed to set process group"); + return -1; + } + + ret = ::tcsetpgrp(0, ::getpid()); + if (ret == -1 && errno != ENOTTY) { + print_sys_error("Failed to set terminal process group"); + return -1; + } + + ret = ::sigprocmask(SIG_SETMASK, &conf.old_set, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore signal mask"); + return -1; + } + + ret = ::sigaction(SIGTTIN, &conf.ttin_action, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore SIGTTIN action"); + return -1; + } + + ret = ::sigaction(SIGTTOU, &conf.ttou_action, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore SIGTTOU action"); + return -1; + } + + args.emplace_back(nullptr); + + ::execv(args[0], const_cast(args.data())); + print_sys_error("Failed to exec"); + return -1; + } + + return pid; +} + +std::optional handle_exited_child(pid_t child) noexcept +{ + int status{}; + while (true) { + auto ret = ::waitpid(-1, &status, WNOHANG); + if (ret == 0) { + break; + } + + if (ret == child) { + return status; + } + } + + return std::nullopt; +} +} // namespace + +int main(int argc, char *argv[]) +{ + auto sig_ret = handle_signals(); + if (std::holds_alternative(sig_ret)) { + return std::get(sig_ret); + } + + auto conf = std::get(sig_ret); + + auto ret = ::prctl(PR_SET_CHILD_SUBREAPER, 1); + if (ret == -1) { + print_sys_error("Failed to set child subreaper"); + return -1; + } + + auto args = parse_args(argc, argv); + if (args.empty()) { + print_info("No arguments provided"); + return -1; + } + + auto child = run(args, conf); + if (child == -1) { + return -1; + } + + auto sigfd = ::signalfd(-1, &conf.cur_set, 0); + if (sigfd == -1) { + print_sys_error("Failed to create signalfd"); + return -1; + } + + int child_status{}; + signalfd_siginfo info{}; + while (true) { + std::memset(&info, 0, sizeof(info)); + auto ret = ::read(sigfd, &info, sizeof(info)); + if (ret == -1) { + print_sys_error("Failed to read from signalfd"); + return -1; + } + + if (info.ssi_signo != SIGCHLD) { + ret = ::kill(child, info.ssi_signo); + if (ret == -1) { + auto msg = std::string("Failed to forward signal ") + ::strsignal(info.ssi_signo); + print_sys_error(msg); + } + } + + auto child_exited = handle_exited_child(child); + if (child_exited) { + child_status = *child_exited; + break; + } + } + + ::close(sigfd); + + if (WIFEXITED(child_status)) { + print_info("Child exited with status " + std::to_string(WEXITSTATUS(child_status))); + } else if (WIFSIGNALED(child_status)) { + print_info("Child exited with signal " + std::to_string(WTERMSIG(child_status))); + } else { + print_info("Child exited with unknown status"); + } + + return 0; +} diff --git a/configure.h.in b/configure.h.in index 18d7b60d9..1d7c4c03b 100644 --- a/configure.h.in +++ b/configure.h.in @@ -18,7 +18,7 @@ #define LINGLONG_DEFAULT_OCI_RUNTIME "@LINGLONG_DEFAULT_OCI_RUNTIME@" #define LINGLONG_UAB_DATA_LOCATION "@CMAKE_INSTALL_FULL_LIBDIR@/linglong/builder/uab" #define LINGLONG_BUILDER_HELPER LINGLONG_LIBEXEC_DIR "/builder/helper" -#define LINGLONG_CONTAINER_INIT LINGLONG_LIBEXEC_DIR "/dumb-init" +#define LINGLONG_CONTAINER_INIT LINGLONG_LIBEXEC_DIR "/ll-init" #define LINGLONG_CLIENT_NAME "@LINGLONG_CLI_BIN@" #define LINGLONG_CLIENT_PATH "@CMAKE_INSTALL_FULL_BINDIR@/@LINGLONG_CLI_BIN@" #define LINGLONG_EXPORT_PATH "@LINGLONG_EXPORT_PATH@" From b21f5968e5466040346c52ed8d5bfd20ccf60a16 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Tue, 17 Jun 2025 14:54:09 +0800 Subject: [PATCH 049/366] feat: ll-init waits all child processes in the container Signed-off-by: ComixHe --- apps/ll-init/src/ll-init.cpp | 105 ++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp index 5b94a14c2..df1119922 100644 --- a/apps/ll-init/src/ll-init.cpp +++ b/apps/ll-init/src/ll-init.cpp @@ -9,15 +9,15 @@ #include #include #include -#include #include #include #include // no need to block these signals -constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS, - SIGTRAP, SIGXCPU, SIGXFSZ, SIGTTIN, SIGTTOU }; +constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, + SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ, SIGTTIN, + SIGTTOU, SIGINT, SIGTERM }; struct sig_conf { @@ -25,8 +25,12 @@ struct sig_conf sigset_t old_set{}; struct sigaction ttin_action{}; struct sigaction ttou_action{}; + struct sigaction int_action{}; + struct sigaction term_action{}; }; +sig_atomic_t received_signal{ 0 }; + namespace { void print_sys_error(std::string_view msg) noexcept @@ -36,7 +40,14 @@ void print_sys_error(std::string_view msg) noexcept void print_info(std::string_view msg) noexcept { - std::cout << msg << std::endl; + std::cerr << msg << std::endl; +} + +// ATTENTION: there is a potential risk that the signal will be overridden if multiple signals are +// received at the same time. +void sig_forward(int signo) noexcept +{ + received_signal = signo; } using sig_result = std::variant; @@ -49,6 +60,7 @@ sig_result handle_signals() noexcept ::sigdelset(&conf.cur_set, signal); } + // ignore the rest of the signals auto ret = ::sigprocmask(SIG_SETMASK, &conf.cur_set, &conf.old_set); if (ret == -1) { print_sys_error("Failed to set signal mask"); @@ -71,6 +83,21 @@ sig_result handle_signals() noexcept return -1; } + // we only forward SIGINT, SIGTERM to the child process + struct sigaction forward_action{}; + forward_action.sa_handler = sig_forward; + forward_action.sa_flags = 0; + + if (::sigaction(SIGINT, &forward_action, &conf.int_action) == -1) { + print_sys_error("Failed to forward SIGINT"); + return -1; + } + + if (::sigaction(SIGTERM, &forward_action, &conf.term_action) == -1) { + print_sys_error("Failed to forward SIGTERM"); + return -1; + } + return conf; } @@ -124,32 +151,28 @@ pid_t run(std::vector args, const sig_conf &conf) noexcept return -1; } + ret = ::sigaction(SIGINT, &conf.int_action, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore SIGINT action"); + return -1; + } + + ret = ::sigaction(SIGTERM, &conf.term_action, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore SIGTERM action"); + return -1; + } + args.emplace_back(nullptr); ::execv(args[0], const_cast(args.data())); print_sys_error("Failed to exec"); - return -1; + ::_exit(EXIT_FAILURE); } return pid; } -std::optional handle_exited_child(pid_t child) noexcept -{ - int status{}; - while (true) { - auto ret = ::waitpid(-1, &status, WNOHANG); - if (ret == 0) { - break; - } - - if (ret == child) { - return status; - } - } - - return std::nullopt; -} } // namespace int main(int argc, char *argv[]) @@ -175,48 +198,42 @@ int main(int argc, char *argv[]) auto child = run(args, conf); if (child == -1) { - return -1; - } - - auto sigfd = ::signalfd(-1, &conf.cur_set, 0); - if (sigfd == -1) { - print_sys_error("Failed to create signalfd"); + print_info("Failed to run child process"); return -1; } int child_status{}; - signalfd_siginfo info{}; while (true) { - std::memset(&info, 0, sizeof(info)); - auto ret = ::read(sigfd, &info, sizeof(info)); - if (ret == -1) { - print_sys_error("Failed to read from signalfd"); - return -1; + ret = waitpid(-1, &child_status, 0); + if (ret != -1) { + if (ret == child) { + // if child process already exited, we will send the signal to all processes in this + // pid namespace + child = -1; + } + + continue; } - if (info.ssi_signo != SIGCHLD) { - ret = ::kill(child, info.ssi_signo); + if (errno == EINTR) { + ret = ::kill(child, received_signal); if (ret == -1) { - auto msg = std::string("Failed to forward signal ") + ::strsignal(info.ssi_signo); + auto msg = std::string("Failed to forward signal ") + ::strsignal(received_signal); print_sys_error(msg); } } - auto child_exited = handle_exited_child(child); - if (child_exited) { - child_status = *child_exited; + if (errno == ECHILD) { break; } } - ::close(sigfd); - if (WIFEXITED(child_status)) { - print_info("Child exited with status " + std::to_string(WEXITSTATUS(child_status))); + print_info("Last child exited with status " + std::to_string(WEXITSTATUS(child_status))); } else if (WIFSIGNALED(child_status)) { - print_info("Child exited with signal " + std::to_string(WTERMSIG(child_status))); + print_info("Last child exited with signal " + std::to_string(WTERMSIG(child_status))); } else { - print_info("Child exited with unknown status"); + print_info("Last child exited with unknown status"); } return 0; From b8db0e242b54b3231d2b64fb960a4b96c8f669a0 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Tue, 17 Jun 2025 16:28:34 +0800 Subject: [PATCH 050/366] chore: remove unused file Signed-off-by: ComixHe --- .../linglong/oci-cfg-generators/90_legacy.cpp | 174 ------------------ 1 file changed, 174 deletions(-) delete mode 100644 libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp deleted file mode 100644 index df7466d4a..000000000 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/90_legacy.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "90_legacy.h" - -#include -#include -#include -#include -#include - -namespace linglong::generator { - -bool Legacy::generate(ocppi::runtime::config::types::Config &config) const noexcept -{ - if (config.ociVersion != "1.0.1") { - std::cerr << "OCI version mismatched." << std::endl; - return false; - } - - if (!config.annotations) { - std::cerr << "no annotations." << std::endl; - return false; - } - - auto onlyApp = config.annotations->find("org.deepin.linglong.onlyApp"); - if (onlyApp != config.annotations->end() && onlyApp->second == "true") { - return true; - } - - auto appID = config.annotations->find("org.deepin.linglong.appID"); - if (appID == config.annotations->end()) { - std::cerr << "appID not found." << std::endl; - return false; - } - - if (appID->second.empty()) { - std::cerr << "appID is empty." << std::endl; - return false; - } - - auto process = config.process.value_or(ocppi::runtime::config::types::Process{}); - auto env = process.env.value_or(std::vector{}); - auto mounts = config.mounts.value_or(std::vector{}); - - // FIXME: time zone in the container does not change when the host time zone changes,need to be - // repaired later. - std::multimap roMountMap{ - { "/etc/resolvconf", "/run/host/etc/resolvconf" }, - { "/etc/hosts", "/run/host/etc/hosts" }, - { "/etc/hosts", "/etc/hosts" }, - { "/etc/machine-id", "/run/host/etc/machine-id" }, - { "/etc/machine-id", "/etc/machine-id" }, - { "/etc/ssl/certs", "/run/host/etc/ssl/certs" }, - { "/etc/ssl/certs", "/etc/ssl/certs" }, - { "/var/cache/fontconfig", "/run/host/appearance/fonts-cache" }, - // FIXME: app can not display normally due to missing cjk font cache file,so we need bind - // /var/cache/fontconfig to container. this is just a temporary solution,need to be removed - // when font cache solution implemented - { "/var/cache/fontconfig", "/var/cache/fontconfig" }, - { "/usr/share/fonts", "/usr/share/fonts" }, - { "/usr/lib/locale/", "/usr/lib/locale/" }, - { "/usr/share/themes", "/usr/share/themes" }, - { "/usr/share/icons", "/usr/share/icons" }, - { "/usr/share/zoneinfo", "/usr/share/zoneinfo" }, - { "/etc/resolvconf", "/etc/resolvconf" }, - }; - - std::error_code ec; - for (const auto [source, destination] : roMountMap) { - if (!std::filesystem::exists(source, ec)) { - if (ec) { - std::cerr << "Failed to check existence of " << source << ": " << ec.message() - << std::endl; - continue; - } - - std::cerr << source << " not exists on host." << std::endl; - continue; - } - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::string{ destination }, - .options = string_list{ "ro", "rbind" }, - .source = std::string{ source }, - .type = "bind", - }); - }; - - { - // FIXME: com.360.browser-stable - // 需要一个所有用户都有可读可写权限的目录(/apps-data/private/com.360.browser-stable) - if (::getenv("LINGLONG_SKIP_HOME_GENERATE") == nullptr - && "com.360.browser-stable" == appID->second) { - auto *home = ::getenv("HOME"); - if (home == nullptr) { - std::cerr << "Couldn't get HOME." << std::endl; - return -1; - } - - auto homeDir = std::filesystem::path(home); - if (!std::filesystem::exists(homeDir)) { - std::cerr << "Home " << homeDir << "doesn't exists." << std::endl; - return -1; - } - - std::error_code ec; - std::string app360DataSourcePath = - homeDir / ".linglong" / appID->second / "share" / "appdata"; - - auto appDataDir = std::filesystem::path(app360DataSourcePath); - std::filesystem::create_directories(appDataDir, ec); - if (ec) { - std::cerr << "Check appDataDir failed:" << ec.message() << std::endl; - return -1; - } - - std::string app360DataPath = "/apps-data"; - std::string app360DataDestPath = app360DataPath + "/private/com.360.browser-stable"; - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::move(app360DataPath), - .options = string_list{ " nodev ", " nosuid ", " mode = 777 " }, - .source = "tmpfs", - .type = "tmpfs", - }); - - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = std::move(app360DataDestPath), - .options = string_list{ "rw", "rbind" }, - .source = std::move(app360DataSourcePath), - .type = "bind", - }); - } - } - - // randomize mount points to avoid path dependency. - auto now = std::chrono::system_clock::now(); - auto timestamp = - std::chrono::duration_cast(now.time_since_epoch()).count(); - auto shareDir = std::filesystem::path("/run/linglong/usr/share_" + std::to_string(timestamp)); - // add mount points to XDG_DATA_DIRS - // 查找是否存在XDG_DATA_DIRS开头的环境变量,如果存在追加到尾部,不存在则添加 - auto it = std::find_if(env.begin(), env.end(), [](const std::string &var) { - return var.find("XDG_DATA_DIRS=") == 0; - }); - if (it != env.end()) { - // 如果存在,追加到尾部 - *it += ":" + shareDir.string(); - } else { - // 如果不存在,添加到末尾 - env.push_back("XDG_DATA_DIRS=" + shareDir.string()); - } - - ec.clear(); - // mount for dtk - if (std::filesystem::exists("/usr/share/deepin/distribution.info", ec)) { - mounts.push_back(ocppi::runtime::config::types::Mount{ - .destination = shareDir / "deepin/distribution.info", - .options = string_list{ "ro", "rbind" }, - .source = "/usr/share/deepin/distribution.info", - .type = "bind", - }); - } - - process.env = std::move(env); - config.process = std::move(process); - config.mounts = std::move(mounts); - - return true; -} - -} // namespace linglong::generator From 44bae7483e24e892cc288e3851af15ab68165d3c Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 17 Jun 2025 17:01:36 +0800 Subject: [PATCH 051/366] fix: handle renaming and copying of non-original linyaps files in exportDir Updated the exportDir function to rename source files to include a ".linyaps.original" suffix if they are not already named as such, ensuring proper handling during the export process. This change prevents overwriting original files and maintains compatibility with existing export logic. --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index e16b51c61..bc16f9db7 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1972,7 +1972,8 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, } } - { + // 如果source_path不是linyaps.original文件,则进行重写 + if (source_path.string().rfind(".linyaps.original") == std::string::npos) { auto info = QFileInfo(target_path.c_str()); if ((info.path().contains("share/applications") && info.suffix() == "desktop") || (info.path().contains("share/dbus-1") && info.suffix() == "service") @@ -1987,7 +1988,16 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, QString::number(timestamp), info.suffix()) .toStdString(); - std::filesystem::copy(source_path, sourceNewPath, ec); + + auto originPath = source_path.string() + ".linyaps.original"; + if (!std::filesystem::exists(originPath, ec)) { + std::filesystem::rename(source_path, originPath, ec); + if (ec) { + return LINGLONG_ERR("rename orig path", ec); + } + } + + std::filesystem::copy(originPath, sourceNewPath, ec); if (ec) { return LINGLONG_ERR("copy file failed: " + sourceNewPath, ec); } From e29efbe56937b83ade087661e13d130a6f97dd80 Mon Sep 17 00:00:00 2001 From: ice909 Date: Wed, 18 Jun 2025 11:32:43 +0800 Subject: [PATCH 052/366] fix: prevent crash in prune command after loop exit Added missing return statements after loop.exit() calls in the prune command to prevent function execution from continuing after exit is called. This fixes a crash that occurred when the function continued executing code after requesting the event loop to exit, potentially accessing invalid memory. --- libs/linglong/src/linglong/cli/cli.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index ed6dd5a3f..206b47247 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -1513,11 +1513,13 @@ int Cli::prune([[maybe_unused]] CLI::App *subcommand) if (!ret) { this->printer.printErr(ret.error()); loop.exit(-1); + return; } if (!ret->packages) { this->printer.printErr(LINGLONG_ERRV("No packages to prune.")); loop.exit(0); + return; } this->printer.printPruneResult(*ret->packages); From 49f4b261f5a44840a44dcf1c80f020ffa41378d3 Mon Sep 17 00:00:00 2001 From: myml Date: Wed, 18 Jun 2025 13:32:02 +0800 Subject: [PATCH 053/366] feat: add GitHub Actions workflow for build process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加github action工作流用于构建测试 --- .github/workflows/build.yaml | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 000000000..d41506da1 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,53 @@ +name: build +on: + pull_request_target: + push: + branches: + - master +jobs: + ubuntu2404: + name: ubuntu_24.04 + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake \ + debhelper-compat \ + erofsfuse \ + intltool \ + libcli11-dev \ + libcurl4-openssl-dev \ + libdeflate-dev \ + libelf-dev \ + libexpected-dev \ + libfuse3-dev \ + libglib2.0-dev \ + libgmock-dev \ + libgtest-dev \ + liblz4-dev \ + liblzma-dev \ + libostree-dev \ + libpcre2-dev \ + libselinux1-dev \ + libssl-dev \ + libsystemd-dev \ + libyaml-cpp-dev \ + libzstd-dev \ + nlohmann-json3-dev \ + pkg-config \ + qtbase5-dev \ + qtbase5-private-dev \ + systemd \ + zlib1g-dev + - name: Build + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release \ + -DCPM_LOCAL_PACKAGES_ONLY=ON \ + -DBUILD_SHARED_LIBS=OFF \ + .. + + make -j$(nproc) \ No newline at end of file From 9450698dc9ee64ca6cca85efa37cec37a1a834c5 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:04:18 +0800 Subject: [PATCH 054/366] i18n: Translate po/en_US.po in uk (#1224) --- po/uk.po | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/po/uk.po b/po/uk.po index e4f805a86..a413c9518 100644 --- a/po/uk.po +++ b/po/uk.po @@ -42,7 +42,7 @@ msgstr "Не вдалося встановити" #: ../libs/linglong/src/linglong/cli/cli.cpp:452 msgid "The module could not be found remotely." -msgstr "" +msgstr "Не вдалося знайти модуль віддалено." #: ../libs/linglong/src/linglong/cli/cli.cpp:455 #: ../libs/linglong/src/linglong/cli/cli.cpp:1659 @@ -321,7 +321,7 @@ msgstr "Встановити вказаний модуль" #: ../apps/ll-cli/src/main.cpp:328 msgid "Install from a specific repo" -msgstr "" +msgstr "Встановити з певного сховища" #: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" @@ -393,6 +393,19 @@ msgid "" "# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" +"Користування: ll-cli search [ПАРАМЕТРИ] КЛЮЧОВІ СЛОВА\n" +"\n" +"Приклад:\n" +"# знайти віддалену програму за назвою\n" +"ll-cli search org.deepin.demo\n" +"# знайти віддалене середовище виконання за назвою\n" +"ll-cli search org.deepin.base --type=runtime\n" +"# знайти усі програми у віддаленому сховищі\n" +"ll-cli search .\n" +"# знайти усі основи віддаленого сховища\n" +"ll-cli search . --type=base\n" +"# знайти усі середовища виконання у віддаленому сховищі\n" +"ll-cli search . --type=runtime" #: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" @@ -401,22 +414,24 @@ msgstr "Вказати ключові слова" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" +"Фільтрувати результат за типом. Одне зі значень, «runtime», «base», «app» " +"або «all»" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" -msgstr "" +msgstr "Вказати сховище" #: ../apps/ll-cli/src/main.cpp:403 msgid "Include develop application in result" -msgstr "" +msgstr "Включити до результату програми у розробці" #: ../apps/ll-cli/src/main.cpp:406 msgid "Show all versions of an application(s), base(s) or runtime(s)" -msgstr "" +msgstr "Показати усі версії програм, основ або середовищ виконання" #: ../apps/ll-cli/src/main.cpp:411 msgid "List installed application(s), base(s) or runtime(s)" -msgstr "" +msgstr "Вивести список встановлених програм, основ або середовищ виконання" #: ../apps/ll-cli/src/main.cpp:414 msgid "" @@ -432,12 +447,25 @@ msgid "" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" +"Користування: ll-cli list [ПАРАМЕТРИ]\n" +"\n" +"Приклад:\n" +"# вивести список встановлених програм, основ або середовищ виконання\n" +"ll-cli list\n" +"# вивести список встановлених основ\n" +"ll-cli list --type=base\n" +"# вивести список встановлених середовищ виконання\n" +"ll-cli list --type=runtime\n" +"# вивести список найсвіжіших версій поточних встановлених програм\n" +"ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" msgstr "" +"Вивести список найсвіжіших встановлених програм, основ або середовищ " +"виконання" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -624,11 +652,11 @@ msgstr "Опис" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 msgid "No packages found in the remote repo." -msgstr "" +msgstr "У віддаленому сховищі не виявлено пакунків." #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 msgid "Repo" -msgstr "" +msgstr "Сховище" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." @@ -816,7 +844,7 @@ msgstr "Експортувати uab повністю" #: ../apps/ll-builder/src/main.cpp:827 msgid "Export to linyaps layer file (deprecated)" -msgstr "" +msgstr "Експортувати до файла шару linyaps (застаріле)" #: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" From fb3013521035e8919d0b72e59f2d8e4a0ed6d519 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 19 Jun 2025 16:05:55 +0800 Subject: [PATCH 055/366] fix: Correctly quote arguments in container entrypoint script This change introduces a quoting mechanism (`quoteArg`) that: 1. Encloses each argument in single quotes. 2. Escapes embedded single quotes within an argument (e.g., `it's` becomes `'it'\''s'`). This ensures that arguments are passed to the `exec` command in the entrypoint script as single, intact units, even if they contain spaces or single quotes. Signed-off-by: reddevillg --- .../src/linglong/runtime/container.cpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index 906b9b6fb..c24d4926b 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -190,13 +190,7 @@ utils::error::Result Container::run(const ocppi::runtime::config::types::P }); auto originalArgs = - this->cfg.process->args.value_or(std::vector{ "echo", "'noting to run'" }); - QStringList appArgs; - std::transform(originalArgs.begin(), - originalArgs.end(), - std::back_inserter(appArgs), - QString::fromStdString); - appArgs.prepend("exec"); + this->cfg.process->args.value_or(std::vector{ "echo", "noting to run" }); auto entrypoint = bundle / "entrypoint.sh"; { @@ -211,7 +205,26 @@ utils::error::Result Container::run(const ocppi::runtime::config::types::P ofs << "#!/run/linglong/container-init /bin/bash\n"; ofs << "source /etc/profile\n"; // we need use /etc/profile to generate all needed // environment variables - ofs << appArgs.join(' ').toStdString(); + ofs << "exec "; + + // quote the argument to avoid the space in the argument and use single quote to avoid the + // shell to expand the argument + // example: + // arg: "let's go" + // quoteArg: "'let'\''s go'" + auto quoteArg = [](std::string arg) { + const std::string quotePrefix = "'\\"; + for (auto it = arg.begin(); it != arg.end(); it++) { + if (*it == '\'') { + it = arg.insert(it, quotePrefix.cbegin(), quotePrefix.cend()); + it = arg.insert(it + quotePrefix.size() + 1, 1, '\''); + } + } + return "'" + arg + "'"; + }; + for (auto arg : originalArgs) { + ofs << quoteArg(arg) << " "; + } } std::filesystem::permissions(entrypoint, std::filesystem::perms::owner_all, ec); From fa063275dbdae1d5107a9d3bd4becb7ec90f1075 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 19 Jun 2025 16:28:55 +0800 Subject: [PATCH 056/366] fix: remove unused old config Signed-off-by: reddevillg --- .../linglong/container/config.d/00-id-mapping | 11 -- .../linglong/container/config.d/05-initialize | 11 -- .../container/config.d/10-basics.json | 110 ------------------ .../linglong/container/config.d/20-devices | 11 -- .../linglong/container/config.d/25-host-env | 11 -- .../container/config.d/25-host-rootfs.json | 25 ---- .../container/config.d/25-host-statics.json | 55 --------- .../linglong/container/config.d/30-user-home | 11 -- .../linglong/container/config.d/40-host-ipc | 11 -- .../lib/linglong/container/config.d/90-legacy | 11 -- misc/lib/linglong/container/config.json | 32 ----- 11 files changed, 299 deletions(-) delete mode 100644 misc/lib/linglong/container/config.d/00-id-mapping delete mode 100644 misc/lib/linglong/container/config.d/05-initialize delete mode 100644 misc/lib/linglong/container/config.d/10-basics.json delete mode 100644 misc/lib/linglong/container/config.d/20-devices delete mode 100644 misc/lib/linglong/container/config.d/25-host-env delete mode 100644 misc/lib/linglong/container/config.d/25-host-rootfs.json delete mode 100644 misc/lib/linglong/container/config.d/25-host-statics.json delete mode 100644 misc/lib/linglong/container/config.d/30-user-home delete mode 100644 misc/lib/linglong/container/config.d/40-host-ipc delete mode 100644 misc/lib/linglong/container/config.d/90-legacy delete mode 100644 misc/lib/linglong/container/config.json diff --git a/misc/lib/linglong/container/config.d/00-id-mapping b/misc/lib/linglong/container/config.d/00-id-mapping deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/00-id-mapping +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/05-initialize b/misc/lib/linglong/container/config.d/05-initialize deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/05-initialize +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/10-basics.json b/misc/lib/linglong/container/config.d/10-basics.json deleted file mode 100644 index cb18820cb..000000000 --- a/misc/lib/linglong/container/config.d/10-basics.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "ociVersion": "1.0.1", - "patch": [ - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/sys", - "type": "bind", - "source": "/sys", - "options": ["rbind", "nosuid", "noexec", "nodev"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/proc", - "type": "proc", - "source": "proc" - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/dev", - "type": "tmpfs", - "source": "tmpfs", - "options": ["nosuid", "strictatime", "mode=0755", "size=65536k"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/dev/pts", - "type": "devpts", - "source": "devpts", - "options": [ - "nosuid", - "noexec", - "newinstance", - "ptmxmode=0666", - "mode=0620" - ] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/dev/shm", - "type": "tmpfs", - "source": "shm", - "options": ["nosuid", "noexec", "nodev", "mode=1777"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/dev/mqueue", - "type": "bind", - "source": "/dev/mqueue", - "options": ["rbind", "nosuid", "noexec", "nodev"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/sys/fs/cgroup", - "type": "cgroup", - "source": "cgroup", - "options": ["nosuid", "noexec", "nodev", "relatime", "ro"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/run", - "type": "tmpfs", - "source": "tmpfs", - "options": ["nosuid", "strictatime", "mode=0755", "size=65536k"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/run/udev", - "type": "bind", - "source": "/run/udev", - "options": ["rbind"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/etc/passwd", - "type": "bind", - "source": "/etc/passwd", - "options": ["ro", "rbind"] - } - } - ] -} diff --git a/misc/lib/linglong/container/config.d/20-devices b/misc/lib/linglong/container/config.d/20-devices deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/20-devices +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/25-host-env b/misc/lib/linglong/container/config.d/25-host-env deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/25-host-env +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/25-host-rootfs.json b/misc/lib/linglong/container/config.d/25-host-rootfs.json deleted file mode 100644 index a44f79beb..000000000 --- a/misc/lib/linglong/container/config.d/25-host-rootfs.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "ociVersion": "1.0.1", - "patch": [ - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/run/host", - "type": "tmpfs", - "source": "tmpfs", - "options": ["nodev", "nosuid", "mode=700"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/run/host/rootfs", - "type": "bind", - "source": "/", - "options": ["rbind"] - } - } - ] -} diff --git a/misc/lib/linglong/container/config.d/25-host-statics.json b/misc/lib/linglong/container/config.d/25-host-statics.json deleted file mode 100644 index ae305297b..000000000 --- a/misc/lib/linglong/container/config.d/25-host-statics.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "ociVersion": "1.0.1", - "patch": [ - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/usr/share/fonts", - "type": "bind", - "source": "/usr/share/fonts", - "options": ["rbind", "ro"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/usr/share/icons", - "type": "bind", - "source": "/usr/share/icons", - "options": ["rbind", "ro"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/etc/ssl/certs", - "type": "bind", - "source": "/etc/ssl/certs", - "options": ["rbind", "ro"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/etc/machine-id", - "type": "bind", - "source": "/etc/machine-id", - "options": ["rbind", "ro"] - } - }, - { - "op": "add", - "path": "/mounts/-", - "value": { - "destination": "/usr/share/themes", - "type": "bind", - "source": "/usr/share/themes", - "options": ["rbind", "ro"] - } - } - ] -} diff --git a/misc/lib/linglong/container/config.d/30-user-home b/misc/lib/linglong/container/config.d/30-user-home deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/30-user-home +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/40-host-ipc b/misc/lib/linglong/container/config.d/40-host-ipc deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/40-host-ipc +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.d/90-legacy b/misc/lib/linglong/container/config.d/90-legacy deleted file mode 100644 index 3e575a283..000000000 --- a/misc/lib/linglong/container/config.d/90-legacy +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -echo "This is a placeholder file for using builtin oci configuration generator. -If you want to customize the behavior of current generator, -you could replace this file with a same name executable file." 1>&2 - -exit 255 diff --git a/misc/lib/linglong/container/config.json b/misc/lib/linglong/container/config.json deleted file mode 100644 index 7e9c0a9bf..000000000 --- a/misc/lib/linglong/container/config.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "ociVersion": "1.0.1", - "hostname": "linglong", - "annotations": { - "org.deepin.linglong.appID": "" - }, - "root": { - "path": "" - }, - "linux": { - "namespaces": [ - { - "type": "pid" - }, - { - "type": "mount" - }, - { - "type": "uts" - }, - { - "type": "user" - } - ] - }, - "mounts": [], - "process": { - "env": [], - "cwd": "/", - "args": ["bash"] - } -} From a963f6e81cbc0353b98c4d0cf5402a4d2110057a Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 19 Jun 2025 16:19:42 +0800 Subject: [PATCH 057/366] fix: generate ld cache before builder run Signed-off-by: reddevillg --- .../src/linglong/builder/linglong_builder.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 7672a5d9f..9b5c4a841 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -1854,11 +1854,12 @@ utils::error::Result Builder::run(const QStringList &modules, .type = "bind", }); - QDir appCache = this->workingDir.absoluteFilePath("linglong/cache"); + auto appCache = std::filesystem::path{ workingDir.absolutePath().toStdString() } / "linglong" / "cache"; + std::string ldConfPath = appCache / "ld.so.conf"; applicationMounts.push_back(ocppi::runtime::config::types::Mount{ .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", .options = { { "rbind", "ro" } }, - .source = appCache.absoluteFilePath("ld.so.conf").toStdString(), + .source = ldConfPath, .type = "bind", }); @@ -1874,13 +1875,25 @@ utils::error::Result Builder::run(const QStringList &modules, return LINGLONG_ERR(res); } cfgBuilder.setAppId(curRef->id.toStdString()) - .setAppCache(appCache.absolutePath().toStdString(), false) + .setAppCache(appCache, false) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() .addExtraMounts(applicationMounts) .enableSelfAdjustingMount(); + // write ld.so.conf + std::string triplet = curRef->arch.getTriplet().toStdString(); + std::string ldRawConf = cfgBuilder.ldConf(triplet); + + QFile ldsoconf{ ldConfPath.c_str() }; + if (!ldsoconf.open(QIODevice::WriteOnly)) { + return LINGLONG_ERR(ldsoconf); + } + ldsoconf.write(ldRawConf.c_str()); + // must be closed here, this conf will be used later. + ldsoconf.close(); + if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); @@ -1911,7 +1924,7 @@ utils::error::Result Builder::run(const QStringList &modules, return LINGLONG_ERR(res); } cfgBuilder.setAppId(curRef->id.toStdString()) - .setAppCache(appCache.absolutePath().toStdString()) + .setAppCache(appCache) .enableLDCache() .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) From 3bc48055bcf638672265d35490707ce5c2bdba33 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 19 Jun 2025 18:55:36 +0800 Subject: [PATCH 058/366] fix: fix build failure caused by removed file Signed-off-by: reddevillg --- .../src/linglong/builder/builder_releases.qrc | 1 - misc/CMakeLists.txt | 29 +------------------ 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/libs/linglong/src/linglong/builder/builder_releases.qrc b/libs/linglong/src/linglong/builder/builder_releases.qrc index f970b59e1..333adedd0 100644 --- a/libs/linglong/src/linglong/builder/builder_releases.qrc +++ b/libs/linglong/src/linglong/builder/builder_releases.qrc @@ -13,6 +13,5 @@ SPDX-License-Identifier: LGPL-3.0-or-later ../../../../../misc/libexec/linglong/fetch-file-source ../../../../../misc/libexec/linglong/fetch-archive-source ../../../../../misc/libexec/linglong/app-conf-generator - ../../../../../misc/lib/linglong/container/config.json diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index 5dc59f991..992880fbc 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -25,17 +25,6 @@ configure_files( libexec/linglong/fetch-git-source libexec/linglong/font-cache-generator libexec/linglong/ld-cache-generator - lib/linglong/container/config.d/00-id-mapping - lib/linglong/container/config.d/05-initialize - lib/linglong/container/config.d/10-basics.json - lib/linglong/container/config.d/20-devices - lib/linglong/container/config.d/25-host-env - lib/linglong/container/config.d/25-host-rootfs.json - lib/linglong/container/config.d/25-host-statics.json - lib/linglong/container/config.d/30-user-home - lib/linglong/container/config.d/40-host-ipc - lib/linglong/container/config.d/90-legacy - lib/linglong/container/config.json lib/linglong/container/README.md lib/linglong/generate-xdg-data-dirs.sh lib/systemd/system-environment-generators/61-linglong @@ -108,29 +97,13 @@ install( DESTINATION ${LIBEXEC_LINGLONG_BUILDER_DIR}/helper) # linglong -set(LINGLONG_CONFIG_DIR - ${CMAKE_CURRENT_BINARY_DIR}/lib/linglong/container/config.d) install( PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/lib/linglong/generate-xdg-data-dirs.sh DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/linglong) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib/linglong/container/config.json - ${CMAKE_CURRENT_BINARY_DIR}/lib/linglong/container/README.md +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib/linglong/container/README.md DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/linglong/container) -install( - FILES ${LINGLONG_CONFIG_DIR}/10-basics.json - ${LINGLONG_CONFIG_DIR}/25-host-rootfs.json - ${LINGLONG_CONFIG_DIR}/25-host-statics.json - ${LINGLONG_CONFIG_DIR}/00-id-mapping - ${LINGLONG_CONFIG_DIR}/05-initialize - ${LINGLONG_CONFIG_DIR}/20-devices - ${LINGLONG_CONFIG_DIR}/25-host-env - ${LINGLONG_CONFIG_DIR}/30-user-home - ${LINGLONG_CONFIG_DIR}/40-host-ipc - ${LINGLONG_CONFIG_DIR}/90-legacy - DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/linglong/container/config.d) - # linglong default configuration install(FILES ${CMAKE_CURRENT_LIST_DIR}/share/linglong/config.yaml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/linglong) From 292ff42e92c841c6b07805b3fadf49545936a49f Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 19 Jun 2025 18:14:43 +0800 Subject: [PATCH 059/366] fix: update GitHub Actions workflow to use pull request head This change ensures that the workflow checks out the specific commit from the pull request, improving build accuracy and consistency. --- .github/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d41506da1..d4d04ceb7 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,6 +10,8 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies run: | sudo apt-get update From b22c58959e283ff60e8cf15380ac74dbf1341844 Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 3 Jun 2025 21:12:18 +0800 Subject: [PATCH 060/366] feat: add PackageInfoDisplay schema and update related components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在ll-cli list --json中添加install_time字段,用于表示包的安装时间 --- api/schema/v1.json | 24 ++++ api/schema/v1.yaml | 12 ++ .../src/linglong/api/types/v1/Generators.hpp | 71 +++++++++++ .../linglong/api/types/v1/LinglongAPIV1.hpp | 2 + .../api/types/v1/PackageInfoDisplay.hpp | 119 ++++++++++++++++++ libs/linglong/src/linglong/cli/cli.cpp | 55 +++++--- libs/linglong/src/linglong/cli/cli.h | 5 + .../linglong/src/linglong/cli/cli_printer.cpp | 4 +- libs/linglong/src/linglong/cli/cli_printer.h | 2 +- .../src/linglong/cli/json_printer.cpp | 6 + libs/linglong/src/linglong/cli/json_printer.h | 7 +- libs/linglong/src/linglong/cli/printer.h | 4 +- .../src/linglong/repo/ostree_repo.cpp | 23 +++- libs/linglong/src/linglong/repo/ostree_repo.h | 8 +- .../linglong/src/linglong/repo/repo_cache.cpp | 4 +- 15 files changed, 318 insertions(+), 28 deletions(-) create mode 100644 libs/api/src/linglong/api/types/v1/PackageInfoDisplay.hpp diff --git a/api/schema/v1.json b/api/schema/v1.json index 784e645c1..b2f20cc5e 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -644,6 +644,27 @@ } } }, + "PackageInfoDisplay": { + "title": "PackageInfoDisplay", + "description": "this is the each item output of ll-cli list --json", + "allOf": [ + { + "$ref": "#/$defs/PackageInfoV2" + }, + { + "type": "object", + "requested": [ + "info" + ], + "properties": { + "install_time": { + "type": "integer", + "description": "package install time" + } + } + } + ] + }, "PackageInfoV2": { "title": "PackageInfoV2", "description": "this is the each item output of ll-cli list --json", @@ -1417,6 +1438,9 @@ "PackageManager1Package": { "$ref": "#/$defs/PackageManager1Package" }, + "PackageInfoDisplay": { + "$ref": "#/$defs/PackageInfoDisplay" + }, "PackageInfoV2": { "$ref": "#/$defs/PackageInfoV2" }, diff --git a/api/schema/v1.yaml b/api/schema/v1.yaml index 4176077aa..60311d8e2 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -508,6 +508,18 @@ $defs: module: type: string description: module of package manager + PackageInfoDisplay: + title: PackageInfoDisplay + description: this is the each item output of ll-cli list --json + allOf: + - $ref: '#/$defs/PackageInfoV2' + - type: object + requested: + - info + properties: + install_time: + type: integer + description: package install time PackageInfoV2: title: PackageInfoV2 description: this is the each item output of ll-cli list --json diff --git a/libs/api/src/linglong/api/types/v1/Generators.hpp b/libs/api/src/linglong/api/types/v1/Generators.hpp index 51c7afb83..f89e9630e 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -46,6 +46,7 @@ #include "linglong/api/types/v1/PackageManager1GetRepoInfoResult.hpp" #include "linglong/api/types/v1/PackageManager1GetRepoInfoResultRepoInfo.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" +#include "linglong/api/types/v1/PackageInfoDisplay.hpp" #include "linglong/api/types/v1/PackageInfo.hpp" #include "linglong/api/types/v1/OciConfigurationPatch.hpp" #include "linglong/api/types/v1/LayerInfo.hpp" @@ -164,6 +165,9 @@ void to_json(json & j, const OciConfigurationPatch & x); void from_json(const json & j, PackageInfo & x); void to_json(json & j, const PackageInfo & x); +void from_json(const json & j, PackageInfoDisplay & x); +void to_json(json & j, const PackageInfoDisplay & x); + void from_json(const json & j, PackageInfoV2 & x); void to_json(json & j, const PackageInfoV2 & x); @@ -730,6 +734,69 @@ j["size"] = x.size; j["version"] = x.version; } +inline void from_json(const json & j, PackageInfoDisplay& x) { +x.arch = j.at("arch").get>(); +x.base = j.at("base").get(); +x.channel = j.at("channel").get(); +x.command = get_stack_optional>(j, "command"); +x.compatibleVersion = get_stack_optional(j, "compatible_version"); +x.description = get_stack_optional(j, "description"); +x.extImpl = get_stack_optional(j, "ext_impl"); +x.extensions = get_stack_optional>(j, "extensions"); +x.id = j.at("id").get(); +x.kind = j.at("kind").get(); +x.packageInfoDisplayModule = j.at("module").get(); +x.name = j.at("name").get(); +x.permissions = get_stack_optional(j, "permissions"); +x.runtime = get_stack_optional(j, "runtime"); +x.schemaVersion = j.at("schema_version").get(); +x.size = j.at("size").get(); +x.uuid = get_stack_optional(j, "uuid"); +x.version = j.at("version").get(); +x.installTime = get_stack_optional(j, "install_time"); +} + +inline void to_json(json & j, const PackageInfoDisplay & x) { +j = json::object(); +j["arch"] = x.arch; +j["base"] = x.base; +j["channel"] = x.channel; +if (x.command) { +j["command"] = x.command; +} +if (x.compatibleVersion) { +j["compatible_version"] = x.compatibleVersion; +} +if (x.description) { +j["description"] = x.description; +} +if (x.extImpl) { +j["ext_impl"] = x.extImpl; +} +if (x.extensions) { +j["extensions"] = x.extensions; +} +j["id"] = x.id; +j["kind"] = x.kind; +j["module"] = x.packageInfoDisplayModule; +j["name"] = x.name; +if (x.permissions) { +j["permissions"] = x.permissions; +} +if (x.runtime) { +j["runtime"] = x.runtime; +} +j["schema_version"] = x.schemaVersion; +j["size"] = x.size; +if (x.uuid) { +j["uuid"] = x.uuid; +} +j["version"] = x.version; +if (x.installTime) { +j["install_time"] = x.installTime; +} +} + inline void from_json(const json & j, PackageInfoV2& x) { x.arch = j.at("arch").get>(); x.base = j.at("base").get(); @@ -1169,6 +1236,7 @@ x.interactionRequest = get_stack_optional(j, "InteractionReq x.layerInfo = get_stack_optional(j, "LayerInfo"); x.ociConfigurationPatch = get_stack_optional(j, "OCIConfigurationPatch"); x.packageInfo = get_stack_optional(j, "PackageInfo"); +x.packageInfoDisplay = get_stack_optional(j, "PackageInfoDisplay"); x.packageInfoV2 = get_stack_optional(j, "PackageInfoV2"); x.packageManager1GetRepoInfoResult = get_stack_optional(j, "PackageManager1GetRepoInfoResult"); x.packageManager1InstallLayerFDResult = get_stack_optional(j, "PackageManager1InstallLayerFDResult"); @@ -1260,6 +1328,9 @@ j["OCIConfigurationPatch"] = x.ociConfigurationPatch; if (x.packageInfo) { j["PackageInfo"] = x.packageInfo; } +if (x.packageInfoDisplay) { +j["PackageInfoDisplay"] = x.packageInfoDisplay; +} if (x.packageInfoV2) { j["PackageInfoV2"] = x.packageInfoV2; } diff --git a/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp b/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp index c5b26384c..5109370ba 100644 --- a/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp +++ b/libs/api/src/linglong/api/types/v1/LinglongAPIV1.hpp @@ -37,6 +37,7 @@ #include "linglong/api/types/v1/LayerInfo.hpp" #include "linglong/api/types/v1/OciConfigurationPatch.hpp" #include "linglong/api/types/v1/PackageInfo.hpp" +#include "linglong/api/types/v1/PackageInfoDisplay.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" #include "linglong/api/types/v1/PackageManager1GetRepoInfoResult.hpp" #include "linglong/api/types/v1/PackageManager1InstallParameters.hpp" @@ -107,6 +108,7 @@ std::optional interactionRequest; std::optional layerInfo; std::optional ociConfigurationPatch; std::optional packageInfo; +std::optional packageInfoDisplay; std::optional packageInfoV2; std::optional packageManager1GetRepoInfoResult; std::optional packageManager1InstallLayerFDResult; diff --git a/libs/api/src/linglong/api/types/v1/PackageInfoDisplay.hpp b/libs/api/src/linglong/api/types/v1/PackageInfoDisplay.hpp new file mode 100644 index 000000000..eaa23fcdb --- /dev/null +++ b/libs/api/src/linglong/api/types/v1/PackageInfoDisplay.hpp @@ -0,0 +1,119 @@ +// 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 +// +// PackageInfoDisplay.hpp data = nlohmann::json::parse(jsonString); + +#pragma once + +#include +#include +#include "linglong/api/types/v1/helper.hpp" + +#include "linglong/api/types/v1/ExtensionImpl.hpp" +#include "linglong/api/types/v1/ExtensionDefine.hpp" +#include "linglong/api/types/v1/ApplicationConfigurationPermissions.hpp" + +namespace linglong { +namespace api { +namespace types { +namespace v1 { +/** +* this is the each item output of ll-cli list --json +* +* package info of package manager search +*/ + +using nlohmann::json; + +/** +* this is the each item output of ll-cli list --json +* +* package info of package manager search +*/ +struct PackageInfoDisplay { +/** +* arch of package info +*/ +std::vector arch; +/** +* base of package info +*/ +std::string base; +/** +* channel of package info +*/ +std::string channel; +/** +* command of package info +*/ +std::optional> command; +/** +* record linyaps package is compatible with linyaps component version +*/ +std::optional compatibleVersion; +/** +* description of package info +*/ +std::optional description; +std::optional extImpl; +/** +* description of extension +*/ +std::optional> extensions; +/** +* id of package info +*/ +std::string id; +/** +* kind of package info +*/ +std::string kind; +/** +* module of package info +*/ +std::string packageInfoDisplayModule; +/** +* name of package info +*/ +std::string name; +std::optional permissions; +/** +* runtime of package info +*/ +std::optional runtime; +/** +* version of 'PackageInfo' +*/ +std::string schemaVersion; +/** +* Uncompressed package size in bytes +*/ +int64_t size; +/** +* this property is only used for app which instead from UAB and it should be null in other +* conditions. +*/ +std::optional uuid; +/** +* version of package info +*/ +std::string version; +/** +* package install time +*/ +std::optional installTime; +}; +} +} +} +} + +// clang-format on diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 206b47247..c56123e3f 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -10,6 +10,8 @@ #include "linglong/api/dbus/v1/dbus_peer.h" #include "linglong/api/types/v1/InteractionReply.hpp" #include "linglong/api/types/v1/InteractionRequest.hpp" +#include "linglong/api/types/v1/LinglongAPIV1.hpp" +#include "linglong/api/types/v1/PackageInfoDisplay.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" #include "linglong/api/types/v1/PackageManager1InstallParameters.hpp" #include "linglong/api/types/v1/PackageManager1JobInfo.hpp" @@ -19,6 +21,7 @@ #include "linglong/api/types/v1/PackageManager1SearchParameters.hpp" #include "linglong/api/types/v1/PackageManager1SearchResult.hpp" #include "linglong/api/types/v1/PackageManager1UninstallParameters.hpp" +#include "linglong/api/types/v1/RepositoryCacheLayersItem.hpp" #include "linglong/api/types/v1/State.hpp" #include "linglong/api/types/v1/SubState.hpp" #include "linglong/api/types/v1/UpgradeListResult.hpp" @@ -39,7 +42,10 @@ #include "ocppi/runtime/Signal.hpp" #include "ocppi/types/ContainerListItem.hpp" +#include +#include #include +#include #include #include @@ -48,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -1699,22 +1706,28 @@ int Cli::uninstall([[maybe_unused]] CLI::App *subcommand) } int Cli::list([[maybe_unused]] CLI::App *subcommand) + { if (!options.showUpgradeList) { - auto pkgs = this->repository.listLocal(); - if (!pkgs) { - this->printer.printErr(pkgs.error()); + auto items = this->repository.listLayerItem(); + if (!items) { + this->printer.printErr(items.error()); return -1; } - - auto localPkgs = std::map>{ - { "local", std::move(pkgs).value() } - }; - + std::vector list; + for (const auto &item : *items) { + nlohmann::json json = item.info; + auto m = json.get(); + auto t = this->repository.getLayerCreateTime(item); + if (t.has_value()) { + m.installTime = *t; + } + list.push_back(std::move(m)); + } if (!options.type.empty()) { - filterPackageInfosByType(localPkgs, options.type); + filterPackageInfosByType(list, options.type); } - this->printer.printPackages(localPkgs["local"]); + this->printer.printPackages(list); return 0; } @@ -2251,6 +2264,20 @@ void Cli::filterPackageInfosByType( list = std::move(filtered); } +void Cli::filterPackageInfosByType(std::vector &list, + const std::string &type) +{ + if (type == "all") { + return; + } + list.erase(std::remove_if(list.begin(), + list.end(), + [&type](const api::types::v1::PackageInfoDisplay &pkg) { + return pkg.kind == type; + }), + list.end()); +} + utils::error::Result Cli::filterPackageInfosByVersion( std::map> &list) noexcept { @@ -2390,11 +2417,9 @@ Cli::RequestDirectories(const api::types::v1::PackageInfoV2 &info) noexcept ::close(fd); }); - struct flock lock{ - .l_type = F_WRLCK, - .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0, + struct flock lock + { + .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, }; // all later processes should be blocked diff --git a/libs/linglong/src/linglong/cli/cli.h b/libs/linglong/src/linglong/cli/cli.h index c6b92e7de..bb57528e0 100644 --- a/libs/linglong/src/linglong/cli/cli.h +++ b/libs/linglong/src/linglong/cli/cli.h @@ -9,6 +9,8 @@ #include "linglong/api/dbus/v1/package_manager.h" #include "linglong/api/dbus/v1/task.h" #include "linglong/api/types/v1/CommonOptions.hpp" +#include "linglong/api/types/v1/PackageInfoDisplay.hpp" +#include "linglong/api/types/v1/RepositoryCacheLayersItem.hpp" #include "linglong/cli/interactive_notifier.h" #include "linglong/cli/printer.h" #include "linglong/repo/ostree_repo.h" @@ -99,9 +101,12 @@ class Cli : public QObject filePathMapping(const std::vector &command) const noexcept; static std::string mappingFile(const std::filesystem::path &file) noexcept; static std::string mappingUrl(std::string_view url) noexcept; + static void filterPackageInfosByType( std::map> &list, const std::string &type) noexcept; + static void filterPackageInfosByType(std::vector &list, + const std::string &type); static utils::error::Result filterPackageInfosByVersion( std::map> &list) noexcept; void printProgress() noexcept; diff --git a/libs/linglong/src/linglong/cli/cli_printer.cpp b/libs/linglong/src/linglong/cli/cli_printer.cpp index a88b78ac7..33fc44ee6 100644 --- a/libs/linglong/src/linglong/cli/cli_printer.cpp +++ b/libs/linglong/src/linglong/cli/cli_printer.cpp @@ -67,7 +67,7 @@ std::string adjustDisplayWidth(const QString &str, int targetWidth) return (str + QString(targetWidth - currentWidth, QChar(' '))).toStdString(); } -void CLIPrinter::printPackages(const std::vector &list) +void CLIPrinter::printPackages(const std::vector &list) { std::cout << "\033[38;5;214m" << std::left << adjustDisplayWidth(qUtf8Printable(_("ID")), 43) << adjustDisplayWidth(qUtf8Printable(_("Name")), 33) @@ -96,7 +96,7 @@ void CLIPrinter::printPackages(const std::vector auto nameOffset = nameStr.size() - nameWcswidth; std::cout << std::setw(43) << info.id + " " << std::setw(33 + nameOffset) << nameStr + " " << std::setw(16) << info.version + " " << std::setw(16) << info.channel + " " - << std::setw(12) << info.packageInfoV2Module + " " + << std::setw(12) << info.packageInfoDisplayModule + " " << simpleDescription.toStdString() << std::endl; } } diff --git a/libs/linglong/src/linglong/cli/cli_printer.h b/libs/linglong/src/linglong/cli/cli_printer.h index eced97541..b4781be34 100644 --- a/libs/linglong/src/linglong/cli/cli_printer.h +++ b/libs/linglong/src/linglong/cli/cli_printer.h @@ -35,7 +35,7 @@ class CLIPrinter : public Printer void printErr(const utils::error::Error &) override; void printPackage(const api::types::v1::PackageInfoV2 &) override; - void printPackages(const std::vector &) override; + void printPackages(const std::vector &) override; void printSearchResult(std::map>) override; void printPruneResult(const std::vector &list) override; diff --git a/libs/linglong/src/linglong/cli/json_printer.cpp b/libs/linglong/src/linglong/cli/json_printer.cpp index c829cc8fc..4687fba78 100644 --- a/libs/linglong/src/linglong/cli/json_printer.cpp +++ b/libs/linglong/src/linglong/cli/json_printer.cpp @@ -7,6 +7,7 @@ #include "linglong/cli/json_printer.h" #include "linglong/api/types/v1/Generators.hpp" +#include "linglong/cli/cli.h" #include "linglong/package/version.h" #include @@ -28,6 +29,11 @@ void JSONPrinter::printPackage(const api::types::v1::PackageInfoV2 &info) std::cout << nlohmann::json(info).dump() << std::endl; } +void JSONPrinter::printPackages(const std::vector &list) +{ + std::cout << nlohmann::json(list).dump() << std::endl; +} + void JSONPrinter::printPackages(const std::vector &list) { std::cout << nlohmann::json(list).dump() << std::endl; diff --git a/libs/linglong/src/linglong/cli/json_printer.h b/libs/linglong/src/linglong/cli/json_printer.h index cb367a4fb..5998ddc08 100644 --- a/libs/linglong/src/linglong/cli/json_printer.h +++ b/libs/linglong/src/linglong/cli/json_printer.h @@ -6,16 +6,21 @@ #pragma once +#include "linglong/api/types/v1/PackageInfoV2.hpp" +#include "linglong/cli/cli.h" #include "linglong/cli/printer.h" namespace linglong::cli { class JSONPrinter : public Printer { +private: + void printPackages(const std::vector &); + public: void printErr(const utils::error::Error &) override; void printPackage(const api::types::v1::PackageInfoV2 &) override; - void printPackages(const std::vector &) override; + void printPackages(const std::vector &) override; void printSearchResult(std::map>) override; void printPruneResult(const std::vector &) override; diff --git a/libs/linglong/src/linglong/cli/printer.h b/libs/linglong/src/linglong/cli/printer.h index 69828398a..cc9ad6340 100644 --- a/libs/linglong/src/linglong/cli/printer.h +++ b/libs/linglong/src/linglong/cli/printer.h @@ -10,11 +10,13 @@ #include "linglong/api/types/v1/CommonResult.hpp" #include "linglong/api/types/v1/InspectResult.hpp" #include "linglong/api/types/v1/LayerInfo.hpp" +#include "linglong/api/types/v1/PackageInfoDisplay.hpp" #include "linglong/api/types/v1/PackageInfoV2.hpp" #include "linglong/api/types/v1/RepoConfigV2.hpp" #include "linglong/api/types/v1/State.hpp" #include "linglong/api/types/v1/SubState.hpp" #include "linglong/api/types/v1/UpgradeListResult.hpp" +#include "linglong/cli/cli.h" #include "linglong/utils/error/error.h" namespace linglong::cli { @@ -75,7 +77,7 @@ class Printer virtual void printErr(const utils::error::Error &) = 0; virtual void printPackage(const api::types::v1::PackageInfoV2 &) = 0; - virtual void printPackages(const std::vector &) = 0; + virtual void printPackages(const std::vector &) = 0; virtual void printSearchResult(std::map>) = 0; virtual void printPruneResult(const std::vector &) = 0; diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index bc16f9db7..4c1eee26a 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1548,12 +1549,7 @@ utils::error::Result> OSTreeRepo::listLocal() const noexcept { std::vector pkgInfos; - - QDir layersDir = this->repoDir.absoluteFilePath("layers"); - Q_ASSERT(layersDir.exists()); - auto items = this->cache->queryExistingLayerItem(); - pkgInfos.reserve(items.size()); for (const auto &item : items) { if (item.deleted && item.deleted.value()) { continue; @@ -1565,6 +1561,23 @@ OSTreeRepo::listLocal() const noexcept return pkgInfos; } +utils::error::Result> +OSTreeRepo::listLayerItem() const noexcept +{ + return this->cache->queryExistingLayerItem(); +} + +utils::error::Result +OSTreeRepo::getLayerCreateTime(const api::types::v1::RepositoryCacheLayersItem &item) const noexcept +{ + LINGLONG_TRACE("get install time"); + auto dir = this->getLayerDir(item); + if (!dir.has_value()) { + return LINGLONG_ERR("get layer dir", dir); + } + return QFileInfo(dir->absolutePath()).birthTime().toSecsSinceEpoch(); +} + // Note: Since version 1.7.0, multiple versions are no longer supported, so there will be multiple // versions locally. In some places, we need to list the latest version of each package. utils::error::Result> diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index 337ced2b2..126ab6c1d 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -6,6 +6,7 @@ #pragma once +#include "linglong/api/types/v1/PackageInfoV2.hpp" #include "linglong/api/types/v1/Repo.hpp" #include "linglong/api/types/v1/RepoConfigV2.hpp" #include "linglong/package/fuzzy_reference.h" @@ -40,6 +41,7 @@ struct getRemoteReferenceByPriorityOption }; class OSTreeRepo : public QObject + { Q_OBJECT public: @@ -102,9 +104,13 @@ class OSTreeRepo : public QObject utils::error::Result> listRemote(const package::FuzzyReference &fuzzyRef, const std::optional &repo = std::nullopt) const noexcept; + + utils::error::Result> + listLayerItem() const noexcept; [[nodiscard]] utils::error::Result> listLocalBy(const linglong::repo::repoCacheQuery &query) const noexcept; - + utils::error::Result + getLayerCreateTime(const api::types::v1::RepositoryCacheLayersItem &item) const noexcept; utils::error::Result remove(const package::Reference &ref, const std::string &module = "binary", diff --git a/libs/linglong/src/linglong/repo/repo_cache.cpp b/libs/linglong/src/linglong/repo/repo_cache.cpp index 3069a69e4..14f03edc6 100644 --- a/libs/linglong/src/linglong/repo/repo_cache.cpp +++ b/libs/linglong/src/linglong/repo/repo_cache.cpp @@ -60,7 +60,7 @@ RepoCache::create(const std::filesystem::path &cacheFile, repoCache->cache = std::move(result).value(); if (repoCache->cache.version != enableMaker::cacheFileVersion || repoCache->cache.llVersion != LINGLONG_VERSION) { - std::cout << "The existing cache is outdated, rebuild cache..." << std::endl; + std::cerr << "The existing cache is outdated, rebuild cache..." << std::endl; auto ret = repoCache->rebuildCache(repoConfig, repo); if (!ret) { return LINGLONG_ERR(ret); @@ -135,7 +135,7 @@ utils::error::Result RepoCache::rebuildCache(const api::types::v1::RepoCon // FIXME: ll-cli may initialize repo, it can make states.json own by root if (getuid() == 0) { - qWarning() << "Rebuild the cache by root, skip to write data to states.json"; + std::cerr << "Rebuild the cache by root, skip to write data to states.json"; return LINGLONG_OK; } From 5401be148fb4d6d2af7c57e95c90725b8605211e Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 20 Jun 2025 17:44:15 +0800 Subject: [PATCH 061/366] fix: correctly pass argument by vector use quoteBashArg if run with bash -c or write to bash script. Signed-off-by: reddevillg --- .../package_manager/package_manager.cpp | 18 ++++++++---- .../src/linglong/runtime/container.cpp | 18 ++---------- libs/utils/src/linglong/utils/bash_quote.h | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 libs/utils/src/linglong/utils/bash_quote.h diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 635bf254c..6fe430b59 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -23,6 +23,7 @@ #include "linglong/repo/config.h" #include "linglong/repo/ostree_repo.h" #include "linglong/runtime/run_context.h" +#include "linglong/utils/bash_quote.h" #include "linglong/utils/command/env.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" @@ -2402,15 +2403,22 @@ utils::error::Result PackageManager::generateCache(const package::Referenc if (!currentArch) { return LINGLONG_ERR(currentArch); } - const auto ldGenerateCmd = "/sbin/ldconfig -X -C " + appCacheDest + "/ld.so.cache"; + auto ldGenerateCmd = + std::vector{ "/sbin/ldconfig", "-X", "-C", appCacheDest + "/ld.so.cache" }; #ifdef LINGLONG_FONT_CACHE_GENERATOR // Usage: font-cache-generator [cacheRoot] [id] - const std::string fontGenerateCmd = - fontGenerator + " " + appCacheDest + " " + ref.id.toStdString(); - process.args = std::vector{ "bash", "-c", ldGenerateCmd + ";" + fontGenerateCmd }; + const std::string fontGenerateCmd = utils::quoteBashArg(fontGenerator) + " " + + utils::quoteBashArg(appCacheDest) + " " + utils::quoteBashArg(ref.id.toStdString()); + auto ldGenerateCmdstr; + for (const auto &c : ldGenerateCmd) { + ldGenerateCmdstr.append(utils::quoteBashArg(c)); + ldGenerateCmdstr.append(" "); + } + process.args = + std::vector{ "bash", "-c", ldGenerateCmdstr + ";" + fontGenerateCmd }; #endif - process.args = std::vector{ ldGenerateCmd }; + process.args = std::move(ldGenerateCmd); // Note: XDG_RUNTIME_DIR is not set in PM, the ll-box will finally fallback to /run/ll-box. // But PM has no write permission in that place, so we should specific the root path. diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index c24d4926b..296de5579 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -7,6 +7,7 @@ #include "linglong/runtime/container.h" #include "configure.h" +#include "linglong/utils/bash_quote.h" #include "linglong/utils/finally/finally.h" #include "ocppi/runtime/RunOption.hpp" #include "ocppi/runtime/config/types/Generators.hpp" @@ -207,23 +208,8 @@ utils::error::Result Container::run(const ocppi::runtime::config::types::P // environment variables ofs << "exec "; - // quote the argument to avoid the space in the argument and use single quote to avoid the - // shell to expand the argument - // example: - // arg: "let's go" - // quoteArg: "'let'\''s go'" - auto quoteArg = [](std::string arg) { - const std::string quotePrefix = "'\\"; - for (auto it = arg.begin(); it != arg.end(); it++) { - if (*it == '\'') { - it = arg.insert(it, quotePrefix.cbegin(), quotePrefix.cend()); - it = arg.insert(it + quotePrefix.size() + 1, 1, '\''); - } - } - return "'" + arg + "'"; - }; for (auto arg : originalArgs) { - ofs << quoteArg(arg) << " "; + ofs << utils::quoteBashArg(arg) << " "; } } diff --git a/libs/utils/src/linglong/utils/bash_quote.h b/libs/utils/src/linglong/utils/bash_quote.h new file mode 100644 index 000000000..8c0a605b1 --- /dev/null +++ b/libs/utils/src/linglong/utils/bash_quote.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include + +namespace linglong::utils { + +// quote the bash argument to avoid the space in the argument +// and use single quote to avoid the shell to expand the argument +// example: +// arg: "let's go" +// quoted arg: "'let'\''s go'" +static inline std::string quoteBashArg(std::string arg) noexcept +{ + const std::string quotePrefix = "'\\"; + for (auto it = arg.begin(); it != arg.end(); it++) { + if (*it == '\'') { + it = arg.insert(it, quotePrefix.cbegin(), quotePrefix.cend()); + it = arg.insert(it + quotePrefix.size() + 1, 1, '\''); + } + } + return "'" + arg + "'"; +} + +} // namespace linglong::utils \ No newline at end of file From 23e4f9bfebd804b8d45d606250e57a0f867a76b8 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 20 Jun 2025 18:04:11 +0800 Subject: [PATCH 062/366] fix: fix compiler error when use CPM nlohmann Signed-off-by: reddevillg --- libs/linglong/src/linglong/cli/cli.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index c56123e3f..a3044eb6f 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -42,10 +42,7 @@ #include "ocppi/runtime/Signal.hpp" #include "ocppi/types/ContainerListItem.hpp" -#include -#include #include -#include #include #include From 8a42aaa2cd553bbb3dae70feea4626aa5595b944 Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Sat, 21 Jun 2025 21:50:13 +0300 Subject: [PATCH 063/366] fix: don't hardcode libexec dir Use `CMAKE_INSTALL_FULL_LIBEXECDIR` so that setting `CMAKE_INSTALL_LIBEXECDIR` changes `LIBEXEC_LINGLONG_DIR` accordingly. --- misc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index 992880fbc..c9b70bd5a 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -69,7 +69,7 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/dbus-1/system-services DESTINATION ${DBUS_SYSTEM_BUS_DIR}) # libexec -set(LIBEXEC_LINGLONG_DIR ${CMAKE_INSTALL_PREFIX}/libexec/linglong) +set(LIBEXEC_LINGLONG_DIR ${CMAKE_INSTALL_FULL_LIBEXECDIR}/linglong) install( PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libexec/linglong/app-conf-generator ${CMAKE_CURRENT_BINARY_DIR}/libexec/linglong/ld-cache-generator From 6cfef1d11735b8c75a0103fef9be3ab1bb749235 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 23 Jun 2025 10:15:13 +0800 Subject: [PATCH 064/366] fix: compiling error at UOS 20 and anolisOS missing unistd.h Signed-off-by: ComixHe --- apps/ll-init/src/ll-init.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp index df1119922..1594e9aae 100644 --- a/apps/ll-init/src/ll-init.cpp +++ b/apps/ll-init/src/ll-init.cpp @@ -13,6 +13,7 @@ #include #include +#include // no need to block these signals constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, From 6d5c1f14044589cf0aee11bd1b046a30d8a20964 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 23 Jun 2025 11:56:49 +0800 Subject: [PATCH 065/366] refactor: some scripts that export env 'XDG_DATA_DIRS' Signed-off-by: ComixHe --- misc/lib/linglong/generate-xdg-data-dirs.sh | 86 +++++++++++-------- .../system-environment-generators/61-linglong | 18 +++- misc/script/linglong.sh | 13 ++- 3 files changed, 72 insertions(+), 45 deletions(-) mode change 100644 => 100755 misc/lib/linglong/generate-xdg-data-dirs.sh diff --git a/misc/lib/linglong/generate-xdg-data-dirs.sh b/misc/lib/linglong/generate-xdg-data-dirs.sh old mode 100644 new mode 100755 index 837942ba0..2eb1eb8cd --- a/misc/lib/linglong/generate-xdg-data-dirs.sh +++ b/misc/lib/linglong/generate-xdg-data-dirs.sh @@ -1,7 +1,11 @@ -# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +#!/usr/bin/env sh + +# SPDX-FileCopyrightText: 2023-2024 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later +# shellcheck shell=sh + # NOTE: # Software installed by linglong (or linypas) are generally GUI applications, # which should not override any existing files in origin XDG_DATA_DIRS, @@ -10,49 +14,55 @@ # So we append the path to XDG_DATA_DIRS here like, # instead of prepending it like flatpak. -# --- 变量初始化和规范化 --- +# --- Variable initialization --- LINGLONG_ROOT="@LINGLONG_ROOT@" LINGLONG_EXPORT_PATH="@LINGLONG_EXPORT_PATH@" - LINGLONG_DATA_DIR="${LINGLONG_ROOT}/entries/share" -# --- 辅助函数:安全地添加路径到 XDG_DATA_DIRS --- -# 这个函数会检查路径是否已存在,如果不存在则添加。 -# 参数1: 要添加的路径 (path_to_add) -# 参数2: 添加位置 ('start' 或 'end',默认为 'start') -_add_path_to_xdg_data_dirs() { - local path_to_add="${1%/}" # 确保要添加的路径没有末尾斜杠 - local position="${2:-start}" # 默认添加到开头 - - # 检查路径是否已存在于 XDG_DATA_DIRS 中 - # 在 XDG_DATA_DIRS 两端加上冒号,以确保精确匹配(无论路径在开头、中间还是结尾) - if [[ ":${XDG_DATA_DIRS}:" == *":${path_to_add}:"* ]]; then - # 路径已存在,不执行任何操作 - return 0 - fi - - if [[ "$position" == "start" ]]; then - # 添加到开头 - XDG_DATA_DIRS="$path_to_add:$XDG_DATA_DIRS" - elif [[ "$position" == "end" ]]; then - # 添加到末尾 - XDG_DATA_DIRS="$XDG_DATA_DIRS:$path_to_add" - fi +# --- Helper function: safely add path to XDG_DATA_DIRS --- +# Parameters: path_to_add [position] +# position: "begin" to add at the beginning, anything else (or omitted) to add at the end +_append_path_to_xdg_data_dirs() { + path_to_add="$1" + position="${2:-end}" + + # Remove trailing slash if present + case "${path_to_add}" in + */) path_to_add="${path_to_add%/}" ;; + esac + + # Check if path is empty + [ -z "${path_to_add}" ] && return 0 + + # Check if path already exists in XDG_DATA_DIRS + [ -n "${XDG_DATA_DIRS}" ] && case ":${XDG_DATA_DIRS}:" in + *":${path_to_add}:"*) return 0 ;; # Path already exists + esac + + # Add to the beginning or end based on position parameter + case "${position}" in + "begin") + XDG_DATA_DIRS="${path_to_add}${XDG_DATA_DIRS:+:${XDG_DATA_DIRS}}" + ;; + *) + XDG_DATA_DIRS="${XDG_DATA_DIRS:+${XDG_DATA_DIRS}:}${path_to_add}" + ;; + esac +} + +# --- Helper function: initialize XDG_DATA_DIRS if empty --- +_init_xdg_data_dir() { + # If XDG_DATA_DIRS is empty, set to system default paths + [ -z "${XDG_DATA_DIRS}" ] && XDG_DATA_DIRS="/usr/local/share:/usr/share" } -# 如果 XDG_DATA_DIRS 为空,则先设置为 /usr/local/share:/usr/share -# 参考: https://specifications.freedesktop.org/basedir-spec/latest -_add_path_to_xdg_data_dirs "/usr/local/share" "end" -_add_path_to_xdg_data_dirs "/usr/share" "end" +_init_xdg_data_dir -# 将 LINGLONG_DATA_DIR 添加到 XDG_DATA_DIRS 的末尾(如果不存在) -_add_path_to_xdg_data_dirs "$LINGLONG_DATA_DIR" "end" +# Add LINGLONG_DATA_DIR to the end of XDG_DATA_DIRS (if it doesn't exist) +_append_path_to_xdg_data_dirs "${LINGLONG_DATA_DIR}" -# 如果有自定义 LINGLONG_EXPORT_PATH(默认为 "share"),将自定义路径添加到 XDG_DATA_DIRS -if [ "$LINGLONG_EXPORT_PATH" != "share" ]; then - CUSTOM_DATA_DIR="${LINGLONG_ROOT}/entries/${LINGLONG_EXPORT_PATH}" - _add_path_to_xdg_data_dirs "$CUSTOM_DATA_DIR" "start" -fi +# If there's a custom LINGLONG_EXPORT_PATH (default is "share"), add custom path to XDG_DATA_DIRS +[ "${LINGLONG_EXPORT_PATH}" != "share" ] && _append_path_to_xdg_data_dirs "${LINGLONG_ROOT}/entries/${LINGLONG_EXPORT_PATH}" "begin" -# --- 清理辅助函数 --- -unset -f _add_path_to_xdg_data_dirs +# --- Clean up helper functions --- +unset -f _append_path_to_xdg_data_dirs _init_xdg_data_dir diff --git a/misc/lib/systemd/system-environment-generators/61-linglong b/misc/lib/systemd/system-environment-generators/61-linglong index 23412123a..6dbb1f43e 100755 --- a/misc/lib/systemd/system-environment-generators/61-linglong +++ b/misc/lib/systemd/system-environment-generators/61-linglong @@ -1,9 +1,19 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# SPDX-FileCopyrightText: 2023-2025 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later -source "@CMAKE_INSTALL_PREFIX@/lib/linglong/generate-xdg-data-dirs.sh" +# shellcheck shell=sh -echo "XDG_DATA_DIRS=$XDG_DATA_DIRS" +# Profile.d script for linglong/linyaps +# This script sources the XDG_DATA_DIRS generation script and exports +# the modified XDG_DATA_DIRS environment variable for user sessions. + +source_script="@CMAKE_INSTALL_PREFIX@/lib/linglong/generate-xdg-data-dirs.sh" + +# Source the script and export XDG_DATA_DIRS if successful +[ -r "${source_script}" ] && . "${source_script}" && [ -n "${XDG_DATA_DIRS}" ] && export XDG_DATA_DIRS + +# Log error in debug mode if sourcing failed +[ "${DEBUG:-0}" = "1" ] && [ ! -r "${source_script}" ] && echo "Source script not found: ${source_script}" >&2 diff --git a/misc/script/linglong.sh b/misc/script/linglong.sh index 072627475..397c7cac5 100644 --- a/misc/script/linglong.sh +++ b/misc/script/linglong.sh @@ -1,9 +1,16 @@ #!/usr/bin/env sh -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# SPDX-FileCopyrightText: 2023-2025 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later -. "@CMAKE_INSTALL_PREFIX@/lib/linglong/generate-xdg-data-dirs.sh" +# shellcheck shell=sh -export XDG_DATA_DIRS +# Profile.d script for linglong/linyaps +# This script sources the XDG_DATA_DIRS generation script and exports +# the modified XDG_DATA_DIRS environment variable for user sessions. + +source_script="@CMAKE_INSTALL_PREFIX@/lib/linglong/generate-xdg-data-dirs.sh" + +# Source the script and export XDG_DATA_DIRS if successful +[ -r "${source_script}" ] && . "${source_script}" && [ -n "${XDG_DATA_DIRS}" ] && export XDG_DATA_DIRS From cab7fa441d6a170c9c08bc9e86ce224edb69c7fa Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 23 Jun 2025 13:09:08 +0800 Subject: [PATCH 066/366] fix: add missing header Signed-off-by: ComixHe --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 4c1eee26a..277e919b7 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include From 39a912c4b6d555f79c59979624b80a1b29118c9b Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 10:52:36 +0800 Subject: [PATCH 067/366] [linyaps] Updates for project Linyaps (#1241) * i18n: Translate po/en_US.po in pt_BR 93% of minimum 50% translated source file: 'po/en_US.po' on 'pt_BR'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pt_BR 95% of minimum 50% translated source file: 'po/en_US.po' on 'pt_BR'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pt_BR 95% of minimum 50% translated source file: 'po/en_US.po' on 'pt_BR'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pt_BR 100% translated source file: 'po/en_US.po' on 'pt_BR'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- po/pt_BR.po | 57 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index 8af842f45..c25be15bc 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -7,6 +7,7 @@ # Cassiano Molinari , 2025 # Wislley Marçal, 2025 # keven doria, 2025 +# Alex, 2025 # #, fuzzy msgid "" @@ -15,7 +16,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-06-09 14:53+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" -"Last-Translator: keven doria, 2025\n" +"Last-Translator: Alex, 2025\n" "Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/teams/3976/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -42,7 +43,7 @@ msgstr "Falha na instalação" #: ../libs/linglong/src/linglong/cli/cli.cpp:452 msgid "The module could not be found remotely." -msgstr "" +msgstr "O módulo não pôde ser encontrado remotamente." #: ../libs/linglong/src/linglong/cli/cli.cpp:455 #: ../libs/linglong/src/linglong/cli/cli.cpp:1659 @@ -320,7 +321,7 @@ msgstr "Instalar um módulo específico" #: ../apps/ll-cli/src/main.cpp:328 msgid "Install from a specific repo" -msgstr "" +msgstr "Instalar a partir de um repositório específico" #: ../apps/ll-cli/src/main.cpp:331 msgid "Force install the application" @@ -393,6 +394,24 @@ msgid "" "# find all of runtime(s) of remote\n" "ll-cli search . --type=runtime" msgstr "" +"Uso: ll-cli search [OPÇÕES] PALAVRAS-CHAVE\n" +"\n" +"Exemplo:\n" +"\n" +"# localizar remotamente aplicativo(s), base(s) ou runtime(s) por palavras-chave\n" +"ll-cli search org.deepin.demo\n" +"\n" +"# localizar remotamente runtime pelo nome\n" +"ll-cli search org.deepin.base --type=runtime\n" +"\n" +"# listar todos os aplicativos remotos\n" +"ll-cli search .\n" +"\n" +"# listar todas as bases remotas\n" +"ll-cli search . --type=base\n" +"\n" +"# listar todos os runtimes remotos\n" +"ll-cli search . --type=runtime" #: ../apps/ll-cli/src/main.cpp:389 msgid "Specify the Keywords" @@ -401,22 +420,24 @@ msgstr "Especifique as palavras-chave" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" +"Filtrar os resultados pelo tipo especificado. Um dos valores: \"runtime\", " +"\"base\", \"app\" ou \"todos\"" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" -msgstr "" +msgstr "Especificar o repositório" #: ../apps/ll-cli/src/main.cpp:403 msgid "Include develop application in result" -msgstr "" +msgstr "Incluir aplicativos em desenvolvimento no resultado" #: ../apps/ll-cli/src/main.cpp:406 msgid "Show all versions of an application(s), base(s) or runtime(s)" -msgstr "" +msgstr "Exibir todas as versões de aplicativos, bases ou runtimes" #: ../apps/ll-cli/src/main.cpp:411 msgid "List installed application(s), base(s) or runtime(s)" -msgstr "" +msgstr "Listar aplicativos, bases ou runtimes instalados" #: ../apps/ll-cli/src/main.cpp:414 msgid "" @@ -432,12 +453,28 @@ msgid "" "# show the latest version list of the currently installed application(s)\n" "ll-cli list --upgradable\n" msgstr "" +"Uso: ll-cli list [OPÇÕES]\n" +"\n" +"Exemplo:\n" +"# exibir aplicativos, bases ou runtimes instalados\n" +"ll-cli list\n" +"\n" +"# exibir bases instaladas\n" +"ll-cli list --type=base\n" +"\n" +"# exibir runtimes instalados\n" +"ll-cli list --type=runtime\n" +"\n" +"# exibir a lista das versões mais recentes dos aplicativos instalados que podem ser atualizados\n" +"ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" msgstr "" +"Exibir a lista das versões mais recentes dos aplicativos, bases ou runtimes " +"atualmente instalados" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -623,11 +660,11 @@ msgstr "Descrição" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:108 msgid "No packages found in the remote repo." -msgstr "" +msgstr "Nenhum pacote encontrado no repositório remoto." #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:140 msgid "Repo" -msgstr "" +msgstr "Repositório" #: ../libs/linglong/src/linglong/cli/cli_printer.cpp:175 msgid "No containers are running." @@ -817,7 +854,7 @@ msgstr "Exportar uab completamente" #: ../apps/ll-builder/src/main.cpp:827 msgid "Export to linyaps layer file (deprecated)" -msgstr "" +msgstr "Exportar para arquivo de camada Linyaps (obsoleto)" #: ../apps/ll-builder/src/main.cpp:830 msgid "Use custom loader" From 71ee2bd1d1d987c1f7f0beba3bff42c602d7bd6a Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 23 Jun 2025 10:39:36 +0800 Subject: [PATCH 068/366] fix: improve ld.so.cache validation and regeneration - Add content-based validation for ld.so.conf to detect layer path changes - Include configuration sources hash in ld.so.conf for validation - In PackageManager GenerateCache always generate cache, tryGenerateCache will skip it if cache directory exists - use memcpy in sha256 to avoid unaligned visit This ensures that ld.so.cache is properly regenerated when the underlying layer configuration changes, preventing stale cache issues. Signed-off-by: reddevillg --- apps/uab/header/src/sha256.h | 5 +- libs/linglong/src/linglong/cli/cli.cpp | 86 +++++++++++++------ libs/linglong/src/linglong/cli/cli.h | 13 ++- .../package_manager/package_manager.cpp | 44 +++++----- .../src/linglong/runtime/run_context.h | 2 + libs/oci-cfg-generators/CMakeLists.txt | 2 +- .../container_cfg_builder.cpp | 29 ++++++- .../container_cfg_builder.h | 2 +- 8 files changed, 125 insertions(+), 58 deletions(-) diff --git a/apps/uab/header/src/sha256.h b/apps/uab/header/src/sha256.h index 9e54a1523..dc04da73e 100644 --- a/apps/uab/header/src/sha256.h +++ b/apps/uab/header/src/sha256.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace digest { @@ -149,7 +150,9 @@ class SHA256 for (std::size_t i = 0; i < block_num; ++i) { std::array M{}; for (int j = 0; j < 16; ++j) { - M[j] = details::to_big_endian(reinterpret_cast(data)[i * 16 + j]); + uint32_t tmp = 0; + std::memcpy(&tmp, &data[i * 64 + j * 4], 4); + M[j] = details::to_big_endian(tmp); } std::array W{}; diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index a3044eb6f..a117e54aa 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -596,12 +596,6 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) qWarning() << ret.error().message(); } - auto appCache = this->ensureCache(*curAppRef, *appLayerItem); - if (!appCache) { - this->printer.printErr(LINGLONG_ERRV(appCache)); - return -1; - } - auto commands = options.commands; if (options.commands.empty()) { commands = info.command.value_or(std::vector{ "bash" }); @@ -705,8 +699,6 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) return -1; } cfgBuilder.setAppId(curAppRef->id.toStdString()) - .setAppCache(*appCache) - .enableLDCache() .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() @@ -728,6 +720,13 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) cfgBuilder.enableFontCache(); #endif + auto appCache = this->ensureCache(runContext, cfgBuilder); + if (!appCache) { + this->printer.printErr(LINGLONG_ERRV(appCache)); + return -1; + } + cfgBuilder.setAppCache(*appCache).enableLDCache(); + if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); qCritical() << "build cfg error: " << QString::fromStdString(err.reason); @@ -2414,9 +2413,11 @@ Cli::RequestDirectories(const api::types::v1::PackageInfoV2 &info) noexcept ::close(fd); }); - struct flock lock - { - .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, + struct flock lock{ + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, }; // all later processes should be blocked @@ -2563,7 +2564,7 @@ Cli::RequestDirectories(const api::types::v1::PackageInfoV2 &info) noexcept int Cli::generateCache(const package::Reference &ref) { - LINGLONG_TRACE("generate cache for all applications"); + LINGLONG_TRACE("generate cache for " + ref.toString()); QEventLoop loop; QString jobIDReply; auto ret = connect(&this->pkgMan, @@ -2598,34 +2599,63 @@ int Cli::generateCache(const package::Reference &ref) return loop.exec(); } -utils::error::Result -Cli::ensureCache(const package::Reference &ref, - const api::types::v1::RepositoryCacheLayersItem &appLayerItem) noexcept +utils::error::Result Cli::ensureCache( + runtime::RunContext &runContext, const generator::ContainerCfgBuilder &cfgBuilder) noexcept { - LINGLONG_TRACE("ensure cache for: " + QString::fromStdString(appLayerItem.info.id)); - - std::error_code ec; - // TODO: Here we need to judge the validity of the cache. The directory may be an empty - // directory. - auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / appLayerItem.commit; + LINGLONG_TRACE("ensure cache"); - if (std::filesystem::exists(appCache, ec)) { - qDebug() << "The cache has been generated."; - return appCache; + auto appLayerItem = runContext.getCachedAppItem(); + if (!appLayerItem) { + return LINGLONG_ERR(appLayerItem); } - if (ec) { - return LINGLONG_ERR(QString::fromStdString(ec.message()), ec.value()); + auto appLayer = runContext.getAppLayer(); + if (!appLayer) { + return LINGLONG_ERR("app layer not found"); } + auto appRef = appLayer->getReference(); + + auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / appLayerItem->commit; + do { + std::error_code ec; + if (!std::filesystem::exists(appCache, ec)) { + break; + } + + // check ld.so.conf + { + auto ldSoConf = appCache / "ld.so.conf"; + if (!std::filesystem::exists(ldSoConf, ec)) { + break; + } + + // If the ld.so.conf exists, check if it is consistent with the current configuration. + auto ldConf = cfgBuilder.ldConf(appRef.arch.getTriplet().toStdString()); + std::stringstream oldCache; + std::ifstream ifs(ldSoConf, std::ios::binary | std::ios::in); + if (!ifs.is_open()) { + return LINGLONG_ERR("failed to open " + QString::fromStdString(ldSoConf.string())); + } + oldCache << ifs.rdbuf(); + qDebug() << "ld.so.conf:" << QString::fromStdString(ldConf); + qDebug() << "old ld.so.conf:" << QString::fromStdString(oldCache.str()); + if (oldCache.str() != ldConf) { + break; + } + } + + return appCache; + } while (false); // Try to generate cache here QProcess process; process.setProgram(LINGLONG_LIBEXEC_DIR "/ll-dialog"); - process.setArguments({ "-m", "startup", "--id", QString::fromStdString(appLayerItem.info.id) }); + process.setArguments( + { "-m", "startup", "--id", QString::fromStdString(appLayerItem->info.id) }); process.start(); qDebug() << process.program() << process.arguments(); - auto ret = this->generateCache(ref); + auto ret = this->generateCache(appRef); if (ret != 0) { this->notifier->notify(api::types::v1::InteractionRequest{ .summary = diff --git a/libs/linglong/src/linglong/cli/cli.h b/libs/linglong/src/linglong/cli/cli.h index bb57528e0..75feacbc3 100644 --- a/libs/linglong/src/linglong/cli/cli.h +++ b/libs/linglong/src/linglong/cli/cli.h @@ -19,6 +19,14 @@ #include +namespace linglong::runtime { +class RunContext; +} + +namespace linglong::generator { +class ContainerCfgBuilder; +} + namespace linglong::cli { class Printer; @@ -121,9 +129,8 @@ class Cli : public QObject utils::error::Result> listUpgradable(const std::string &type = "app"); int generateCache(const package::Reference &ref); - utils::error::Result - ensureCache(const package::Reference &ref, - const api::types::v1::RepositoryCacheLayersItem &appLayerItem) noexcept; + utils::error::Result ensureCache( + runtime::RunContext &runContext, const generator::ContainerCfgBuilder &cfgBuilder) noexcept; QDBusReply authorization(); void updateAM() noexcept; diff --git a/libs/linglong/src/linglong/package_manager/package_manager.cpp b/libs/linglong/src/linglong/package_manager/package_manager.cpp index 6fe430b59..d1aa412f7 100644 --- a/libs/linglong/src/linglong/package_manager/package_manager.cpp +++ b/libs/linglong/src/linglong/package_manager/package_manager.cpp @@ -2319,7 +2319,8 @@ utils::error::Result PackageManager::generateCache(const package::Referenc const std::string fontGenerator = generatorDest + "/font-cache-generator"; #endif std::error_code ec; - if (!std::filesystem::create_directories(appCache, ec)) { + std::filesystem::create_directories(appCache, ec); + if (ec) { return LINGLONG_ERR(QString::fromStdString(ec.message())); } @@ -2374,12 +2375,12 @@ utils::error::Result PackageManager::generateCache(const package::Referenc // generate ld config { - std::ofstream ofs(ldConfPath); + std::ofstream ofs(ldConfPath, std::ios::binary | std::ios::out | std::ios::trunc); Q_ASSERT(ofs.is_open()); if (!ofs.is_open()) { return LINGLONG_ERR("create ld config in bundle directory"); } - ofs << cfgBuilder.ldConf(ref.arch.getTriplet().toStdString()) << std::endl; + ofs << cfgBuilder.ldConf(ref.arch.getTriplet().toStdString()); } if (!cfgBuilder.build()) { @@ -2437,10 +2438,25 @@ utils::error::Result PackageManager::generateCache(const package::Referenc return LINGLONG_OK; } -// we should allow cache generation to fail, skip it when an error occurs by. the function can be -// removed later when the kernel clone new_user problem is solved. +// it's safe to skip cache generation here, if the cache directory already exists. +// when application begins to run, it will regenerate the cache if necessary utils::error::Result PackageManager::tryGenerateCache(const package::Reference &ref) noexcept { + LINGLONG_TRACE("try to generate cache for " + ref.toString()); + + auto layerItem = this->repo.getLayerItem(ref); + if (!layerItem) { + return LINGLONG_ERR(layerItem); + } + auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / layerItem->commit; + std::error_code ec; + if (std::filesystem::exists(appCache, ec)) { + return LINGLONG_OK; + } + if (ec) { + return LINGLONG_ERR(QString::fromStdString(ec.message())); + } + auto ret = generateCache(ref); if (!ret) { qWarning() << "failed to generate cache" << ret.error(); @@ -2479,24 +2495,6 @@ auto PackageManager::GenerateCache(const QString &reference) noexcept -> QVarian m_generator_queue.runTask([this, jobID, ref]() { qInfo() << "Generate cache for:" << ref.toString(); - const auto &appLayerItem = this->repo.getLayerItem(ref); - if (!appLayerItem) { - qWarning() << "failed to get app layer item" << appLayerItem.error(); - return; - } - auto appCache = std::filesystem::path(LINGLONG_ROOT) / "cache" / appLayerItem->commit; - - std::error_code ec; - if (std::filesystem::exists(appCache, ec)) { - qInfo() << "The cache has been generated."; - return; - } - - if (ec) { - qCritical() << "failed to get app cache" << ec.message().c_str() << ec.value(); - return; - } - auto ret = this->generateCache(ref); if (!ret) { qCritical() << "failed to generate cache for:" << ref.toString(); diff --git a/libs/linglong/src/linglong/runtime/run_context.h b/libs/linglong/src/linglong/runtime/run_context.h index aff117229..f2540e946 100644 --- a/libs/linglong/src/linglong/runtime/run_context.h +++ b/libs/linglong/src/linglong/runtime/run_context.h @@ -78,6 +78,8 @@ class RunContext const std::optional &getRuntimeLayer() const { return runtimeLayer; } + const std::optional &getAppLayer() const { return appLayer; } + utils::error::Result getBaseLayerPath() const; utils::error::Result getRuntimeLayerPath() const; diff --git a/libs/oci-cfg-generators/CMakeLists.txt b/libs/oci-cfg-generators/CMakeLists.txt index 74958eaf7..dceba4689 100644 --- a/libs/oci-cfg-generators/CMakeLists.txt +++ b/libs/oci-cfg-generators/CMakeLists.txt @@ -21,4 +21,4 @@ pfl_add_library( ) get_real_target_name(GEN linglong::oci-cfg-generators) -target_include_directories(${GEN} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src/linglong/oci-cfg-generators) +target_include_directories(${GEN} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src/linglong/oci-cfg-generators ${CMAKE_SOURCE_DIR}/apps/uab/header/src) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 0e996af5b..3fa7c8de7 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -10,9 +10,11 @@ #include "linglong/api/types/v1/Generators.hpp" #include "linglong/api/types/v1/OciConfigurationPatch.hpp" #include "ocppi/runtime/config/types/Generators.hpp" +#include "sha256.h" #include #include +#include #include #include @@ -469,8 +471,9 @@ ContainerCfgBuilder &ContainerCfgBuilder::addMask(const std::vector return *this; } -std::string ContainerCfgBuilder::ldConf(const std::string &triplet) +std::string ContainerCfgBuilder::ldConf(const std::string &triplet) const { + std::vector factors; std::string ldRawConf; auto appendLdConf = [&ldRawConf, &triplet](const std::string &prefix) { ldRawConf.append(prefix + "/lib\n"); @@ -480,18 +483,42 @@ std::string ContainerCfgBuilder::ldConf(const std::string &triplet) if (runtimePath) { appendLdConf(runtimeMountPoint); + factors.push_back(runtimePath->string()); } if (appPath) { appendLdConf(std::filesystem::path{ "/opt/apps" } / appId / "files"); + factors.push_back(appPath->string()); } if (extensionMount) { for (const auto &extension : *extensionMount) { appendLdConf(extension.destination); + if (extension.source) { + factors.push_back(*extension.source); + } } } + std::sort(factors.begin(), factors.end()); + + digest::SHA256 sha256; + for (const auto &factor : factors) { + sha256.update(reinterpret_cast(factor.c_str()), factor.size()); + } + std::array digest{}; + sha256.final(digest.data()); + + std::stringstream stream; + stream << "# "; + stream << std::setfill('0') << std::hex; + for (auto v : digest) { + stream << std::setw(2) << static_cast(v); + } + stream << std::endl; + + ldRawConf.insert(0, stream.str()); + return ldRawConf; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index a535c8387..0fb0e6c78 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -172,7 +172,7 @@ class ContainerCfgBuilder return *this; } - std::string ldConf(const std::string &triplet); + std::string ldConf(const std::string &triplet) const; bool build() noexcept; From 70156a8722578622cbd7e3aceb3c1b871f4f5588 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 30 Jun 2025 14:13:33 +0800 Subject: [PATCH 069/366] fix: copy hidden files see issue #1246 Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 9b5c4a841..6d56078f9 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -87,7 +87,7 @@ utils::error::Result inline copyDir(const QString &src, const QString &dst } const QFileInfoList list = - srcDir.entryInfoList(QDir::System | QDir::AllEntries | QDir::NoDotAndDotDot); + srcDir.entryInfoList(QDir::System | QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden); for (const auto &info : list) { if (info.isDir() && !info.isSymLink()) { From 7cef08dba420290eccdbe3bf6db8feaeb10f8a27 Mon Sep 17 00:00:00 2001 From: myml Date: Fri, 27 Jun 2025 18:01:25 +0800 Subject: [PATCH 070/366] fix: invert condition in filterPackageInfosByType invert condition in filterPackageInfosByType to correctly filter package types --- libs/linglong/src/linglong/cli/cli.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index a117e54aa..c505e24c8 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -2269,7 +2269,7 @@ void Cli::filterPackageInfosByType(std::vector Date: Mon, 30 Jun 2025 17:13:24 +0800 Subject: [PATCH 071/366] fix: ensure correct localtime and resolv.conf mounting Mounting may fail if the file types differed between the build layer and host (e.g., regular file vs. symbolic link). Implemented solution through two approaches 1. Build phase: Proactively remove /etc/localtime and /etc/resolv.conf from base layer during overlayfs preparation to prevent conflicts with host. 2. Container configuration: Introduced dedicated buildMountLocalTime and buildNetworkConf methods to handle timezone and resolv.conf mounts, with enableSelfAdjustingMount properly managing these cases. Signed-off-by: reddevillg --- .../src/linglong/builder/linglong_builder.cpp | 29 +++- .../src/linglong/builder/linglong_builder.h | 1 + .../container_cfg_builder.cpp | 159 ++++++++++++++---- .../container_cfg_builder.h | 5 + 4 files changed, 157 insertions(+), 37 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 6d56078f9..21a42e0ff 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -703,6 +703,30 @@ std::unique_ptr Builder::makeOverlay(QString lowerdir, return overlay; } +// when using overlayfs, remove /etc/localtime and allow the container(box for now) to create the +// correct mount point +void Builder::fixLocaltimeInOverlay(std::unique_ptr &baseOverlay) +{ + std::filesystem::path base{ baseOverlay->mergedDirPath().toStdString() }; + std::vector remove{ + "etc/localtime", + "etc/resolv.conf", + }; + + for (const auto &r : remove) { + std::error_code ec; + auto target = base / r; + if (std::filesystem::exists(target, ec)) { + std::filesystem::remove(target, ec); + if (ec) { + qWarning() << QString("failed to remove %1: %2") + .arg(target.string().c_str()) + .arg(ec.message().c_str()); + } + } + } +} + utils::error::Result Builder::processBuildDepends() noexcept { LINGLONG_TRACE("process build depends"); @@ -800,6 +824,7 @@ utils::error::Result Builder::buildStagePreBuild() noexcept if (!baseOverlay) { return LINGLONG_ERR("failed to mount build base overlayfs"); } + fixLocaltimeInOverlay(baseOverlay); if (buildContext.hasRuntime()) { auto runtimeLayerPath = buildContext.getRuntimeLayerPath(); @@ -978,6 +1003,7 @@ utils::error::Result Builder::buildStagePreCommit() noexcept if (!baseOverlay) { return LINGLONG_ERR("failed to mount prepare base overlayfs"); } + fixLocaltimeInOverlay(baseOverlay); if (buildContext.hasRuntime()) { auto runtimeLayerPath = buildContext.getRuntimeLayerPath(); @@ -1854,7 +1880,8 @@ utils::error::Result Builder::run(const QStringList &modules, .type = "bind", }); - auto appCache = std::filesystem::path{ workingDir.absolutePath().toStdString() } / "linglong" / "cache"; + auto appCache = + std::filesystem::path{ workingDir.absolutePath().toStdString() } / "linglong" / "cache"; std::string ldConfPath = appCache / "ld.so.conf"; applicationMounts.push_back(ocppi::runtime::config::types::Mount{ .destination = "/etc/ld.so.conf.d/zz_deepin-linglong-app.conf", diff --git a/libs/linglong/src/linglong/builder/linglong_builder.h b/libs/linglong/src/linglong/builder/linglong_builder.h index 25dcacd2c..0b02a855f 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.h +++ b/libs/linglong/src/linglong/builder/linglong_builder.h @@ -103,6 +103,7 @@ class Builder utils::error::Result processBuildDepends() noexcept; utils::error::Result commitToLocalRepo() noexcept; std::unique_ptr makeOverlay(QString lowerdir, QString overlayDir) noexcept; + void fixLocaltimeInOverlay(std::unique_ptr &base); utils::error::Result ensureUtils(const std::string &id) noexcept; utils::error::Result clearDependency(const std::string &ref, bool forceRemote, diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 3fa7c8de7..f84464bbd 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -12,6 +12,8 @@ #include "ocppi/runtime/config/types/Generators.hpp" #include "sha256.h" +#include + #include #include #include @@ -39,6 +41,30 @@ using ocppi::runtime::config::types::NamespaceType; using ocppi::runtime::config::types::Process; using ocppi::runtime::config::types::RootfsPropagation; +namespace { +bool bindIfExist(std::vector &mounts, + std::filesystem::path source, + std::string destination = "", + bool ro = true) noexcept +{ + std::error_code ec; + if (!std::filesystem::exists(source, ec)) { + return false; + } + + if (destination.empty()) { + destination = source.string(); + } + + mounts.emplace_back(Mount{ .destination = destination, + .options = string_list{ "rbind", ro ? "ro" : "rw" }, + .source = source, + .type = "bind" }); + + return true; +} +} // namespace + ContainerCfgBuilder &ContainerCfgBuilder::addUIdMapping(int64_t containerID, int64_t hostID, int64_t size) noexcept @@ -356,33 +382,19 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindHostRoot() noexcept ContainerCfgBuilder &ContainerCfgBuilder::bindHostStatics() noexcept { - std::vector statics{ + std::vector statics{ "/etc/machine-id", - "/etc/resolvconf", // FIXME: support for host /etc/ssl, ref https://github.com/p11-glue/p11-kit "/usr/lib/locale", "/usr/share/fonts", "/usr/share/icons", "/usr/share/themes", - "/usr/share/zoneinfo", "/var/cache/fontconfig", - // TODO It's better to move to volatileMount - "/etc/localtime", - "/etc/resolv.conf", - "/etc/timezone", - "/etc/hosts" }; hostStaticsMount = std::vector{}; - std::error_code ec; for (const auto &loc : statics) { - if (!std::filesystem::exists(loc, ec)) { - continue; - } - hostStaticsMount->emplace_back(Mount{ .destination = loc, - .options = string_list{ "rbind", "ro" }, - .source = loc, - .type = "bind" }); + bindIfExist(*hostStaticsMount, loc); } return *this; @@ -920,20 +932,7 @@ bool ContainerCfgBuilder::buildMountIPC() noexcept return false; } - auto bindIfExist = [this](std::string_view source, std::string_view destination) mutable { - std::error_code ec; - if (!std::filesystem::exists(source, ec)) { - return; - } - - auto realDest = destination.empty() ? source : destination; - ipcMount->emplace_back(Mount{ .destination = std::string{ realDest }, - .options = string_list{ "rbind" }, - .source = std::string{ source }, - .type = "bind" }); - }; - - bindIfExist("/tmp/.X11-unix", ""); + bindIfExist(*ipcMount, "/tmp/.X11-unix", "", false); // TODO 应该参考规范文档实现更完善的地址解析支持 // https://dbus.freedesktop.org/doc/dbus-specification.html#addresses @@ -975,7 +974,7 @@ bool ContainerCfgBuilder::buildMountIPC() noexcept std::string("unix:path=/run/dbus/system_bus_socket") + options; }(); - [this, &bindIfExist]() { + [this]() { auto *XDGRuntimeDirEnv = getenv("XDG_RUNTIME_DIR"); // NOLINT if (XDGRuntimeDirEnv == nullptr) { return; @@ -1004,10 +1003,14 @@ bool ContainerCfgBuilder::buildMountIPC() noexcept auto cognitiveXDGRuntimeDir = std::filesystem::path{ environment["XDG_RUNTIME_DIR"] }; - bindIfExist((hostXDGRuntimeDir / "pulse").string(), - (cognitiveXDGRuntimeDir / "pulse").string()); - bindIfExist((hostXDGRuntimeDir / "gvfs").string(), - (cognitiveXDGRuntimeDir / "gvfs").string()); + bindIfExist(*ipcMount, + hostXDGRuntimeDir / "pulse", + (cognitiveXDGRuntimeDir / "pulse").string(), + false); + bindIfExist(*ipcMount, + hostXDGRuntimeDir / "gvfs", + (cognitiveXDGRuntimeDir / "gvfs").string(), + false); [this, &hostXDGRuntimeDir, &cognitiveXDGRuntimeDir]() { auto *waylandDisplayEnv = getenv("WAYLAND_DISPLAY"); // NOLINT @@ -1163,6 +1166,82 @@ bool ContainerCfgBuilder::buildLDCache() noexcept return true; } +bool ContainerCfgBuilder::buildMountLocalTime() noexcept +{ + // always bind host's localtime + // assume /etc/localtime is a symlink to /usr/share/zoneinfo/XXX/NNN + localtimeMount = std::vector{}; + + std::filesystem::path localtime{ "/etc/localtime" }; + std::error_code ec; + if (std::filesystem::exists(localtime, ec)) { + bool isSymLink = false; + if (std::filesystem::is_symlink(localtime, ec)) { + isSymLink = true; + } + localtimeMount->emplace_back(Mount{ .destination = localtime.string(), + .options = isSymLink ? string_list{ "copy-symlink" } + : string_list{ "rbind", "ro" }, + .source = localtime, + .type = "bind" }); + } + + bindIfExist(*localtimeMount, "/usr/share/zoneinfo"); + bindIfExist(*localtimeMount, "/etc/timezone"); + + return true; +} + +bool ContainerCfgBuilder::buildMountNetworkConf() noexcept +{ + networkConfMount = std::vector{}; + + std::filesystem::path resolvConf{ "/etc/resolv.conf" }; + std::error_code ec; + if (std::filesystem::exists(resolvConf, ec)) { + if (std::filesystem::is_symlink(resolvConf, ec) && hostRootMount) { + // If /etc/resolv.conf is a symlink, its target may be a relative path that is + // invalid inside the container. To work around this, we create a new symlink + // in the bundle directory pointing to the actual target, and then mount it with + // the 'copy-symlink' option, which tells the runtime to recreate the symlink + // inside the container. + std::array buf{}; + auto *rpath = realpath(resolvConf.string().c_str(), buf.data()); + if (rpath == nullptr) { + error_.reason = + "Failed to read symlink " + resolvConf.string() + ": " + strerror(errno); + error_.code = BUILD_NETWORK_CONF_ERROR; + return false; + } + + std::filesystem::path target = std::filesystem::path{ "/run/host/rootfs" } + / std::filesystem::path{ rpath }.lexically_relative("/"); + auto bundleResolvConf = bundlePath / "resolv.conf"; + std::filesystem::create_symlink(target, bundleResolvConf, ec); + if (ec) { + error_.reason = + "Failed to create symlink " + bundleResolvConf.string() + ": " + ec.message(); + error_.code = BUILD_NETWORK_CONF_ERROR; + return false; + } + + networkConfMount->emplace_back(Mount{ .destination = resolvConf.string(), + .options = string_list{ "copy-symlink" }, + .source = bundleResolvConf, + .type = "bind" }); + } else { + networkConfMount->emplace_back(Mount{ .destination = resolvConf.string(), + .options = string_list{ "rbind", "ro" }, + .source = resolvConf, + .type = "bind" }); + } + } + + bindIfExist(*networkConfMount, "/etc/resolvconf"); + bindIfExist(*networkConfMount, "/etc/hosts"); + return true; +} + // TODO bool ContainerCfgBuilder::buildQuirkVolatile() noexcept { @@ -1549,6 +1628,14 @@ bool ContainerCfgBuilder::mergeMount() noexcept std::move(ldCacheMount->begin(), ldCacheMount->end(), std::back_inserter(mounts)); } + if (localtimeMount) { + std::move(localtimeMount->begin(), localtimeMount->end(), std::back_inserter(mounts)); + } + + if (networkConfMount) { + std::move(networkConfMount->begin(), networkConfMount->end(), std::back_inserter(mounts)); + } + if (privateMount) { std::move(privateMount->begin(), privateMount->end(), std::back_inserter(mounts)); } @@ -1924,7 +2011,7 @@ bool ContainerCfgBuilder::build() noexcept return false; } - if (!buildMountIPC()) { + if (!buildMountIPC() || !buildMountLocalTime() || !buildMountNetworkConf()) { return false; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 0fb0e6c78..0fc5c25e6 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -41,6 +41,7 @@ class ContainerCfgBuilder BUILD_LDCONF_ERROR, BUILD_LDCACHE_ERROR, BUILD_ENV_ERROR, + BUILD_NETWORK_CONF_ERROR, }; class Error @@ -202,6 +203,8 @@ class ContainerCfgBuilder bool buildMountIPC() noexcept; bool buildMountCache() noexcept; bool buildLDCache() noexcept; + bool buildMountLocalTime() noexcept; + bool buildMountNetworkConf() noexcept; bool buildQuirkVolatile() noexcept; bool buildEnv() noexcept; bool applyPatch() noexcept; @@ -258,6 +261,8 @@ class ContainerCfgBuilder std::optional> hostRootMount; std::optional> hostStaticsMount; std::optional> ipcMount; + std::optional> localtimeMount; + std::optional> networkConfMount; // cache std::optional> cacheMount; From c3d8c21aca2834e6dae1bc8b2162992644feeb62 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 30 Jun 2025 18:18:31 +0800 Subject: [PATCH 072/366] fix: Isolate app-specific patches in dedicated directories Previously, app-specific patches were identified by matching the patch filename (without the extension) against the application ID. This approach was flawed as it caused patch conflicts between different applications. For example, a patch named `com.app.A.json`, intended only for `com.app.A`, would be incorrectly applied as a global patch to `com.app.B`. This commit introduces a directory-based mechanism to correctly isolate application-specific patches. All patches for a specific app must now reside within a subdirectory named after the app ID. Signed-off-by: reddevillg --- .../container_cfg_builder.cpp | 26 ++++++++++++++----- misc/lib/linglong/container/README.md | 9 +++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index f84464bbd..57fb129c9 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -1339,17 +1339,31 @@ bool ContainerCfgBuilder::applyPatch() noexcept return false; } for (const auto &entry : iter) { + const auto &path = entry.path(); if (entry.is_regular_file(ec)) { - const auto &path = entry.path(); - // application-specific patch will be applied last - if (path.stem().string() == appId) { - appPatchFiles.emplace_back(path); - continue; - } globalPatchFiles.emplace_back(path); + } else if (entry.is_directory(ec)) { + if (path.filename().string() == appId) { + auto iterApp = std::filesystem::directory_iterator{ + path, + std::filesystem::directory_options::skip_permission_denied, + ec + }; + if (ec) { + error_.reason = + "failed to iterator directory " + path.string() + ": " + ec.message(); + } + for (const auto &entryApp : iterApp) { + if (!entryApp.is_regular_file(ec)) { + continue; + } + appPatchFiles.emplace_back(entryApp.path()); + } + } } } std::sort(globalPatchFiles.begin(), globalPatchFiles.end()); + std::sort(appPatchFiles.begin(), appPatchFiles.end()); auto doPatch = [this](const std::vector &patchFiles) -> bool { for (const auto &patchFile : patchFiles) { diff --git a/misc/lib/linglong/container/README.md b/misc/lib/linglong/container/README.md index 5f83c8343..843a0089c 100644 --- a/misc/lib/linglong/container/README.md +++ b/misc/lib/linglong/container/README.md @@ -50,15 +50,14 @@ can be found at [/api/schema/v1.yaml]. ## Application-specific patches -Patches whose filenames match the application ID are treated as application-specific. -These patches are applied after global patches. +Patches in application ID-named directories are application-specific and apply after global patches ## Examples - Global patch: `99-dump-conf` -- App patch: `com.example.app.json` (matches app ID) +- App patch: `com.example.app/99-test.json` -com.example.app.json: +com.example.app/99-test.json: ```json { @@ -80,7 +79,7 @@ com.example.app.json: } ``` -com.example.app.json add an extra mounts, which bind host's `/opt/apps` to container's `/opt/host-apps`, +com.example.app/99-test.json add an extra mounts, which bind host's `/opt/apps` to container's `/opt/host-apps`, this patch will applied after 99-dump-conf. 99-dump-conf can write following content to print the container's configuration: From ebcadfe8507561d0de410c74a94ebbe60d1bac00 Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 1 Jul 2025 17:15:56 +0800 Subject: [PATCH 073/366] fix: the context menu of the file manager displays abnormally Add optional file suffix filtering to exportDir, ensures only files matching the specified suffix are processed. --- configure.h.in | 2 +- .../src/linglong/repo/ostree_repo.cpp | 28 +++++++++++++++++-- libs/linglong/src/linglong/repo/ostree_repo.h | 10 ++++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/configure.h.in b/configure.h.in index 1d7c4c03b..ed27e087d 100644 --- a/configure.h.in +++ b/configure.h.in @@ -25,7 +25,7 @@ // The directory where the package install hooks reside. #define LINGLONG_INSTALL_HOOKS_DIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@/linglong/config.d" -#define LINGLONG_EXPORT_VERSION "1.0.0.1" +#define LINGLONG_EXPORT_VERSION "1.0.0.2" // The package's locale domain. #define PACKAGE_LOCALE_DOMAIN "@GETTEXT_DOMAIN_NAME@" diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 277e919b7..ecca28bc1 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1908,7 +1908,8 @@ void OSTreeRepo::exportReference(const package::Reference &ref) noexcept utils::error::Result OSTreeRepo::exportDir(const std::string &appID, const std::filesystem::path &source, const std::filesystem::path &destination, - const int &max_depth) + const int &max_depth, + const std::optional &fileSuffix) { LINGLONG_TRACE(QString("export %1").arg(source.c_str())); if (max_depth <= 0) { @@ -1932,6 +1933,7 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, if (!is_directory) { return LINGLONG_ERR("source is not a directory"); } + // 检查目标目录是否存在,如果不存在则创建 exists = std::filesystem::exists(destination, ec); if (ec) { @@ -1952,10 +1954,20 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, return LINGLONG_ERR(QString("Failed to create directory: ") + destination.c_str(), ec); } } + auto iterator = std::filesystem::directory_iterator(source, ec); if (ec) { return LINGLONG_ERR("list directory: " + source.string(), ec); } + + static auto endWithFunc = [](std::string_view path, std::string_view suffix) { + if (suffix.length() > path.length()) { + return false; + } + + return path.substr(path.length() - suffix.length()) == suffix; + }; + // 遍历源目录中的所有文件和子目录 for (const auto &entry : iterator) { const auto &source_path = entry.path(); @@ -1975,6 +1987,12 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, return LINGLONG_ERR("check file type: " + source_path.string(), ec); } if (is_regular_file) { + // 如果有指定的后缀名,则只处理指定后缀名的文件 + if (fileSuffix.has_value() + && !endWithFunc(std::string_view(source_path.string()), std::string_view(fileSuffix.value()))) { + continue; + } + exists = std::filesystem::exists(target_path, ec); if (ec) { return LINGLONG_ERR("check file existence", ec); @@ -2056,7 +2074,7 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, return LINGLONG_ERR("check file type", ec); } if (is_directory) { - auto ret = this->exportDir(appID, source_path, target_path, max_depth - 1); + auto ret = this->exportDir(appID, source_path, target_path, max_depth - 1, fileSuffix); if (!ret.has_value()) { return ret; } @@ -2153,7 +2171,11 @@ OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, destination = rootEntriesDir / desktopExportPath; - auto ret = this->exportDir(item.info.id, source, destination, 10); + auto ret = this->exportDir(item.info.id, + source, + destination, + 10, + std::make_optional(".desktop")); if (!ret.has_value()) { return ret; } diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index 126ab6c1d..ad9569531 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -197,10 +197,12 @@ class OSTreeRepo : public QObject static utils::error::Result IniLikeFileRewrite(const QFileInfo &info, const QString &id) noexcept; - utils::error::Result exportDir(const std::string &appID, - const std::filesystem::path &source, - const std::filesystem::path &destination, - const int &max_depth); + utils::error::Result + exportDir(const std::string &appID, + const std::filesystem::path &source, + const std::filesystem::path &destination, + const int &max_depth, + const std::optional &fileSuffix = std::nullopt); // exportEntries will clear the entries/share and export all applications to the entries/share utils::error::Result exportAllEntries() noexcept; }; From f56b597e3347821f569cf65765877d4a1e651d11 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 2 Jul 2025 15:57:53 +0800 Subject: [PATCH 074/366] feat: add branch release/** to workflow Signed-off-by: reddevillg --- .github/workflows/build.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d4d04ceb7..e3775558f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -4,6 +4,7 @@ on: push: branches: - master + - 'release/**' jobs: ubuntu2404: name: ubuntu_24.04 @@ -52,4 +53,4 @@ jobs: -DBUILD_SHARED_LIBS=OFF \ .. - make -j$(nproc) \ No newline at end of file + make -j$(nproc) From 7e00c9b76dca52c3a1f7f73488cdd5ca713b1d7f Mon Sep 17 00:00:00 2001 From: myml Date: Fri, 4 Jul 2025 12:01:53 +0800 Subject: [PATCH 075/366] fix: skip rewrite for files with a single hard link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为了兼容上个版本直接对source进行重写,这里需要判断原始文件的硬链接数 如果硬链接数为1,则说明原始文件重写过了,就跳过重写 因为多次重写会导致应用出问题 --- .../src/linglong/repo/ostree_repo.cpp | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index ecca28bc1..829b423ad 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -2021,6 +2021,7 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, info.suffix()) .toStdString(); + // 如果原始文件不存在,当前source作为原始文件 auto originPath = source_path.string() + ".linyaps.original"; if (!std::filesystem::exists(originPath, ec)) { std::filesystem::rename(source_path, originPath, ec); @@ -2028,12 +2029,13 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, return LINGLONG_ERR("rename orig path", ec); } } - + // 复制原始文件到source用于后面的重写 std::filesystem::copy(originPath, sourceNewPath, ec); if (ec) { return LINGLONG_ERR("copy file failed: " + sourceNewPath, ec); } - + + // TODO 这部分代码可以删除 exists = std::filesystem::exists(sourceNewPath, ec); if (ec) { return LINGLONG_ERR("check file exists", ec); @@ -2044,14 +2046,22 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, continue; } - auto ret = IniLikeFileRewrite(QFileInfo(sourceNewPath.c_str()), appID.c_str()); - if (ret) { - std::filesystem::rename(sourceNewPath, source_path, ec); - if (ec) { - return LINGLONG_ERR("rename new path", ec); + // 为了兼容上个版本直接对source进行重写,这里需要判断原始文件的硬链接数 + // 如果硬链接数为1,则说明原始文件重写过了,就跳过重写 + auto hard_link_count = std::filesystem::hard_link_count(originPath, ec); + if (ec) { + return LINGLONG_ERR("get hard link count", ec); + } + if (hard_link_count > 1) { + auto ret = IniLikeFileRewrite(QFileInfo(sourceNewPath.c_str()), appID.c_str()); + if (!ret) { + qWarning() << "rewrite file failed: " << ret.error().message(); + continue; } - } else { - qWarning() << "rewrite file failed: " << ret.error().message(); + } + std::filesystem::rename(sourceNewPath, source_path, ec); + if (ec) { + return LINGLONG_ERR("rename new path", ec); } } From 3cbe65dad1d90c765ae581f4dcdac4305c7c8adb Mon Sep 17 00:00:00 2001 From: myml Date: Mon, 7 Jul 2025 20:18:15 +0800 Subject: [PATCH 076/366] refactor: simplify environment variable handling in systemd generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Removed debug logging code that was checking for script readability 2. Changed from direct export to echo output for systemd environment handling 3. Simplified the logic by removing redundant checks since systemd generators expect echo output 4. The change aligns better with systemd's environment generator expectations where variables should be echoed rather than exported directly refactor: 简化 systemd 生成器中的环境变量处理 1. 移除了检查脚本可读性的调试日志代码 2. 将直接导出改为 echo 输出以适配 systemd 环境处理 3. 通过移除冗余检查简化了逻辑,因为 systemd 生成器期望 echo 输出 4. 此变更更符合 systemd 环境生成器的预期,变量应该通过 echo 输出而非直接 导出 --- .../systemd/system-environment-generators/61-linglong | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/misc/lib/systemd/system-environment-generators/61-linglong b/misc/lib/systemd/system-environment-generators/61-linglong index 6dbb1f43e..474e0c7e3 100755 --- a/misc/lib/systemd/system-environment-generators/61-linglong +++ b/misc/lib/systemd/system-environment-generators/61-linglong @@ -13,7 +13,10 @@ source_script="@CMAKE_INSTALL_PREFIX@/lib/linglong/generate-xdg-data-dirs.sh" # Source the script and export XDG_DATA_DIRS if successful -[ -r "${source_script}" ] && . "${source_script}" && [ -n "${XDG_DATA_DIRS}" ] && export XDG_DATA_DIRS +[ -r "${source_script}" ] && . "${source_script}" -# Log error in debug mode if sourcing failed -[ "${DEBUG:-0}" = "1" ] && [ ! -r "${source_script}" ] && echo "Source script not found: ${source_script}" >&2 +if [ -n "${XDG_DATA_DIRS}" ]; then +# !!!systemd requires environment variables to be printed to standard output!!! +# https://www.freedesktop.org/software/systemd/man/latest/systemd.environment-generator.html +echo "XDG_DATA_DIRS=${XDG_DATA_DIRS}" +fi From c7559ffe7c6b24faa6ffc3ab0a65304d0ab4921c Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 7 Jul 2025 23:23:53 +0800 Subject: [PATCH 077/366] fix: treat /etc/localtime as fixed mount node Signed-off-by: reddevillg --- .../oci-cfg-generators/container_cfg_builder.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 57fb129c9..539efce23 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -1770,9 +1770,12 @@ bool ContainerCfgBuilder::shouldFix(int node, std::filesystem::path &fixPath) no }); return find != mount.options->end(); }; - // if file is not exist or - // file is not a symlink but mount with option copy-symlink - if (!std::filesystem::exists(hostPath, ec) + // node should fix if the file + // 1. is /etc/localtime or + // 2. is not exist or + // 3. is not a symlink but mount with option copy-symlink + if (getRelativePath(0, node) == "etc/localtime" + || !std::filesystem::exists(hostPath, ec) || ((!std::filesystem::is_symlink(hostPath, ec)) && isCopySymlink(node))) { fixPath = std::move(hostPath); return true; From bdf2cde3c90d2155930e33c55ba1988a367ea65c Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 10 Jul 2025 14:18:01 +0800 Subject: [PATCH 078/366] feat: add mirror enable/disable functionality for repos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added new CLI commands `enable-mirror` and `disable-mirror` for repository management 2. Implemented handler functions for mirror enable/disable operations in both ll-builder and ll-cli 3. Modified repo config handling to support mirrorEnabled flag as optional boolean 4. Updated test cases to include mirrorEnabled field in test data 5. Improved repo alias handling by using value_or to fallback to repoName when alias is not provided These changes allow users to control mirror functionality for repositories through CLI commands, providing more flexibility in repository configuration. The mirrorEnabled flag is now properly handled in the OSTree repo configuration. feat: 为仓库添加镜像启用/禁用功能 1. 新增了用于仓库管理的`enable-mirror`和`disable-mirror` CLI命令 2. 在ll-builder和ll-cli中实现了镜像启用/禁用操作的处理函数 3. 修改了仓库配置处理以支持可选的mirrorEnabled标志 4. 更新了测试用例,在测试数据中包含mirrorEnabled字段 5. 通过使用value_or在别名未提供时回退到repoName,改进了仓库别名处理 这些变更允许用户通过CLI命令控制仓库的镜像功能,为仓库配置提供更多灵活 性。现在在OSTree仓库配置中正确处理了mirrorEnabled标志。 --- api/schema/v1.json | 4 + api/schema/v1.yaml | 3 + apps/ll-builder/src/main.cpp | 89 +++++++++++++++++-- apps/ll-cli/src/main.cpp | 14 +++ .../src/linglong/api/types/v1/Generators.hpp | 4 + libs/api/src/linglong/api/types/v1/Repo.hpp | 4 + .../src/linglong/repo/ostree_repo.cpp | 8 ++ .../src/linglong/repo/config_test.cpp | 40 ++++----- 8 files changed, 141 insertions(+), 25 deletions(-) diff --git a/api/schema/v1.json b/api/schema/v1.json index b2f20cc5e..8b6184abe 100644 --- a/api/schema/v1.json +++ b/api/schema/v1.json @@ -600,6 +600,10 @@ "priority": { "type": "integer", "description": "priority of repo" + }, + "mirror_enabled": { + "type": "boolean", + "description": "whether mirror is enabled for this repo" } } }, diff --git a/api/schema/v1.yaml b/api/schema/v1.yaml index 60311d8e2..9ef823ce0 100644 --- a/api/schema/v1.yaml +++ b/api/schema/v1.yaml @@ -478,6 +478,9 @@ $defs: priority: type: integer description: priority of repo + mirror_enabled: + type: boolean + description: whether mirror is enabled for this repo LayerInfo: description: Meta information on the head of layer file. type: object diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index d01157446..ce9997957 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -496,7 +496,7 @@ int handleRepoAdd(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions & int handleRepoRemove(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions &options) { auto newCfg = repo.getConfig(); - const std::string &alias = options.repoAlias.value(); + const std::string &alias = options.repoAlias.value_or(options.repoName); auto existingRepo = std::find_if(newCfg.repos.begin(), newCfg.repos.end(), [&alias](const auto &r) { @@ -529,7 +529,7 @@ int handleRepoRemove(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOption int handleRepoUpdate(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions &options) { auto newCfg = repo.getConfig(); - const std::string &alias = options.repoAlias.value(); + const std::string &alias = options.repoAlias.value_or(options.repoName); if (options.repoUrl.empty()) { std::cerr << "url is empty." << std::endl; @@ -561,7 +561,7 @@ int handleRepoUpdate(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOption int handleRepoSetDefault(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions &options) { auto newCfg = repo.getConfig(); - const std::string &alias = options.repoAlias.value(); + const std::string &alias = options.repoAlias.value_or(options.repoName); auto existingRepo = std::find_if(newCfg.repos.begin(), newCfg.repos.end(), [&alias](const auto &r) { @@ -588,13 +588,66 @@ int handleRepoSetDefault(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOp return 0; } +int handleRepoEnableMirror(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions &options) +{ + auto newCfg = repo.getConfig(); + const std::string &alias = options.repoAlias.value_or(options.repoName); + + auto existingRepo = + std::find_if(newCfg.repos.begin(), newCfg.repos.end(), [&alias](const auto &r) { + return r.alias.value_or(r.name) == alias; + }); + + if (existingRepo == newCfg.repos.cend()) { + std::cerr << "the operated repo " + alias + " doesn't exist." << std::endl; + return -1; + } + + existingRepo->mirrorEnabled = true; + auto ret = repo.setConfig(newCfg); + if (!ret) { + std::cerr << ret.error().message().toStdString() << std::endl; + return -1; + } + + std::cerr << "Repository " << alias << " mirror enabled successfully."; + return 0; +} + +int handleRepoDisableMirror(linglong::repo::OSTreeRepo &repo, linglong::cli::RepoOptions &options) +{ + auto newCfg = repo.getConfig(); + const std::string &alias = options.repoAlias.value_or(options.repoName); + + auto existingRepo = + std::find_if(newCfg.repos.begin(), newCfg.repos.end(), [&alias](const auto &r) { + return r.alias.value_or(r.name) == alias; + }); + + if (existingRepo == newCfg.repos.cend()) { + std::cerr << "the operated repo " + alias + " doesn't exist." << std::endl; + return -1; + } + + existingRepo->mirrorEnabled = false; + auto ret = repo.setConfig(newCfg); + if (!ret) { + std::cerr << ret.error().message().toStdString() << std::endl; + return -1; + } + std::cerr << "Repository " << alias << " mirror disabled successfully."; + return 0; +} + int handleRepo(linglong::repo::OSTreeRepo &repo, const RepoSubcommandOptions &options, CLI::App *buildRepoShow, CLI::App *buildRepoAdd, CLI::App *buildRepoRemove, CLI::App *buildRepoUpdate, - CLI::App *buildRepoSetDefault) + CLI::App *buildRepoSetDefault, + CLI::App *buildRepoEnableMirror, + CLI::App *buildRepoDisableMirror) { if (buildRepoShow->parsed()) { return handleRepoShow(repo); @@ -628,6 +681,14 @@ int handleRepo(linglong::repo::OSTreeRepo &repo, return handleRepoSetDefault(repo, repoOptions); } + if (buildRepoEnableMirror->parsed()) { + return handleRepoEnableMirror(repo, repoOptions); + } + + if (buildRepoDisableMirror->parsed()) { + return handleRepoDisableMirror(repo, repoOptions); + } + std::cerr << "unknown repo operation, please see help information." << std::endl; return EINVAL; } @@ -930,6 +991,22 @@ You can report bugs to the linyaps team under this project: https://github.com/O ->required() ->check(validatorString); + // add repo sub command enable mirror + auto buildRepoEnableMirror = + buildRepo->add_subcommand("enable-mirror", _("Enable mirror for the repo")); + buildRepoEnableMirror->usage(_("Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS")); + buildRepoEnableMirror->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) + ->required() + ->check(validatorString); + + // add repo sub command disable mirror + auto buildRepoDisableMirror = + buildRepo->add_subcommand("disable-mirror", _("Disable mirror for the repo")); + buildRepoDisableMirror->usage(_("Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS")); + buildRepoDisableMirror->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) + ->required() + ->check(validatorString); + // add repo sub command show auto buildRepoShow = buildRepo->add_subcommand("show", _("Show repository information")); buildRepoShow->usage(_("Usage: ll-builder repo show [OPTIONS]")); @@ -994,7 +1071,9 @@ You can report bugs to the linyaps team under this project: https://github.com/O buildRepoAdd, buildRepoRemove, buildRepoUpdate, - buildRepoSetDefault); + buildRepoSetDefault, + buildRepoEnableMirror, + buildRepoDisableMirror); } if (buildImport->parsed()) { diff --git a/apps/ll-cli/src/main.cpp b/apps/ll-cli/src/main.cpp index 519e851dd..2f55599cb 100644 --- a/apps/ll-cli/src/main.cpp +++ b/apps/ll-cli/src/main.cpp @@ -509,6 +509,20 @@ ll-cli list --upgradable ->add_option("PRIORITY", options.repoOptions.repoPriority, _("Priority of the repo")) ->required() ->check(validatorString); + // add repo sub command enable mirror + auto *repoEnableMirror = + cliRepo->add_subcommand("enable-mirror", _("Enable mirror for the repo")); + repoEnableMirror->usage(_("Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS")); + repoEnableMirror->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) + ->required() + ->check(validatorString); + // add repo sub command disable mirror + auto *repoDisableMirror = + cliRepo->add_subcommand("disable-mirror", _("Disable mirror for the repo")); + repoDisableMirror->usage(_("Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS")); + repoDisableMirror->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) + ->required() + ->check(validatorString); // add sub command info auto *cliInfo = diff --git a/libs/api/src/linglong/api/types/v1/Generators.hpp b/libs/api/src/linglong/api/types/v1/Generators.hpp index f89e9630e..5c05294cd 100644 --- a/libs/api/src/linglong/api/types/v1/Generators.hpp +++ b/libs/api/src/linglong/api/types/v1/Generators.hpp @@ -1058,6 +1058,7 @@ j["packages"] = x.packages; inline void from_json(const json & j, Repo& x) { x.alias = get_stack_optional(j, "alias"); +x.mirrorEnabled = get_stack_optional(j, "mirror_enabled"); x.name = j.at("name").get(); x.priority = j.at("priority").get(); x.url = j.at("url").get(); @@ -1068,6 +1069,9 @@ j = json::object(); if (x.alias) { j["alias"] = x.alias; } +if (x.mirrorEnabled) { +j["mirror_enabled"] = x.mirrorEnabled; +} j["name"] = x.name; j["priority"] = x.priority; j["url"] = x.url; diff --git a/libs/api/src/linglong/api/types/v1/Repo.hpp b/libs/api/src/linglong/api/types/v1/Repo.hpp index 1e9928678..39baa3302 100644 --- a/libs/api/src/linglong/api/types/v1/Repo.hpp +++ b/libs/api/src/linglong/api/types/v1/Repo.hpp @@ -36,6 +36,10 @@ struct Repo { */ std::optional alias; /** +* whether mirror is enabled for this repo +*/ +std::optional mirrorEnabled; +/** * repo name */ std::string name; diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 829b423ad..d2e6dfb60 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -398,6 +398,14 @@ updateOstreeRepoConfig(OstreeRepo *repo, // libcurl 8.2.1 has a http2 bug https://github.com/curl/curl/issues/11859 // We disable http2 for now. g_variant_builder_add(&builder, "{sv}", "http2", g_variant_new_boolean(FALSE)); + // add contenturl to use mirrorlist + if (repoCfg.mirrorEnabled.value_or(false)) { + auto mirrorlist = std::string("mirrorlist=") + repoCfg.url + "/api/v2/mirrors/stable"; + g_variant_builder_add(&builder, + "{sv}", + "contenturl", + g_variant_new_string(mirrorlist.c_str())); + } options = g_variant_ref_sink(g_variant_builder_end(&builder)); if (ostree_repo_remote_change(repo, diff --git a/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp b/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp index 635a19191..3ebecdbcc 100644 --- a/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp +++ b/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp @@ -18,22 +18,22 @@ TEST(Repo, GetRepoMinPriority) { RepoConfigV2 cfg; - cfg.repos = { { std::nullopt, "repo1", 100, "http://example.com/repo1" } }; + cfg.repos = { { std::nullopt,false, "repo1", 100, "http://example.com/repo1" }}; EXPECT_EQ(getRepoMinPriority(cfg), 100); - cfg.repos = { { std::nullopt, "repo1", 200, "http://example.com/repo1" }, - { std::nullopt, "repo2", 100, "http://example.com/repo2" }, - { std::nullopt, "repo3", 300, "http://example.com/repo3" } }; + cfg.repos = { { std::nullopt, false, "repo1", 200, "http://example.com/repo1" }, + { std::nullopt, false, "repo2", 100, "http://example.com/repo2" }, + { std::nullopt, false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMinPriority(cfg), 100); - cfg.repos = { { std::nullopt, "repo1", -100, "http://example.com/repo1" }, - { std::nullopt, "repo2", 0, "http://example.com/repo2" }, - { std::nullopt, "repo3", 500, "http://example.com/repo3" } }; + cfg.repos = { { std::nullopt, false, "repo1", -100, "http://example.com/repo1" }, + { std::nullopt, false, "repo2", 0, "http://example.com/repo2" }, + { std::nullopt, false, "repo3", 500, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMinPriority(cfg), -100); - cfg.repos = { { "alias1", "repo1", 200, "http://example.com/repo1" }, - { "alias2", "repo2", 100, "http://example.com/repo2" }, - { "alias3", "repo3", 300, "http://example.com/repo3" } }; + cfg.repos = { { "alias1", false, "repo1", 200, "http://example.com/repo1" }, + { "alias2", false, "repo2", 100, "http://example.com/repo2" }, + { "alias3", false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMinPriority(cfg), 100); } @@ -41,22 +41,22 @@ TEST(Repo, GetRepoMaxPriority) { RepoConfigV2 cfg; - cfg.repos = { { std::nullopt, "repo1", 100, "http://example.com/repo1" } }; + cfg.repos = { { std::nullopt, false, "repo1", 100, "http://example.com/repo1" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 100); - cfg.repos = { { std::nullopt, "repo1", 200, "http://example.com/repo1" }, - { std::nullopt, "repo2", 100, "http://example.com/repo2" }, - { std::nullopt, "repo3", 300, "http://example.com/repo3" } }; + cfg.repos = { { std::nullopt, false, "repo1", 200, "http://example.com/repo1" }, + { std::nullopt, false, "repo2", 100, "http://example.com/repo2" }, + { std::nullopt, false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 300); - cfg.repos = { { std::nullopt, "repo1", -200, "http://example.com/repo1" }, - { std::nullopt, "repo2", 0, "http://example.com/repo2" }, - { std::nullopt, "repo3", 300, "http://example.com/repo3" } }; + cfg.repos = { { std::nullopt, false, "repo1", -200, "http://example.com/repo1" }, + { std::nullopt, false, "repo2", 0, "http://example.com/repo2" }, + { std::nullopt, false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 300); - cfg.repos = { { "alias1", "repo1", 200, "http://example.com/repo1" }, - { "alias2", "repo2", 0, "http://example.com/repo2" }, - { "alias3", "repo3", 300, "http://example.com/repo3" } }; + cfg.repos = { { "alias1",false, "repo1", 200, "http://example.com/repo1" }, + { "alias2", false, "repo2", 0, "http://example.com/repo2" }, + { "alias3", false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 300); } From e85ff3b6d1098733b0230ecb337e96da91c13360 Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 10 Jul 2025 14:19:06 +0800 Subject: [PATCH 079/366] fix: update msgmerge command options in translation workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added --no-fuzzy-matching and --backup=off flags to msgmerge command 2. These changes prevent creation of fuzzy matches and backup files during translation updates 3. Improves consistency in translation files and reduces unnecessary file clutter 4. The modification affects both custom target and file-level commands in CMake fix: 更新翻译工作流中的 msgmerge 命令选项 1. 为 msgmerge 命令添加了 --no-fuzzy-matching 和 --backup=off 标志 2. 这些更改防止在翻译更新过程中创建模糊匹配和备份文件 3. 提高翻译文件的一致性并减少不必要的文件混乱 4. 修改同时影响 CMake 中的自定义目标和文件级命令 --- po/CMakeLists.txt | 4 +- po/ca.po | 281 +++++++++++++++++++++++------------------- po/en_GB.po | 281 +++++++++++++++++++++++------------------- po/en_US.po | 262 +++++++++++++++++++++------------------ po/es.po | 305 +++++++++++++++++++++++++--------------------- po/fi.po | 292 ++++++++++++++++++++++++-------------------- po/linyaps.pot | 254 +++++++++++++++++++++----------------- po/pl.po | 294 ++++++++++++++++++++++++-------------------- po/pt_BR.po | 300 +++++++++++++++++++++++++-------------------- po/sq.po | 278 +++++++++++++++++++++++------------------- po/uk.po | 296 ++++++++++++++++++++++++-------------------- po/zh_CN.po | 289 ++++++++++++++++++++++++------------------- 12 files changed, 1744 insertions(+), 1392 deletions(-) diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt index 025c251f9..386c22b47 100644 --- a/po/CMakeLists.txt +++ b/po/CMakeLists.txt @@ -66,7 +66,7 @@ if(GETTEXT_FOUND) foreach(language ${langs}) add_custom_target( linyaps_${language}.po - COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --update --verbose ${language}.po + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --no-fuzzy-matching --backup=off --update --verbose ${language}.po ${GETTEXT_DOMAIN_NAME}.pot WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/po COMMENT "Updating ${language}.po file") @@ -79,6 +79,8 @@ if(GETTEXT_FOUND) ${language}.po: && ${GETTEXT_MSGMERGE_EXECUTABLE} + --no-fuzzy-matching + --backup=off --update --verbose ${language}.po diff --git a/po/ca.po b/po/ca.po index 6d266e0b4..c261ba4d5 100644 --- a/po/ca.po +++ b/po/ca.po @@ -2,68 +2,69 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Jaime Muñoz Martín , 2025 # Davidmp , 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Davidmp , 2025\n" -"Language-Team: Catalan (https://app.transifex.com/linuxdeepin/teams/3976/ca/)\n" +"Language-Team: Catalan (https://app.transifex.com/linuxdeepin/teams/3976/" +"ca/)\n" +"Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Se n'ha denegat el permís. Comproveu si s'executa com a arrel." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Per instal·lar el mòdul, primer cal instal·lar l'aplicació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "El mòdul ja està instal·lat.." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Ha fallat la instal·lació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "No s'ha pogut trobar el mòdul remotament." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Ha fallat la desinstal·lació." -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "Ha fallat l'actualització." -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "L'aplicació no està instal·lada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "La darrera versió ja està instal·lada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -73,7 +74,7 @@ msgstr "" "1. Comproveu la connexió a Internet.\n" "2. Verifiqueu la configuració del servidor intermediari de xarxa, si n'hi ha." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -81,15 +82,15 @@ msgstr "" "L'aplicació ja està instal·lada, si la voleu substituir, proveu d'usar \"ll-" "cli install %1 --force\"." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "L'aplicació %1 no es troba al repositori remot." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "No es pot especificar una versió en instal·lar un mòdul." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -97,7 +98,7 @@ msgstr "" "Se n'ha instal·lat la darrera versió. Si la voleu substituir, proveu d'usar " "'ll-cli install %1/version --force'." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -110,13 +111,14 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "CLI de linyaps\n" -"Un programa de línia d'ordres per executar aplicacions i gestionar l'aplicació i el temps d'execució\n" +"Un programa de línia d'ordres per executar aplicacions i gestionar " +"l'aplicació i el temps d'execució\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Imprimeix aquest missatge d'ajuda i surt." -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Expandeix tota l'ajuda." @@ -127,14 +129,15 @@ msgstr "Ús: ll-cli [OPCIONS] [SUBORDRE]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si heu trobat algun problema durant l'ús,\n" "podeu informar d'errors a l'equip de linyaps en aquest projecte: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Mostra'n la versió." @@ -150,7 +153,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Usa el format json per generar el resultat." -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "El paràmetre d'entrada és buit; introduïu un paràmetre vàlid." @@ -366,8 +369,8 @@ msgstr "Ús: ll-cli upgrade [OPCIONS] [APLICACIÓ]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Especifiqueu l'ID de l'aplicació. Si no s'especifica, s'actualitzaran totes " "les aplicacions." @@ -413,7 +416,9 @@ msgid "Specify the Keywords" msgstr "Especifiqueu les paraules clau." #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" "Filtra el resultat amb el tipus especificat: \"runtime\", \"base\", \"app\" " "o \"all\"." @@ -457,7 +462,8 @@ msgstr "" "ll-cli list --type=base\n" "# mostra els temps d'execució instal·lats\n" "ll-cli list --type=runtime\n" -"# mostra la llista de versions més recents de les aplicacions instal·lades actualment\n" +"# mostra la llista de versions més recents de les aplicacions instal·lades " +"actualment\n" "ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 @@ -477,7 +483,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Ús: ll-cli repo SUBORDRE [OPCIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Afegeix un repositori nou." @@ -486,21 +492,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Ús: ll-cli repo add [OPCIONS] NOM DE L'URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Especifiqueu el nom del repositori." #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "URL del repositori" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Àlies del nom del repositori" @@ -509,7 +517,7 @@ msgid "Modify repository URL" msgstr "Modifica l'URL del repositori" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Elimina un repositori" @@ -520,7 +528,7 @@ msgstr "Ús: ll-cli repo remove [OPCIONS] NOM" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Actualitza l'URL del repositori." @@ -528,7 +536,7 @@ msgstr "Actualitza l'URL del repositori." msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Ús: ll-cli repo update [OPCIONS] NOM D'URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Estableix un nom de repositori per defecte." @@ -537,7 +545,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Ús: ll-cli repo set-default [OPCIONS] NOM" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Mostra la informació del repositori." @@ -557,65 +565,80 @@ msgstr "Ús: ll-cli repo set-priority PRIORITAT DE L'ÀLIES" msgid "Priority of the repo" msgstr "Prioritat del repositori" -#: ../apps/ll-cli/src/main.cpp:516 -msgid "Display information about installed apps or runtimes" +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" msgstr "" -"Mostra informació sobre aplicacions instal·lades o entorns d'execució." -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:530 +msgid "Display information about installed apps or runtimes" +msgstr "Mostra informació sobre aplicacions instal·lades o entorns d'execució." + +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Ús: ll-cli info [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Especifiqueu l'ID de l'aplicació. També pot ser un fitxer .layer." -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Mostra els fitxers exportats de l'aplicació instal·lada." -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Ús: ll-cli content [OPCIONS] APLICACIÓ" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Especifiqueu l'ID de l'aplicació instal·lada." #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Elimina la base o l'entorn d'execució no usat." -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Ús: ll-cli prune [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Mostra la informació de l'aplicació instal·lada." -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Ús: ll-cli inspect [OPCIONS]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Especifiqueu l'identificador del procés." -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Identificador de procés no vàlid" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Format pid no vàlid" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Especifiqueu l'aplicació instal·lada (base o entorn d'execució)." -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "Versió CLI de linyaps" @@ -699,7 +722,7 @@ msgstr "Instal·lada" msgid "New" msgstr "Nova" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -707,51 +730,51 @@ msgstr "" "CLI del constructor de linyaps \n" "Un programa CLI per crear una aplicació de linyaps.\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Ús: ll-builder [OPCIONS] [SUBORDRE]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si heu trobat algun problema durant l'ús,\n" "podeu informar d'errors a l'equip de linyaps en aquest projecte: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Crea un projecte de plantilla de compilació de linyaps." -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Ús: ll-builder create [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Nom del projecte" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Construeix un projecte de linyaps." -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Ús: ll-builder build [OPCIONS] [ORDRE...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Camí del fitxer linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Entreu al contenidor per executar l'ordre en lloc de construir aplicacions." -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -759,197 +782,205 @@ msgstr "" "Usa només fitxers locals. Això implica que s'establiran --skip-fetch-source " "i --skip-pull-depend." -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Crea paquets de desenvolupament complets, cal entorn d'execució." -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Omet fonts d'obtenció." -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Omet la dependència de l'ordre pull." -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Omet el contenidor d'execució." -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Omet la sortida d'enviament de la compilació." -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Omet la comprovació de sortida." -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Omet els símbols de depuració." -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Construeix en un entorn de xarxa aïllat." #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Executa l'aplicació de linyaps creada." -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Ús: ll-builder run [OPCIONS] [ORDRE..]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Executa el mòdul especificat. Ex.: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" "Entreu al contenidor per executar l'ordre en lloc d'executar l'aplicació." -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Executa en mode de depuració (activa el mòdul de desenvolupament)." -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Llista les aplicacions de linyaps creades." -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Ús: ll-builder list [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Elimina l'aplicació de linyaps creada." -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Ús: ll-builder remove [OPCIONS] [APLICACIÓ...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Exporta a la capa linyaps o uab." -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Ús: ll-builder export [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Icona d'uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Exporta uab completament." -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Exporta a un fitxer de capa de Linyaps (obsolet)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Usa un carregador personalitzat." -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "No exportis el mòdul de desenvolupament." -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Fitxer de sortida" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Envieu l'aplicació linyaps al repositori remot." -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Ús: ll-builder push [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "URL del repositori remot" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Nom del repositori remot" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Envia un mòdul únic." -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Importa la capa de linyaps al repositori de construcció." -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Ús: ll-builder import [OPCIONS] CAPA" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Camí del fitxer de la capa" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "" "Importa el directori de la capa de linyaps al repositori de construcció." -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Camí del directori de la capa" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Extreu la capa de linyaps al directori." -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Ús: ll-builder extract [OPCIONS] DIRECTORI DE CAPES" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Directori de destinació" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Mostra i gestiona els repositoris." -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Ús: ll-builder repo [OPCIONS] SUBORDRES" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Ús: ll-builder repo add [OPCIONS] NOM D'URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Ús: ll-builder repo remove [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Ús: ll-builder repo update [OPCIONS] NOM D'URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Ús: ll-builder repo set-default [OPCIONS] NOM" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Ús: ll-builder repo show [OPCIONS]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "Versió de l'eina de construcció de linyaps" diff --git a/po/en_GB.po b/po/en_GB.po index df49a2490..0f171615f 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -2,94 +2,95 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Gary Wang , 2025\n" -"Language-Team: English (United Kingdom) (https://app.transifex.com/linuxdeepin/teams/3976/en_GB/)\n" +"Language-Team: English (United Kingdom) (https://app.transifex.com/" +"linuxdeepin/teams/3976/en_GB/)\n" +"Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -103,11 +104,11 @@ msgstr "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Print this help message and exit" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Expand all help" @@ -118,13 +119,15 @@ msgstr "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Show version" @@ -140,7 +143,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Use json format to output result" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Input parameter is empty, please input valid parameter instead" @@ -226,8 +229,7 @@ msgstr "Execute commands in the currently running sandbox" #: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" -msgstr "" -"Specify the application running instance(you can get it by ps command)" +msgstr "Specify the application running instance(you can get it by ps command)" #: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" @@ -353,8 +355,8 @@ msgstr "Usage: ll-cli upgrade [OPTIONS] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" #: ../apps/ll-cli/src/main.cpp:374 @@ -385,7 +387,9 @@ msgid "Specify the Keywords" msgstr "Specify the Keywords" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" #: ../apps/ll-cli/src/main.cpp:400 @@ -434,7 +438,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Add a new repository" @@ -443,21 +447,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo add [OPTIONS] NAME URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Specify the repo name" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "Url of the repository" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias of the repo name" @@ -466,7 +472,7 @@ msgid "Modify repository URL" msgstr "Modify repository URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Remove a repository" @@ -477,7 +483,7 @@ msgstr "Usage: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Update the repository URL" @@ -485,7 +491,7 @@ msgstr "Update the repository URL" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Set a default repository name" @@ -494,7 +500,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Usage: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Show repository information" @@ -514,64 +520,80 @@ msgstr "" msgid "Priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Display information about installed apps or runtimes" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Usage: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specify the application ID, and it can also be a .layer file" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Display the exported files of installed application" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Usage: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Specify the installed application ID" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Remove the unused base or runtime" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Usage: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Display the information of installed application" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Usage: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Specify the process id" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "linyaps CLI version " @@ -655,7 +677,7 @@ msgstr "Installed" msgid "New" msgstr "New" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -663,50 +685,51 @@ msgstr "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Create linyaps build template project" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Usage: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Project name" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Build a linyaps project" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "File path of the linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Enter the container to execute command instead of building applications" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -714,195 +737,203 @@ msgstr "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Build full develop packages, runtime requires" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Skip fetch sources" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Skip pull dependency" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Skip run container" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Skip commit build output" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Skip output check" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Skip strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Run specified module. eg: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "Enter the container to execute command instead of running application" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Run in debug mode (enable develop module)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Usage: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Usage: ll-builder remove [OPTIONS] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Export to linyaps layer or uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Usage: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Uab icon (optional)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Export uab fully" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Push linyaps app to remote repo" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Usage: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "Remote repo url" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Remote repo name" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Push single module" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Import linyaps layer to build repo" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Usage: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Layer file path" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Import linyaps layer dir to build repo" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Layer dir path" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Extract linyaps layer to dir" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Usage: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Destination directory" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Display and manage repositories" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Usage: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Usage: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Usage: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "linyaps build tool version " diff --git a/po/en_US.po b/po/en_US.po index 4ab574e78..5bf4e63f2 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-01-07 17:11+0800\n" "Last-Translator: deepiner, 2024\n" "Language-Team: LANGUAGE \n" @@ -17,48 +17,48 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Permission denied, please check whether you are running as root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "To install the module, one must first install the app." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "Module is already installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Install failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "The module could not be found remotely." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Uninstall failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "Upgrade failed" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "Application is not installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "Latest version is already installed." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -68,7 +68,7 @@ msgstr "" "1. Check your internet connection\n" "2. Verify network proxy settings if used" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -76,15 +76,15 @@ msgstr "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "Application %1 is not found in remote repo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "Cannot specify a version when installing a module." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -92,7 +92,7 @@ msgstr "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -106,11 +106,11 @@ msgstr "" "linyaps CLI\n" "A CLI program to run application and manage application and runtime\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Print this help message and exit" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Expand all help" @@ -121,15 +121,15 @@ msgstr "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Show version" @@ -145,7 +145,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Use json format to output result" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Input parameter is empty, please input valid parameter instead" @@ -470,7 +470,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Add a new repository" @@ -479,21 +479,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo add [OPTIONS] NAME URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Specify the repo name" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "Url of the repository" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias of the repo name" @@ -502,7 +504,7 @@ msgid "Modify repository URL" msgstr "Modify repository URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Remove a repository" @@ -513,7 +515,7 @@ msgstr "Usage: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Update the repository URL" @@ -521,7 +523,7 @@ msgstr "Update the repository URL" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Usage: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Set a default repository name" @@ -530,7 +532,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Usage: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Show repository information" @@ -550,64 +552,80 @@ msgstr "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgid "Priority of the repo" msgstr "Priority of the repo" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "Enable mirror for the repo" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "Disable mirror for the repo" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Display information about installed apps or runtimes" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Usage: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specify the application ID, and it can also be a .layer file" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Display the exported files of installed application" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Usage: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Specify the installed application ID" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Remove the unused base or runtime" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Usage: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Display the information of installed application" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Usage: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Specify the process id" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Invalid process id" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Invalid pid format" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Specify the installed app(base or runtime)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "linyaps CLI version " @@ -691,7 +709,7 @@ msgstr "Installed" msgid "New" msgstr "New" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -699,51 +717,51 @@ msgstr "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Create linyaps build template project" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Usage: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Project name" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Build a linyaps project" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "File path of the linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 +#: ../apps/ll-builder/src/main.cpp:808 msgid "Enter the container to execute command instead of building applications" msgstr "" "Enter the container to execute command instead of building applications" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -751,195 +769,203 @@ msgstr "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Build full develop packages, runtime requires" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Skip fetch sources" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Skip pull dependency" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Skip run container" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Skip commit build output" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Skip output check" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Skip strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Build in an isolated network environment" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Run built linyaps app" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Usage: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Run specified module. eg: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "Enter the container to execute command instead of running application" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Run in debug mode (enable develop module)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "List built linyaps app" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Usage: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Remove built linyaps app" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Usage: ll-builder remove [OPTIONS] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Export to linyaps layer or uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Usage: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Uab icon (optional)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Export uab fully" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Export to linyaps layer file (deprecated)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Use custom loader" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Don't export the develop module" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Output file" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Push linyaps app to remote repo" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Usage: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "Remote repo url" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Remote repo name" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Push single module" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Import linyaps layer to build repo" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Usage: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Layer file path" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Import linyaps layer dir to build repo" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Usage: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Layer dir path" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Extract linyaps layer to dir" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Usage: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Destination directory" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Display and manage repositories" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Usage: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Usage: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Usage: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Usage: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "linyaps build tool version " diff --git a/po/es.po b/po/es.po index 0a00451f2..de4243602 100644 --- a/po/es.po +++ b/po/es.po @@ -2,69 +2,71 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 # Isaías Gätjens M , 2025 # Zaraza, 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Zaraza, 2025\n" -"Language-Team: Spanish (https://app.transifex.com/linuxdeepin/teams/3976/es/)\n" +"Language-Team: Spanish (https://app.transifex.com/linuxdeepin/teams/3976/" +"es/)\n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " +"1 : 2;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Permiso denegado, verifique si está ejecutando como root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Para instalar el módulo, primero debe instalar la aplicación." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "El módulo ya está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "La instalación falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "No se pudo encontrar el módulo de forma remota." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "La desinstalación falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "La actualización falló" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "La aplicación no está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "La última versión ya está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -74,7 +76,7 @@ msgstr "" "1. Verifique su conexión a internet.\n" "2. Verifique la configuración del proxy de red, si lo utiliza." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -82,23 +84,23 @@ msgstr "" "Aplicación instalada, si desea reemplazarla intente usar 'll-cli install %1 " "--force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "La aplicación %1 no se encuentra en el repositorio remoto." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "No se puede especificar la versión al instalar un módulo" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -"Se ha instalado la última versión. Si desea reemplazarla, pruebe con «ll-cli" -" install %1/version --force»." +"Se ha instalado la última versión. Si desea reemplazarla, pruebe con «ll-cli " +"install %1/version --force»." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -111,13 +113,14 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Un programa CLI para ejecutar aplicaciones y gestionar aplicaciones y entornos de ejecución\n" +"Un programa CLI para ejecutar aplicaciones y gestionar aplicaciones y " +"entornos de ejecución\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Imprimir este mensaje de ayuda y salir" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Expandir toda la ayuda" @@ -128,13 +131,15 @@ msgstr "Uso: ll-cli [OPCIONES] [SUBCOMANDO]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si encuentras algún problema durante el uso,\n" -"puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"puede reportar errores al equipo de linyaps en este proyecto: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Mostrar versión" @@ -150,7 +155,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Usar formato json para mostrar el resultado" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" @@ -211,8 +216,7 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" -msgstr "" -"Pasar archivo a las aplicaciones que se ejecutan en un entorno aislado" +msgstr "Pasar archivo a las aplicaciones que se ejecutan en un entorno aislado" #: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" @@ -248,8 +252,7 @@ msgstr "Especificar la carpeta de trabajo" #: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" -msgstr "" -"Entrar en el espacio de nombres donde se está ejecutando la aplicación" +msgstr "Entrar en el espacio de nombres donde se está ejecutando la aplicación" #: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" @@ -315,8 +318,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Especificar el ID de la aplicación, también puede ser un archivo .uab o " -".layer" +"Especificar el ID de la aplicación, también puede ser un archivo .uab o ." +"layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -369,8 +372,8 @@ msgstr "Uso: ll-cli upgrade [OPCIONES] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Especificar el ID de la aplicación. Si no se especifica, se actualizarán " "todas las aplicaciones" @@ -400,7 +403,8 @@ msgstr "" "Uso: ll-cli search [OPCIONES] PALABRAS CLAVE\n" "\n" "Ejemplo:\n" -"# Buscar aplicaciones, bases o entornos de ejecución de forma remota por palabras clave\n" +"# Buscar aplicaciones, bases o entornos de ejecución de forma remota por " +"palabras clave\n" "ll-cli search org.deepin.demo\n" "# Buscar entornos de ejecución de forma remota por nombre\n" "ll-cli search org.deepin.base --type=runtime\n" @@ -416,10 +420,12 @@ msgid "Specify the Keywords" msgstr "Especificar las Palabras Clave" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" -"Filtrar resultados especificando el tipo: \"tiempo de ejecución\", \"base\"," -" \"aplicación\" o \"todos\"." +"Filtrar resultados especificando el tipo: \"tiempo de ejecución\", \"base\", " +"\"aplicación\" o \"todos\"." #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -482,7 +488,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Uso: ll-cli repo SUBCOMANDO [OPCIONES]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Añadir un nuevo repositorio" @@ -491,21 +497,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo add [OPCIONES] NOMBRE URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Especificar el nombre del repositorio" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "URL del repositorio" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Especificar el nombre del repositorio" @@ -514,7 +522,7 @@ msgid "Modify repository URL" msgstr "Modificar la URL del repositorio" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Eliminar un repositorio" @@ -525,7 +533,7 @@ msgstr "Uso: ll-cli repo remove [OPCIONES] NOMBRE" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Actualizar la URL del repositorio" @@ -533,7 +541,7 @@ msgstr "Actualizar la URL del repositorio" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo update [OPCIONES] NOMBRE URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Establecer un nombre de repositorio predeterminado" @@ -542,7 +550,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Uso: ll-cli repo set-default [OPCIONES] NOMBRE" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Mostrar información del repositorio" @@ -562,66 +570,82 @@ msgstr "Usage: ll-cli repo set-priority ALIAS PRIORITY" msgid "Priority of the repo" msgstr "Prioridad del repositorio" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "" "Mostrar información sobre aplicaciones o entornos de ejecución instalados" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Uso: ll-cli info [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "" "Especificar el ID de la aplicación, también puede ser un archivo .layer" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Mostrar los archivos exportados de la aplicación instalada" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Uso: ll-cli content [OPCIONES] APP" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Especificar el ID de la aplicación instalada" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Eliminar la base o el entorno de ejecución no utilizado" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Uso: ll-cli prune [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Mostrar la información de la aplicación instalada." -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Uso: ll-cli inspect [OPCIONES]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Especifica el ID del proceso" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "ID de proceso no válido" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Formato de PID no válido" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Especifique la aplicación instalada (base o tiempo de ejecución)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "versión de linyaps CLI " @@ -705,7 +729,7 @@ msgstr "Instalado" msgid "New" msgstr "Nuevo" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -713,51 +737,52 @@ msgstr "" "linyaps builder CLI \n" "Un programa CLI para construir aplicaciones linyaps\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-builder [OPCIONES] [SUBCOMANDO]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si encuentras algún problema durante el uso\n" -"Puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"Puede reportar errores al equipo de linyaps en este proyecto: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Crear proyecto de plantilla de compilación de linyaps" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Uso: ll-builder create [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Nombre del proyecto" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Construir un proyecto de linyaps" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder build [OPCIONES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Ruta del archivo de linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Entrar en el contenedor para ejecutar comandos en lugar de construir " "aplicaciones" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -765,198 +790,206 @@ msgstr "" "Usar solo archivos locales. Esto implica que se configurarán --skip-fetch-" "source y --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "" "Construir paquetes de desarrollo completos, se requiere tiempo de ejecución" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Omitir la obtención de fuentes" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Omitir la dependencia de extracción" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Omitir la ejecución del contenedor" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Omitir la confirmación de la salida de la compilación" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Omitir la comprobación de la salida" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Omitir el despojo de los símbolos de depuración" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Construir en un entorno de red aislado" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Ejecutar la aplicación Linyaps creada" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder run [OPCIONES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Ejecutar módulo especificado. ej: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" "Entrar en el contenedor para ejecutar comandos en lugar de ejecutar la " "aplicación" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Ejecutar en modo depuración (habilitar módulo de desarrollo)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Lista de aplicaciones de Linyaps creadas" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Uso: ll-builder list [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Eliminar la aplicación Linyaps creada" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Uso: ll-builder remove [OPCIONES] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Exportar a la capa o uab de linyaps" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Uso: ll-builder export [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Icono de uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Exportar uab completamente" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Exportar a archivo de capa linyaps (obsoleto)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Utilice un cargador personalizado" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "No exportar el módulo de desarrollo" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Archivo de salida" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Enviar la aplicación linyaps al repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Uso: ll-builder push [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "URL del repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Nombre del repositorio remoto" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Enviar módulo único" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Importar la capa de linyaps para construir el repositorio" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Uso: ll-builder import [OPCIONES] CAPA" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Ruta del archivo de la capa" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Importar carpeta de capa linyaps al repositorio de compilación" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Uso: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Ruta de la carpeta de capa" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Extraer la capa de linyaps a la carpeta" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Uso: ll-builder extract [OPCIONES] CAPA DIR" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Carpeta de destino" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Mostrar y gestionar repositorios" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Uso: ll-builder repo [OPCIONES] SUBCOMANDO" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo add [OPCIONES] NOMBRE URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Uso: ll-builder repo remove [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo update [OPCIONES] NOMBRE URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Uso: ll-builder repo set-default [OPCIONES] NOMBRE" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Uso: ll-builder repo show [OPCIONES]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "versión de la herramienta de construcción de linyaps " diff --git a/po/fi.po b/po/fi.po index 8dce6baef..7ce32b3d0 100644 --- a/po/fi.po +++ b/po/fi.po @@ -2,67 +2,68 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Kimmo Kujansuu , 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Kimmo Kujansuu , 2025\n" -"Language-Team: Finnish (https://app.transifex.com/linuxdeepin/teams/3976/fi/)\n" +"Language-Team: Finnish (https://app.transifex.com/linuxdeepin/teams/3976/" +"fi/)\n" +"Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Lupa evätty. Tarkista oletko root-käyttäjänä." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Moduulin asentamiseksi on ensin asennettava sovellus." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "Moduuli on jo asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Asennus epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "Moduulia ei löytynyt palvelimelta." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Poistaminen epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "Päivitys epäonnistui" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "Sovellusta ei ole asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "Uusin versio on jo asennettu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -72,7 +73,7 @@ msgstr "" "1. Tarkista internetyhteys\n" "2. Tarkista välityspalvelimen asetukset, jos niitä käytetään" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -80,15 +81,15 @@ msgstr "" "Sovellus on jo asennettu. Jos haluat vaihtaa sen, kokeile \"ll-cli install " "%1 --force\"" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "Sovellusta %1 ei löydy palvelimelta." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "Moduulia asennettaessa ei voitu määrittää versiota." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -96,7 +97,7 @@ msgstr "" "Uusin versio on asennettu. Jos haluat vaihtaa sen, kokeile \"ll-cli install " "%1/version --force\"" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -110,11 +111,11 @@ msgstr "" "linyaps CLI\n" "Ohjelma sovellusten suorittamiseen ja ajoympäristön hallintaan\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Tulosta tämä ohje ja poistu" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Kaikki ohjeet" @@ -125,13 +126,15 @@ msgstr "Käyttö: ll-cli [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jos havaitset ongelmia käytön aikana,\n" -"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-" +"Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Näytä versio" @@ -147,7 +150,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Käytä json-formaattia tuloksiin" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Parametri on tyhjä, anna kelvollinen parametri" @@ -306,8 +309,7 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" -msgstr "" -"Määritä sovelluksen id-tunnus. Voi olla myös .uab- tai .layer-tiedosto" +msgstr "Määritä sovelluksen id-tunnus. Voi olla myös .uab- tai .layer-tiedosto" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -360,8 +362,8 @@ msgstr "Käyttö: ll-cli upgrade [OPTIONS] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Määritä sovelluksen id-tunnus. Jos ei määritetä, kaikki sovellukset " "päivitetään" @@ -371,8 +373,8 @@ msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" msgstr "" -"Etsi palvelimen arkistosta tietyn tekstin sisältävät " -"sovellukset/ajoympäristöt" +"Etsi palvelimen arkistosta tietyn tekstin sisältävät sovellukset/" +"ajoympäristöt" #: ../apps/ll-cli/src/main.cpp:378 msgid "" @@ -391,7 +393,8 @@ msgstr "" "Käyttö: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Esimerkki:\n" -"# etsi palvelimelta sovellukse(t), alusta(t) tai ajoympäristö(t) hakusanoilla\n" +"# etsi palvelimelta sovellukse(t), alusta(t) tai ajoympäristö(t) " +"hakusanoilla\n" "ll-cli search org.deepin.demo\n" "# etsi ajoympäristö palvelimelta nimellä\n" "ll-cli search org.deepin.base --type=runtime\n" @@ -407,7 +410,9 @@ msgid "Specify the Keywords" msgstr "Määrittele hakusanat" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" "Suodata tulokset tyypillä. Joku seuraavista: \"runtime\", \"base\", \"app\" " "tai \"all\"" @@ -472,7 +477,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Käyttö: ll-cli repo SUBCOMMAND [OPTIONS]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Lisää uusi ohjelma-arkisto" @@ -481,21 +486,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Käyttö: ll-cli repo add [OPTIONS] NAME URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Määritä arkiston nimi" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "Arkiston verkko-osoite" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias arkiston nimelle" @@ -504,7 +511,7 @@ msgid "Modify repository URL" msgstr "Muokkaa arkiston verkko-osoitetta" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Poista ohjelma-arkisto" @@ -515,7 +522,7 @@ msgstr "Käyttö: ll-cli repo remove [OPTIONS] NAME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Päivitä arkiston verkko-osoite" @@ -523,7 +530,7 @@ msgstr "Päivitä arkiston verkko-osoite" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Käyttö: ll-cli repo update [OPTIONS] NAME URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Aseta oletusarkiston nimi" @@ -532,7 +539,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Käyttö: ll-cli repo set-default [OPTIONS] NAME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Näytä ohjelma-arkiston tiedot" @@ -552,64 +559,80 @@ msgstr "Käyttö: ll-cli repo set-priority ALIAS PRIORITY" msgid "Priority of the repo" msgstr "Arkiston prioriteetti" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Näytä tiedot sovelluksista tai ajoympäristöistä" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Käyttö: ll-cli info [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Määritä sovelluksen id-tunnus. Voi olla myös .layer-tiedosto" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Näytä asennetun sovelluksen viedyt tiedostot" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Käyttö: ll-cli content [OPTIONS] APP" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Määritä sovelluksen id-tunnus" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Poista käyttämätön alusta tai ajoympäristö" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Käyttö: ll-cli prune [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Näytä sovelluksen tiedot" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Käyttö: ll-cli inspect [OPTIONS]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Määritä prosessin id-tunnus" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Väärä prosessin id-tunnus" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Väärä pid formaatti" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Määritä asennettu sovellus (base tai runtime)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "linyaps CLI versio " @@ -693,7 +716,7 @@ msgstr "Asennettu" msgid "New" msgstr "Uusi" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -701,247 +724,256 @@ msgstr "" "linyaps builder CLI \n" "Ohjelma jolla linyaps-sovellukset käännetään\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Käyttö: ll-builder [OPTIONS] [SUBCOMMAND]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jos havaitset ongelmia käytön aikana,\n" -"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-" +"Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Rakenna linyaps malliprojekti" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Käyttö: ll-builder create [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Projektin nimi" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Rakenna linyaps projekti" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Käyttö: ll-builder build [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Tiedoston linglong.yaml tiedostopolku" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Kirjoita kontin nimi, suorittaaksesi komento sovelluksen rakentamisen sijaan" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Käytä vain paikallisia tiedostoja. Tarkoittaa, että --skip-fetch-source ja " -"--skip-pull-depend asetetaan" +"Käytä vain paikallisia tiedostoja. Tarkoittaa, että --skip-fetch-source ja --" +"skip-pull-depend asetetaan" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Rakenna kehityspaketteja kokonaan, ajoympäristö tarvitaan" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Ohita fetch sources" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Ohita pull dependency" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Ohita run container" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Ohita commit build output" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Ohita output check" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Ohita strip debug symbols" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Rakenna eristettyyn verkkoympäristöön" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Suorita rakennettu linyaps sovellus" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Käyttö: ll-builder run [OPTIONS] [COMMAND...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Suorita tiettyjä moduuleja, kuten: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" "Kirjoita kontin nimi, suorittaaksesi komento sovelluksen suorittamiseksi" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Suorita vikasietotilassa (ottaa käyttöön kehitysmoduulit)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Luettelo rakennetuista linyaps sovelluksista" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Käyttö: ll-builder list [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Poista rakennettu linyaps sovellus" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Käyttö: ll-builder remove [OPTIONS] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Vie linyaps kerrokseen tai uab:iin" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Käyttö: ll-builder export [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Uab kuvake (valinnainen)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Vie uab kokonaan" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Vie linyaps tiedosto-kerrokseen (vanhentunut)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Käytä mukautettua lataajaa" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Älä vie kehitysmoduulia" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Tulostustiedosto" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Siirrä linyaps sovellus palvelimen arkistoon" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Käyttö: ll-builder push [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "Arkiston verkko-osoite" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Arkiston nimi" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Lähetä yksittäinen moduuli" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Tuo linyaps kerros rakennus-arkistoon" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Käyttö: ll-builder import [OPTIONS] LAYER" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Tason tiedostopolku" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Tuo linyaps kerroshakemisto rakennus-arkistoon" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Käyttö: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Tason hakemistopolku" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Pura linyaps kerros hakemistoon" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Käyttö: ll-builder extract [OPTIONS] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Kohdehakemisto" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Näytä ja hallitse ohjelma-arkistoja" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Käyttö: ll-builder repo [OPTIONS] SUBCOMMAND" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Käyttö: ll-builder repo add [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Käyttö: ll-builder repo remove [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Käyttö: ll-builder repo update [OPTIONS] NAME URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Käyttö: ll-builder repo set-default [OPTIONS] NAME" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Käyttö: ll-builder repo show [OPTIONS]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "linyaps build tool versio " diff --git a/po/linyaps.pot b/po/linyaps.pot index 716bd087f..03880f70e 100644 --- a/po/linyaps.pot +++ b/po/linyaps.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-10 14:30+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,75 +17,75 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -96,11 +96,11 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "" @@ -111,12 +111,12 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "" @@ -130,7 +130,7 @@ msgstr "" msgid "Use json format to output result" msgstr "" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" @@ -398,7 +398,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "" @@ -407,21 +407,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "" @@ -430,7 +432,7 @@ msgid "Modify repository URL" msgstr "" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "" @@ -441,7 +443,7 @@ msgstr "" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "" @@ -449,7 +451,7 @@ msgstr "" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "" @@ -458,7 +460,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "" @@ -478,64 +480,80 @@ msgstr "" msgid "Priority of the repo" msgstr "" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "" @@ -619,247 +637,255 @@ msgstr "" msgid "New" msgstr "" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" msgstr "" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "" -#: ../apps/ll-builder/src/main.cpp:747 +#: ../apps/ll-builder/src/main.cpp:808 msgid "Enter the container to execute command instead of building applications" msgstr "" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "" diff --git a/po/pl.po b/po/pl.po index 0ae5718d1..df10cf10b 100644 --- a/po/pl.po +++ b/po/pl.po @@ -2,67 +2,70 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Janusz Ruchała, 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Janusz Ruchała, 2025\n" -"Language-Team: Polish (https://app.transifex.com/linuxdeepin/teams/3976/pl/)\n" +"Language-Team: Polish (https://app.transifex.com/linuxdeepin/teams/3976/" +"pl/)\n" +"Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: pl\n" -"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Odmowa dostępu, sprawdź, czy uruchamiasz jako root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Aby zainstalować moduł, najpierw zainstaluj aplikację." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "Moduł jest już zainstalowany." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Nie udało się zainstalować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "Nie znaleziono modułu w zdalnym repozytorium." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Nie udało się odinstalować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "Nie udało się zaktualizować" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "Aplikacja nie jest zainstalowana." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "Najnowsza wersja jest już zainstalowana." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -72,7 +75,7 @@ msgstr "" "1. Sprawdzić swoje połączenie sieciowe\n" "2. Jeśli korzystasz, sprawdzić ustawienia proxy" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -80,15 +83,15 @@ msgstr "" "Aplikacja jest już zainstalowana. Jeśli chcesz ją zastąpić, spróbuj 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "Aplikacja %1 nie została znaleziona w zdalnym repozytorium" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "Nie można ustawić wersji podczas instalowania modułu." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -96,7 +99,7 @@ msgstr "" "Najnowsza wersja jest już zainstalowana. Jeśli chcesz ją zastąpić, spróbuj " "'ll-cli install %1/version --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -109,13 +112,14 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Aplikacja wiersza poleceń do uruchamiania i zarządzania aplikacjami oraz środowiskami wykonawczymi\n" +"Aplikacja wiersza poleceń do uruchamiania i zarządzania aplikacjami oraz " +"środowiskami wykonawczymi\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Wyświetl tę wiadomość i zakończ" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Rozwiń pomoc" @@ -126,14 +130,15 @@ msgstr "Polecenie: ll-cli [OPCJE] [PODKOMENDA]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jeśli znajdziesz jakieś problemy, \n" "możesz zgłosić błąd do zespołu linyaps pod tym adresem: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Pokaż wersję" @@ -149,7 +154,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Użyj formatu JSON do wyświetlenia wyniku." -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Parametr wejściowy jest pusty, wprowadź prawidłowy parametr" @@ -361,8 +366,8 @@ msgstr "Polecenie: ll-cli upgrade [OPCJE] [APLIKACJA]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Podaj ID aplikacji. Jeśli nie podasz, wszystkie aplikacje zostaną " "zaktualizowane." @@ -408,8 +413,12 @@ msgid "Specify the Keywords" msgstr "Podaj słowa kluczowe" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" -msgstr "Filtruj wyniki wybranego typu. Na przykład \"runtime\", \"base\", \"app\" lub \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" +msgstr "" +"Filtruj wyniki wybranego typu. Na przykład \"runtime\", \"base\", \"app\" " +"lub \"all\"" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -425,8 +434,7 @@ msgstr "Pokaż wszystkie wersje aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:411 msgid "List installed application(s), base(s) or runtime(s)" -msgstr "" -"Wyświetl listę zainstalowanych aplikacji, baz i środowisk wykonawczych" +msgstr "Wyświetl listę zainstalowanych aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:414 msgid "" @@ -459,8 +467,8 @@ msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" msgstr "" -"Wyświetl listę najnowszych wersji zainstalowanych aplikacji, baz i środowisk" -" wykonawczych" +"Wyświetl listę najnowszych wersji zainstalowanych aplikacji, baz i środowisk " +"wykonawczych" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -471,7 +479,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Polecenie: ll-cli repo PODKOMENDA [OPCJE]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Dodaj nowe repozytorium" @@ -480,21 +488,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Polecenie: ll-cli repo add [OPCJE] NAZWA URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Podaj nazwę repozytorium" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "Adres URL repozytorium" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias repozytorium" @@ -503,7 +513,7 @@ msgid "Modify repository URL" msgstr "Zmień adres URL repozytorium" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Usuń repozytorium" @@ -514,7 +524,7 @@ msgstr "Polecenie: ll-cli repo remove [OPCJE] NAZWA" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Zaktualizuj adres URL repozytorium" @@ -522,7 +532,7 @@ msgstr "Zaktualizuj adres URL repozytorium" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Polecenie: ll-cli repo update [OPCJE] NAZWA URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Ustaw domyślną nazwę repozytorium" @@ -531,7 +541,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Polecenie: ll-cli repo set-default [OPCJE] NAZWA" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Pokaż informacje repozytorium" @@ -551,65 +561,81 @@ msgstr "Polecenie: ll-cli repo set-priority ALIAS PRIORYTET" msgid "Priority of the repo" msgstr "Priorytet repozytorium" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "" "Pokaż informacje o zainstalowanych aplikacjach i środowiskach wykonawczych" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Polecenie: ll-cli info [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Podaj ID aplikacji, może być to również plik .layer" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Pokaż wyeksportowane pliki zainstalowanych aplikacji" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Polecenie: ll-cli content [OPCJE] APLIKACJA" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Podaj ID zainstalowanej aplikacji" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Usuń nieużywaną bazę lub środowisko wykonawcze" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Polecenie: ll-cli prune [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Pokaż informacje zainstalowanej aplikacji" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Polecenie: ll-cli inspect [OPCJE]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Podaj ID procesu" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Nieprawidłowe ID procesu" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Nieprawidłowy format PID" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Podaj zainstalowaną aplikację (baza lub środowisko wykonawcze)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "Wersja linyaps CLI " @@ -693,7 +719,7 @@ msgstr "Zainstalowana" msgid "New" msgstr "Nowa" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -701,249 +727,257 @@ msgstr "" "linyaps builder CLI \n" "Aplikacja wiersza poleceń do budowania aplikacji\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Polecenie: ll-builder [OPCJE] [PODKOMENDA]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jeśli znajdziesz jakieś problemy, \n" "Możesz zgłosić błąd do zespołu linyaps klikając ten link: \n" "https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Utwórz szablon budowania projektu linyaps" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Polecenie: ll-builder create [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Nazwa projektu" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Zbuduj projekt linyaps" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Polecenie: ll-builder build [OPCJE] [KOMENDA...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Ścieżka pliku linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Wykonuj polecenia wewnątrz kontenera, zamiast ciągle przebudowywać aplikacje" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Korzystaj tylko z plików lokalnych. To oznacza, że flagi --skip-fetch-source" -" i --skip-pull-depend będą ustawione" +"Korzystaj tylko z plików lokalnych. To oznacza, że flagi --skip-fetch-source " +"i --skip-pull-depend będą ustawione" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "" "Zbuduj ze wszystkimi pakietami dewelopera, wymagane przez środowisko " "wykonawcze" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Pomiń pobieranie źródeł" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Pomiń pobieranie zależności" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Pomiń uruchamianie kontenera" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Pomiń dane commitów buildu" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Pomiń kontrolę danych wyjściowych" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Pomiń usuwanie symboli debug" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Zbuduj w izolowanym środowisku sieciowym" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Uruchom zbudowaną aplikację linyaps" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Polecenie: ll-builder run [OPCJE] [KOMENDA...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Uruchom określony moduł. np. --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "Wykonuj polecenia wewnątrz kontenera, zamiast włączać aplikację" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Uruchom w trybie debug (włącz moduł develop)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Wyświetl listę zbudowanych aplikacji linyaps" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Polecenie: ll-builder list [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Usuń zbudowaną aplikację linyaps" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Polecenie: ll-builder remove [OPCJE] [APLIKACJA...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Eksportuj do warstwy linyaps lub uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Polecenie: ll-builder export [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Ikona uab (opcjonalne)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Eksportuj uab całkowicie" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Eksportuj do pliku warstwy linyaps (brak wsparcia)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Użyj własnego loadera" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Nie eksportuj modułu develop" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Plik wyjściowy" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Wyślij aplikację linyaps do zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Polecenie: ll-builder push [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "Adres URL zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Nazwa zdalnego repozytorium" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Wyślij pojedynczy moduł" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Importuj warstwę linyaps do repozytorium build" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Polecenie: ll-builder import [OPCJE] WARSTWA" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Ścieżka pliku layer" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Importuj katalog warstw linyaps do repozytorium build" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Polecenie: ll-builder import-dir ŚCIEŻKA" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Ścieżka katalogu layer" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Wypakuj warstwy linyaps do katalogu" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Polecenie: ll-builder extract [OPCJE] WARSTWA KATALOG" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Katalog docelowy" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Wyświetl i zarządzaj repozytoriami" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Polecenie: ll-builder repo [OPCJE] PODKOMENDA" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Polecenie: ll-builder repo add [OPCJE] NAZWA URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Polecenie: ll-builder repo remove [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Polecenie: ll-builder repo update [OPCJE] NAZWA URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Polecenie: ll-builder repo set-default [OPCJE] NAZWA" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Polecenie: ll-builder repo show [OPCJE]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "Wersja narzędzia budowania linyaps " diff --git a/po/pt_BR.po b/po/pt_BR.po index c25be15bc..f83e00dfa 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -2,70 +2,72 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Cassiano Molinari , 2025 # Wislley Marçal, 2025 # keven doria, 2025 # Alex, 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Alex, 2025\n" -"Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/teams/3976/pt_BR/)\n" +"Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/" +"teams/3976/pt_BR/)\n" +"Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % " +"1000000 == 0 ? 1 : 2;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "Permissão negada, verifique se você está executando como root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Para instalar o módulo, primeiro é necessário instalar o aplicativo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "O módulo já está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Falha na instalação" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "O módulo não pôde ser encontrado remotamente." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Falha na desinstalação" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "A atualização falhou" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "O aplicativo não está instalado." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "A versão mais recente já está instalada." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -75,7 +77,7 @@ msgstr "" "1. Verifique sua conexão com a internet.\n" "2. Verifique as configurações de proxy da rede, se utilizadas." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -83,15 +85,15 @@ msgstr "" "Aplicativo já instalado. Se você quiser substituí-lo, tente usar 'll-cli " "install %1 --force'" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "O aplicativo %1 não foi encontrado no repositório remoto." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "Não é possível especificar uma versão ao instalar um módulo." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -99,7 +101,7 @@ msgstr "" "A versão mais recente foi instalada. Se quiser substituí-la, tente usar 'll-" "cli install %1/version --force'." -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -111,13 +113,14 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Um programa em CLI para executar aplicativos e gerenciar aplicativos e runtimes\n" +"Um programa em CLI para executar aplicativos e gerenciar aplicativos e " +"runtimes\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Exibir esta mensagem de ajuda e sair" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Expandir toda a ajuda" @@ -128,13 +131,15 @@ msgstr "Uso: ll-cli [OPÇÕES] [SUBCOMANDO]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Se encontrar qualquer problema durante o uso,\n" -"Você pode reportar erros para o time linyaps sob este projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"Você pode reportar erros para o time linyaps sob este projeto: https://" +"github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Mostrar versão" @@ -150,11 +155,10 @@ msgstr "" msgid "Use json format to output result" msgstr "Usar o formato json para o resultado de saída" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" -msgstr "" -"Parâmetro de entrada está vazio, por favor informe um parâmetro válido" +msgstr "Parâmetro de entrada está vazio, por favor informe um parâmetro válido" #: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" @@ -238,8 +242,8 @@ msgstr "Executar comandos na sandbox atualmente em execução" #: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" -"Especificar a instância de execução do aplicativo (você pode obter isto pelo" -" comando ps)" +"Especificar a instância de execução do aplicativo (você pode obter isto pelo " +"comando ps)" #: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" @@ -312,8 +316,7 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Especifique o ID do aplicativo, que também pode ser um arquivo .uab ou " -".layer" +"Especifique o ID do aplicativo, que também pode ser um arquivo .uab ou .layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -366,8 +369,8 @@ msgstr "Uso: ll-cli upgrade [OPÇÕES] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Especifique o ID do aplicativo. Caso não seja especificado, todos os " "aplicativos serão atualizados." @@ -398,7 +401,8 @@ msgstr "" "\n" "Exemplo:\n" "\n" -"# localizar remotamente aplicativo(s), base(s) ou runtime(s) por palavras-chave\n" +"# localizar remotamente aplicativo(s), base(s) ou runtime(s) por palavras-" +"chave\n" "ll-cli search org.deepin.demo\n" "\n" "# localizar remotamente runtime pelo nome\n" @@ -418,7 +422,9 @@ msgid "Specify the Keywords" msgstr "Especifique as palavras-chave" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" "Filtrar os resultados pelo tipo especificado. Um dos valores: \"runtime\", " "\"base\", \"app\" ou \"todos\"" @@ -465,7 +471,8 @@ msgstr "" "# exibir runtimes instalados\n" "ll-cli list --type=runtime\n" "\n" -"# exibir a lista das versões mais recentes dos aplicativos instalados que podem ser atualizados\n" +"# exibir a lista das versões mais recentes dos aplicativos instalados que " +"podem ser atualizados\n" "ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 @@ -485,7 +492,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Uso: ll-cli repo SUBCOMANDO [OPÇÕES]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Adicionar um novo repositório" @@ -494,21 +501,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo add [OPÇÕES] NOME URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Especifique o nome do repositório" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "URL do repositório" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias ​​do nome do repositório" @@ -517,7 +526,7 @@ msgid "Modify repository URL" msgstr "Modificar URL do repositório" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr " Remover um repositório" @@ -528,7 +537,7 @@ msgstr "Uso: ll-cli repo remove [OPÇÕES] NOME" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Atualizar a URL do repositório" @@ -536,7 +545,7 @@ msgstr "Atualizar a URL do repositório" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Uso: ll-cli repo update [OPÇÕES] NOME URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Defina um nome padrão para o repositório" @@ -545,7 +554,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Uso: ll-cli repo set-default [OPÇÕES] NOME" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Mostrar informações do repositório" @@ -565,64 +574,80 @@ msgstr "Uso: ll-cli repo set-priority ALIAS PRIORITY" msgid "Priority of the repo" msgstr "Prioridade do repositório" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Exibir informações sobre aplicativos instalados ou tempos de execução" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Uso: ll-cli info [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Especifique o ID do aplicativo, que também pode ser um arquivo .layer" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Exibir os arquivos exportados do aplicativo instalado" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Uso: ll-cli content [OPÇÕES] APP" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Especifique o ID do aplicativo instalado" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Remova a base ou o tempo de execução não utilizado" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Uso: ll-cli prune [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Exibir as informações do aplicativo instalado" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Uso: ll-cli inspect [OPÇÕES]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Especifique o ID do processo" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "ID de processo inválido" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Formato PID inválido" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Especifique o aplicativo instalado (base ou tempo de execução)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "Versão CLI do linyaps" @@ -706,7 +731,7 @@ msgstr "Instalado" msgid "New" msgstr "Novo" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -714,50 +739,51 @@ msgstr "" "construtor linyaps CLI \n" "Um programa CLI para construir um aplicativo Linyaps\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Uso: ll-builder [OPÇÕES] [SUBCOMANDO]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Se você encontrar algum problema durante o uso,\n" -"Você pode reportar bugs para a equipe linyaps neste projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"Você pode reportar bugs para a equipe linyaps neste projeto: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Criar projeto de modelo de construção linyaps" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Uso: ll-builder create [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Nome do projeto" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Crie um projeto linyaps" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder build [OPÇÕES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Caminho do arquivo linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Entre no contêiner para executar o comando em vez de construir aplicativos" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -765,196 +791,204 @@ msgstr "" "Use apenas arquivos locais. Isso implica que --skip-fetch-source e --skip-" "pull-depend serão definidos" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Crie pacotes de desenvolvimento completos, o tempo de execução requer" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Pular busca de fontes" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Pular dependência de pull" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Pular execução do contêiner" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Pular saída de confirmação de compilação" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Pular verificação de saída" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Símbolos de depuração de faixa de salto" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Construir em um ambiente de rede isolado" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Execute o aplicativo Linyaps criado" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Uso: ll-builder run [OPÇÕES] [COMANDO...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Execute o módulo especificado. Por exemplo: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" "Entre no contêiner para executar o comando em vez de executar o aplicativo" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Executar em modo de depuração (habilitar módulo de desenvolvimento)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Lista de aplicativos Linyaps criados" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Uso: ll-builder list [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Remover aplicativo linyaps construído" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Uso: ll-builder remove [OPÇÕES] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Exportar para camada linyaps ou uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Uso: ll-builder export [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Ícone Uab (opcional)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Exportar uab completamente" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Exportar para arquivo de camada Linyaps (obsoleto)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Usar carregador personalizado" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Não exporte o módulo de desenvolvimento" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Arquivo de saída" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Enviar aplicativo Linyaps para repositório remoto" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Uso: ll-builder push [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "URL do repositório remoto" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Nome do repositório remoto" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Empurre um único módulo" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Importar camada linyaps para construir repositório" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Uso: ll-builder import [OPÇÕES] CAMADA" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Caminho do arquivo de camada" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Importar diretório da camada linyaps para construir repositório" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Uso: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Caminho do diretório da camada" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Extrair camada linyaps para diretório" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Uso: ll-builder extract [OPÇÕES] LAYER DIR" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Diretório de destino" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Exibir e gerenciar repositórios" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Uso: ll-builder repo [OPÇÕES] SUBCOMANDO" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo add [OPÇÕES] NOME URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Uso: ll-builder repo remove [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Uso: ll-builder repo update [OPÇÕES] NOME URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Uso: ll-builder repo set-default [OPÇÕES] NOME" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Uso: ll-builder repo show [OPÇÕES]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "versão da ferramenta de construção linyaps" diff --git a/po/sq.po b/po/sq.po index a24cd17ae..b26c7fe26 100644 --- a/po/sq.po +++ b/po/sq.po @@ -2,94 +2,95 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Besnik Bleta , 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Besnik Bleta , 2025\n" -"Language-Team: Albanian (https://app.transifex.com/linuxdeepin/teams/3976/sq/)\n" +"Language-Team: Albanian (https://app.transifex.com/linuxdeepin/teams/3976/" +"sq/)\n" +"Language: sq\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: sq\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" "2. Verify network proxy settings if used" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" @@ -104,11 +105,11 @@ msgstr "" "linyaps CLI\n" "Një program CLI për të xhiruar dhe administruar aplikacion dhe “runtime”\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Shtyp këtë mesazh ndihme dhe dil" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Zgjero krejt ndihmën" @@ -119,13 +120,15 @@ msgstr "Përdorimi: ll-cli [MUNDËSI] [NËNURDHRA]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Nëse gjetët çfarëdo problemi gjatë përdorimit\n" -"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Shfaq versionin" @@ -139,7 +142,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Përdor formatin json për të dhënë përfundimin" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "" @@ -356,8 +359,8 @@ msgstr "Përdorimi: ll-cli upgrade [MUNDËSI] [APLIKACION]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" #: ../apps/ll-cli/src/main.cpp:374 @@ -386,7 +389,9 @@ msgid "Specify the Keywords" msgstr "Jepni Fjalëkyçet" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" #: ../apps/ll-cli/src/main.cpp:400 @@ -435,7 +440,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Përdorimi: ll-cli repo NËNURDHËR [MUNDËSI]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Shtoni depo të re" @@ -444,21 +449,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Përdorimi: ll-cli repo add [MUNDËSI] EMËR URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Jepni emrin e depos" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "URL e depos" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Alias i emrit të depos" @@ -467,7 +474,7 @@ msgid "Modify repository URL" msgstr "Ndryshoni URL depo" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Hiqni një depo" @@ -478,7 +485,7 @@ msgstr "Përdorimi: ll-cli repo remove [MUNDËSI] EMËR" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Përditësoni URL-në e depos" @@ -486,7 +493,7 @@ msgstr "Përditësoni URL-në e depos" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Përdorimi: ll-cli repo update [MUNDËSI] EMËR URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Caktoni një emër depoje parazgjedhje" @@ -495,7 +502,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Përdorimi: ll-cli repo set-default [MUNDËSI] EMËR" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Shfaq hollësi depoje" @@ -515,64 +522,80 @@ msgstr "Përdorimi: ll-cli repo set-priority ALIAS PËRPARËSI" msgid "Priority of the repo" msgstr "Përparësi e depos" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Shfaq hollësi rreth aplikacionesh të instaluar ose runtime-sh" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Përdorimi: ll-cli info [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Specifikoni ID-në e aplikacionit dhe mund të jetë një kartelë .layer" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Shfaq kartelat e eksportuara të aplikacionit të instaluar" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Përdorimi: ll-cli content [MUNDËSI] APLIKACION" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Specifikoni ID aplikacioni të instaluar" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Hiq bazën ose runtime-n e papërdorur" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Përdorimi: ll-cli prune [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Shfaq hollësitë e aplikacionit të instaluar" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Përdorimi: ll-cli inspect [MUNDËSI]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Jepni ID procesi" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "ID e pavlefshme procesi" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Format i pavlefshëm PID" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Specifikoni aplikacionin e instaluar (bazë ose “runtime”)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "Version CLI linyaps " @@ -656,7 +679,7 @@ msgstr "Të instaluar" msgid "New" msgstr "I ri" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -664,51 +687,52 @@ msgstr "" "linyaps builder CLI \n" "Një program CLI për montim aplikacionesh linyaps\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Përdorimi: ll-builder [MUNDËSI] [NËNURDHËR]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Nëse gjetët çfarëdo problemi gjatë përdorimit\n" -"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Krijoni projekt gjedhe montimi linyaps" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Përdorimi: ll-builder create [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Emër projekti" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Ndërtoni një projekt linyaps" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Përdorimi: ll-builder build [MUNDËSI] [URDHËR…]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Shteg kartele linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "" "Jepni kontejnerin ku të ekzekutohet urdhri, në vend se të montohen " "aplikacione" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" @@ -716,197 +740,205 @@ msgstr "" "Përdor vetëm kartela vendore. Kjo nënkupton se do të përdoren --skip-fetch-" "source dhe --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Monto paketa të plota zhvillimi, lyp “runtime”" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Anashkalo sjellje burimesh" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Anashkalo marrje varësish" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Anashkalo xhirim kontejneri" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Anashkalo kontroll të ç’jepet si përfundim" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Anashkalo heqje simbolesh diagnostikimi" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Montoni në një mjedis të izoluar rrjeti" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Përdorimi: ll-builder run [MUNDËSI] [URDHËR…]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Xhiro modulin e treguar. P. sh.: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "" "Për ekzekutimin e urdhrit hyr në kontejner, në vend të xhirimit të " "aplikacionit" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Xhiroje nën mënyrën diagnostikim (aktivizoni modulin “develop”)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Përdorimi: ll-builder list [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Përdorimi: ll-builder remove [MUNDËSI] [APLIKACION…]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Eksportoje te shtresë linyaps, ose uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Përdorimi: ll-builder export [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Ikonë uab (opsionale)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Përdor ngarkues vetjak" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Mos eksporto modulin e zhvillimit" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Kaloje aplikacionin linyaps te depoja e largët" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Përdorimi: ll-builder push [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "URL depoje të largët" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Emër depoje të largët" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Përdorimi: ll-builder import [MUNDËSI] SHTRESË" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Shteg kartele shtrese" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Përdorimi: ll-builder import-dir SHTEG" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Shteg drejtorie shtrese" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Përfto shtresë linyaps te drejtoria" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Përdorimi: ll-builder extract [MUNDËSI] SHTRESË DREJTORI" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Drejtori vendmbërritje" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Shfaqni dhe administroni depo" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Përdorimi: ll-builder repo [MUNDËSI] NËNURDHËR" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Përdorimi: ll-builder repo add [MUNDËSI] EMËR URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Përdorimi: ll-builder repo remove [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Përdorimi: ll-builder repo update [MUNDËSI] EMËR URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Përdorimi: ll-builder repo set-default [MUNDËSI] EMËR" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Përdorimi: ll-builder repo show [MUNDËSI]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "version mjeti montimesh linyaps" diff --git a/po/uk.po b/po/uk.po index a413c9518..ab583e5c8 100644 --- a/po/uk.po +++ b/po/uk.po @@ -2,69 +2,73 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Yuri Chornoivan , 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Yuri Chornoivan , 2025\n" -"Language-Team: Ukrainian (https://app.transifex.com/linuxdeepin/teams/3976/uk/)\n" +"Language-Team: Ukrainian (https://app.transifex.com/linuxdeepin/teams/3976/" +"uk/)\n" +"Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: uk\n" -"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "" "Відмовлено у доступі. Будь ласка, перевірте, чи запущено програму від імені " "користувача root." -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "Для встановлення модуля слід спочатку встановити програму." -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "Модуль вже встановлено." -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "Не вдалося встановити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "Не вдалося знайти модуль віддалено." -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "Не вдалося вилучити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "Не вдалося оновити" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "Програму не встановлено." -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "Вже встановлено найсвіжішу версію." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -74,7 +78,7 @@ msgstr "" "1. Перевірте працездатність з'єднання з інтернетом\n" "2. Перевірте параметри проксі-сервера, якщо такий використано" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" @@ -82,15 +86,15 @@ msgstr "" "Програму вже встановлено. Якщо ви хочете її замінити, спробуйте команду «ll-" "cli install %1 --force»" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "У віддаленому сховищі не знайдено програми %1." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "Не можна вказувати версію, якщо встановлюється модуль." -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" @@ -98,12 +102,11 @@ msgstr "" "Вже встановлено найсвіжішу версію. Якщо ви хочете її замінити, спробуйте " "команду «ll-cli install %1/version --force»" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" -"Не вдалося створити кеш. Будь ласка, вилучіть і повторно встановіть " -"програму." +"Не вдалося створити кеш. Будь ласка, вилучіть і повторно встановіть програму." #: ../apps/ll-cli/src/main.cpp:149 msgid "" @@ -111,13 +114,14 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Інтерфейс командного рядка для запуску програм і керування програмами та середовищами виконання програм\n" +"Інтерфейс командного рядка для запуску програм і керування програмами та " +"середовищами виконання програм\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "Вивести це довідкове повідомлення і завершити роботу" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "Розгорнути довідку" @@ -128,13 +132,15 @@ msgstr "Користування: ll-cli [ПАРАМЕТРИ] [ПІДКОМАН #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Якщо під час користування у вас виникнуть якісь проблеми,\n" -"ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"ви можете повідомити про вади команді розробників linyaps на сторінці " +"проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "Показати дані щодо версії" @@ -150,7 +156,7 @@ msgstr "" msgid "Use json format to output result" msgstr "Використати формат json для виведення результату" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "Вхідний параметр є порожнім. Будь ласка, вкажіть чинний параметр" @@ -312,8 +318,7 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Вказати за ідентифікатором програми, також можна вказати файл .uab або " -".layer" +"Вказати за ідентифікатором програми, також можна вказати файл .uab або .layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -366,8 +371,8 @@ msgstr "Користування: ll-cli upgrade [ПАРАМЕТРИ] [ПРОГ #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "" "Вказати ідентифікатор програми. Якщо не вказано, буде оновлено усі програми" @@ -412,7 +417,9 @@ msgid "Specify the Keywords" msgstr "Вказати ключові слова" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" msgstr "" "Фільтрувати результат за типом. Одне зі значень, «runtime», «base», «app» " "або «all»" @@ -476,7 +483,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "Користування: ll-cli repo ПІДКОМАНДА [ПАРАМЕТРИ]" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "Додати новий запис сховища" @@ -485,21 +492,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "Користування: ll-cli repo add [ПАРАМЕТРИ] НАЗВА АДРЕСА" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "Вказати назву сховища" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "Адреса сховища" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "Альтернативна назва сховища" @@ -508,7 +517,7 @@ msgid "Modify repository URL" msgstr "Змінити адресу сховища" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "Вилучити запис сховища" @@ -519,7 +528,7 @@ msgstr "Користування: ll-cli repo remove [ПАРАМЕТРИ] НАЗ #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "Оновити адресу сховища" @@ -527,7 +536,7 @@ msgstr "Оновити адресу сховища" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "Користування: ll-cli repo update [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "Встановити назву типового сховища" @@ -536,7 +545,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "Користування: ll-cli repo set-default [ПАРАМЕТРИ] НАЗВА" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "Вивести дані сховища" @@ -557,64 +566,80 @@ msgstr "" msgid "Priority of the repo" msgstr "Пріоритетність сховища" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "Вивести дані щодо встановлених програм або середовищ виконання" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "Користування: ll-cli info [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "Вказати за ідентифікатором програми, також можна вказати файл .layer" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "Показати експортовані файли встановленої програми" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "Користування: ll-cli content [ПАРАМЕТРИ] ПРОГРАМА" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "Вказати ідентифікатор встановленої програми" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "Вилучити невикористану основу або середовище виконання" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "Користування: ll-cli prune [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "Вивести дані щодо встановленої програми" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "Користування: ll-cli inspect [ПАРАМЕТРИ]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "Вказати ідентифікатор процесу" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "Некоректний ідентифікатор процесу" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "Некоректний формат PID" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "Вказати встановлену програму (основу або середовище виконання)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "Командний інтерфейс linyaps, версія " @@ -698,7 +723,7 @@ msgstr "Встановлено" msgid "New" msgstr "Створити" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -706,245 +731,254 @@ msgstr "" "Командний інтерфейс збиральника linyaps \n" "Командний інтерфейс для збирання програм linyaps\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "Користування: ll-builder [ПАРАМЕТРИ] [ПІДКОМАНДА]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Якщо під час користування у вас виникнуть якісь проблеми,\n" -"ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"ви можете повідомити про вади команді розробників linyaps на сторінці " +"проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "Створити проєкт шаблону збирання linyaps" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "Користування: ll-builder create [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "Назва проєкту" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "Зібрати проєкт linyaps" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "Користування: ll-builder build [ПАРАМЕТРИ] [КОМАНДА...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "Шлях до файла linglong.yaml" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "Введіть контейнер для виконання команди замість збирання програм" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Використовувати лише локальні файли. Неявно припускає, що буде встановлено " -"--skip-fetch-source і --skip-pull-depend" +"Використовувати лише локальні файли. Неявно припускає, що буде встановлено --" +"skip-fetch-source і --skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "Зібрати повні пакунки для розробки, потрібне середовище виконання" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "Пропустити отримання початкового коду" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "Пропустити отримання залежності" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "Пропустити запуск контейнера" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "Пропустити внесення результатів збирання" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "Пропустити перевірку результатів" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "Пропустити вилучення діагностичних символів" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "Зібрати у ізольованому середовищі у мережі" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "Запустити зібрану програму linyaps" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "Користування: ll-builder run [ПАРАМЕТРИ] [КОМАНДА...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "Запустити вказаний модуль. Приклад: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "Введіть контейнер для виконання команди замість запуску програми" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "Запустити у діагностичному режимі (увімкнути модуль розробки)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "Вивести список зібраних програм linyaps" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "Користування: ll-builder list [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "Вилучити зібрану програму linyaps" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "Користування: ll-builder remove [ПАРАМЕТРИ] [ПРОГРАМА...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "Експортувати до шару або uab linyaps" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "Користування: ll-builder export [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Піктограма uab (необов'язкова)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "Експортувати uab повністю" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "Експортувати до файла шару linyaps (застаріле)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "Використати нетиповий завантажувач" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "Не експортувати модуль розробки" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "Файл результатів" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "Записати програму linyaps до віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "Користування: ll-builder push [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "Адреса віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "Назва віддаленого сховища" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "Записати окремий модуль" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "Імпортувати шар linyaps для побудови сховища" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "Користування: ll-builder import [ПАРАМЕТРИ] ШАР" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "Шлях до файла шару" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "Імпортувати каталог шару linyaps для побудови сховища" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "Користування: ll-builder import-dir ШЛЯХ" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "Шлях до каталогу шару" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "Видобути шар linyaps до каталогу" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "Користування: ll-builder extract [ПАРАМЕТРИ] ШАР КАТАЛОГ" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "Каталог призначення" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "Показати сховища і керувати ними" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "Користування: ll-builder repo [ПАРАМЕТРИ] ПІДКОМАНДА" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "Користування: ll-builder repo add [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "Користування: ll-builder repo remove [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "Користування: ll-builder repo update [ПАРАМЕТРИ] НАЗВА АДРЕСА" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "Користування: ll-builder repo set-default [ПАРАМЕТРИ] НАЗВА" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "Користування: ll-builder repo show [ПАРАМЕТРИ]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "Інструмент збирання linyaps, версія " diff --git a/po/zh_CN.po b/po/zh_CN.po index aa178f1eb..e947ac79f 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -2,68 +2,69 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 # chang Gao, 2025 -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-09 14:53+0800\n" +"POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: chang Gao, 2025\n" -"Language-Team: Chinese (China) (https://app.transifex.com/linuxdeepin/teams/3976/zh_CN/)\n" +"Language-Team: Chinese (China) (https://app.transifex.com/linuxdeepin/" +"teams/3976/zh_CN/)\n" +"Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../libs/linglong/src/linglong/cli/cli.cpp:67 +#: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." msgstr "权限被拒绝,请检查是否以 root 身份运行。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:443 +#: ../libs/linglong/src/linglong/cli/cli.cpp:447 msgid "To install the module, one must first install the app." msgstr "要安装该模块,必须先安装此应用程序。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:446 +#: ../libs/linglong/src/linglong/cli/cli.cpp:450 msgid "Module is already installed." msgstr "模块已经安装" -#: ../libs/linglong/src/linglong/cli/cli.cpp:449 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1170 +#: ../libs/linglong/src/linglong/cli/cli.cpp:453 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1172 msgid "Install failed" msgstr "安装失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:452 +#: ../libs/linglong/src/linglong/cli/cli.cpp:456 msgid "The module could not be found remotely." msgstr "远程无法找到该模块" -#: ../libs/linglong/src/linglong/cli/cli.cpp:455 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 +#: ../libs/linglong/src/linglong/cli/cli.cpp:459 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1663 msgid "Uninstall failed" msgstr "卸载失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:458 +#: ../libs/linglong/src/linglong/cli/cli.cpp:462 msgid "Upgrade failed" msgstr "升级失败" -#: ../libs/linglong/src/linglong/cli/cli.cpp:461 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1582 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1655 +#: ../libs/linglong/src/linglong/cli/cli.cpp:465 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1586 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1659 msgid "Application is not installed." msgstr "应用未安装。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:464 +#: ../libs/linglong/src/linglong/cli/cli.cpp:468 msgid "Latest version is already installed." msgstr "已安装最新版本。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1144 -#: ../libs/linglong/src/linglong/cli/cli.cpp:1438 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1146 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1440 msgid "" "Network connection failed. Please:\n" "1. Check your internet connection\n" @@ -73,27 +74,29 @@ msgstr "" "1. 检查您的互联网连接\n" "2. 如使用代理,请确认网络代理设置" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1150 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1152 msgid "" "Application already installed, If you want to replace it, try using 'll-cli " "install %1 --force'" msgstr "应用已安装。如需覆盖安装,请尝试使用命令:ll-cli install %1 --force" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1156 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1158 msgid "Application %1 is not found in remote repo." msgstr "远程仓库中未找到应用 %1" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1160 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1162 msgid "Cannot specify a version when installing a module." msgstr "安装模块时不允许指定版本。" -#: ../libs/linglong/src/linglong/cli/cli.cpp:1164 +#: ../libs/linglong/src/linglong/cli/cli.cpp:1166 msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" -msgstr "当前已安装最新版本。如需覆盖安装,请尝试使用命令:ll-cli install %1/version --force" +msgstr "" +"当前已安装最新版本。如需覆盖安装,请尝试使用命令:ll-cli install %1/version " +"--force" -#: ../libs/linglong/src/linglong/cli/cli.cpp:2609 +#: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "缓存生成失败,请卸载并重新安装该应用程序。" @@ -106,11 +109,11 @@ msgstr "" "如意玲珑 CLI\n" "一个用于运行应用程序和管理应用程序和运行时的命令行工具\n" -#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:700 +#: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" msgstr "打印帮助信息并退出" -#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:701 +#: ../apps/ll-cli/src/main.cpp:162 ../apps/ll-builder/src/main.cpp:762 msgid "Expand all help" msgstr "展开所有帮助" @@ -121,13 +124,15 @@ msgstr "用法: ll-cli [选项] [子命令]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "如果在使用过程中遇到任何问题,\n" -"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" +"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-" +"Linyaps/linyaps/issues" #. add flags -#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:725 +#: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 msgid "Show version" msgstr "显示版本" @@ -141,7 +146,7 @@ msgstr "使用点对点 DBus,仅在 DBus 守护程序不可用时使用" msgid "Use json format to output result" msgstr "使用json格式输出结果" -#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:553 +#: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" msgstr "输入参数为空,请输入有效参数" @@ -353,8 +358,8 @@ msgstr "用法: ll-cli upgrade [选项] [应用]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be" -" upgraded" +"Specify the application ID. If it not be specified, all applications will be " +"upgraded" msgstr "指定应用程序名。如果未指定,将升级所有可升级的应用程序" #: ../apps/ll-cli/src/main.cpp:374 @@ -396,8 +401,11 @@ msgid "Specify the Keywords" msgstr "指定搜索关键词" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" -msgstr "按指定类型过滤结果。可选类型:\"runtime\"、\"base\"、\"app\"或 \"all\"。" +msgid "" +"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " +"\"all\"" +msgstr "" +"按指定类型过滤结果。可选类型:\"runtime\"、\"base\"、\"app\"或 \"all\"。" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -445,7 +453,9 @@ msgstr "" msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" -msgstr "显示当前已安装的应用(application)、基础环境(base)或运行时(runtime)的最新版本" +msgstr "" +"显示当前已安装的应用(application)、基础环境(base)或运行时(runtime)的最" +"新版本" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -456,7 +466,7 @@ msgid "Usage: ll-cli repo SUBCOMMAND [OPTIONS]" msgstr "用法: ll-cli repo [选项] 子命令" #. add repo sub command add -#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:892 +#: ../apps/ll-cli/src/main.cpp:449 ../apps/ll-builder/src/main.cpp:953 msgid "Add a new repository" msgstr "添加新的仓库" @@ -465,21 +475,23 @@ msgid "Usage: ll-cli repo add [OPTIONS] NAME URL" msgstr "用法: ll-cli repo add [选项] 名称 URL" #: ../apps/ll-cli/src/main.cpp:451 ../apps/ll-cli/src/main.cpp:464 -#: ../apps/ll-builder/src/main.cpp:894 +#: ../apps/ll-builder/src/main.cpp:955 msgid "Specify the repo name" msgstr "指定仓库名称" #: ../apps/ll-cli/src/main.cpp:454 ../apps/ll-cli/src/main.cpp:467 -#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:897 -#: ../apps/ll-builder/src/main.cpp:920 +#: ../apps/ll-cli/src/main.cpp:485 ../apps/ll-builder/src/main.cpp:958 +#: ../apps/ll-builder/src/main.cpp:981 msgid "Url of the repository" msgstr "仓库URL" #: ../apps/ll-cli/src/main.cpp:457 ../apps/ll-cli/src/main.cpp:474 #: ../apps/ll-cli/src/main.cpp:482 ../apps/ll-cli/src/main.cpp:493 -#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-builder/src/main.cpp:901 -#: ../apps/ll-builder/src/main.cpp:909 ../apps/ll-builder/src/main.cpp:917 -#: ../apps/ll-builder/src/main.cpp:929 +#: ../apps/ll-cli/src/main.cpp:505 ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:523 ../apps/ll-builder/src/main.cpp:962 +#: ../apps/ll-builder/src/main.cpp:970 ../apps/ll-builder/src/main.cpp:978 +#: ../apps/ll-builder/src/main.cpp:990 ../apps/ll-builder/src/main.cpp:998 +#: ../apps/ll-builder/src/main.cpp:1006 msgid "Alias of the repo name" msgstr "仓库别名" @@ -488,7 +500,7 @@ msgid "Modify repository URL" msgstr "修改仓库URL" #. add repo sub command remove -#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:906 +#: ../apps/ll-cli/src/main.cpp:472 ../apps/ll-builder/src/main.cpp:967 msgid "Remove a repository" msgstr "移除仓库" @@ -499,7 +511,7 @@ msgstr "用法: ll-cli repo remove [选项] 名称" #. add repo sub command update #. TODO: add --repo and --url options #. add repo sub command update -#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:914 +#: ../apps/ll-cli/src/main.cpp:480 ../apps/ll-builder/src/main.cpp:975 msgid "Update the repository URL" msgstr "更新仓库URL" @@ -507,7 +519,7 @@ msgstr "更新仓库URL" msgid "Usage: ll-cli repo update [OPTIONS] NAME URL" msgstr "用法: ll-cli repo update [选项] 名称 URL" -#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:926 +#: ../apps/ll-cli/src/main.cpp:491 ../apps/ll-builder/src/main.cpp:987 msgid "Set a default repository name" msgstr "设置默认仓库名称" @@ -516,7 +528,7 @@ msgid "Usage: ll-cli repo set-default [OPTIONS] NAME" msgstr "用法: ll-cli repo set-default [选项] 名称" #. add repo sub command show -#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:934 +#: ../apps/ll-cli/src/main.cpp:498 ../apps/ll-builder/src/main.cpp:1011 msgid "Show repository information" msgstr "显示仓库信息" @@ -536,64 +548,80 @@ msgstr "用法:ll-cli repo set-priority ALIAS PRIORITY" msgid "Priority of the repo" msgstr "仓库优先级" -#: ../apps/ll-cli/src/main.cpp:516 +#: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 +msgid "Enable mirror for the repo" +msgstr "启用仓库镜像" + +#: ../apps/ll-cli/src/main.cpp:515 +msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" +msgstr "用法: ll-cli repo enable-mirror [选项] 名称" + +#: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 +msgid "Disable mirror for the repo" +msgstr "禁用仓库镜像" + +#: ../apps/ll-cli/src/main.cpp:522 +msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" +msgstr "用法: ll-cli repo disable-mirror [选项] 名称" + +#: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" msgstr "显示已安装的应用程序或运行时的信息" -#: ../apps/ll-cli/src/main.cpp:519 +#: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" msgstr "用法: ll-cli info [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:523 +#: ../apps/ll-cli/src/main.cpp:537 msgid "Specify the application ID, and it can also be a .layer file" msgstr "指定应用程序名,也可以是如意玲珑.layer文件" -#: ../apps/ll-cli/src/main.cpp:530 +#: ../apps/ll-cli/src/main.cpp:544 msgid "Display the exported files of installed application" msgstr "显示已安装应用导出的文件" -#: ../apps/ll-cli/src/main.cpp:533 +#: ../apps/ll-cli/src/main.cpp:547 msgid "Usage: ll-cli content [OPTIONS] APP" msgstr "用法: ll-cli content [选项] 应用" -#: ../apps/ll-cli/src/main.cpp:534 +#: ../apps/ll-cli/src/main.cpp:548 msgid "Specify the installed application ID" msgstr "指定已安装应用程序名" #. add sub command prune -#: ../apps/ll-cli/src/main.cpp:539 +#: ../apps/ll-cli/src/main.cpp:553 msgid "Remove the unused base or runtime" msgstr "移除未使用的最小系统或运行时" -#: ../apps/ll-cli/src/main.cpp:541 +#: ../apps/ll-cli/src/main.cpp:555 msgid "Usage: ll-cli prune [OPTIONS]" msgstr "用法: ll-cli prune [选项]" -#: ../apps/ll-cli/src/main.cpp:546 +#: ../apps/ll-cli/src/main.cpp:560 msgid "Display the information of installed application" msgstr "显示已安装应用导出的文件" -#: ../apps/ll-cli/src/main.cpp:548 +#: ../apps/ll-cli/src/main.cpp:562 msgid "Usage: ll-cli inspect [OPTIONS]" msgstr "用法: ll-cli inspect [选项]" -#: ../apps/ll-cli/src/main.cpp:550 +#: ../apps/ll-cli/src/main.cpp:564 msgid "Specify the process id" msgstr "指定进程id" -#: ../apps/ll-cli/src/main.cpp:559 +#: ../apps/ll-cli/src/main.cpp:573 msgid "Invalid process id" msgstr "无效的进程id" -#: ../apps/ll-cli/src/main.cpp:562 +#: ../apps/ll-cli/src/main.cpp:576 msgid "Invalid pid format" msgstr "无效的pid格式" -#: ../apps/ll-cli/src/main.cpp:572 +#: ../apps/ll-cli/src/main.cpp:586 msgid "Specify the installed app(base or runtime)" msgstr "指定已安装的应用(base或runtime)" -#: ../apps/ll-cli/src/main.cpp:583 +#: ../apps/ll-cli/src/main.cpp:597 msgid "linyaps CLI version " msgstr "如意玲珑CLI版本 " @@ -677,7 +705,7 @@ msgstr "已安装" msgid "New" msgstr "新版本" -#: ../apps/ll-builder/src/main.cpp:698 +#: ../apps/ll-builder/src/main.cpp:759 msgid "" "linyaps builder CLI \n" "A CLI program to build linyaps application\n" @@ -685,243 +713,252 @@ msgstr "" "如意玲珑构建工具 CLI\n" "一个用于构建如意玲珑应用的命令行工具\n" -#: ../apps/ll-builder/src/main.cpp:703 +#: ../apps/ll-builder/src/main.cpp:764 msgid "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" msgstr "用法: ll-builder [选项] [子命令]" -#: ../apps/ll-builder/src/main.cpp:705 +#: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github." +"com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "如果在使用过程中遇到任何问题,\n" -"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" +"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-" +"Linyaps/linyaps/issues" -#: ../apps/ll-builder/src/main.cpp:729 +#: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" msgstr "创建如意玲珑构建模板" -#: ../apps/ll-builder/src/main.cpp:730 +#: ../apps/ll-builder/src/main.cpp:791 msgid "Usage: ll-builder create [OPTIONS] NAME" msgstr "用法: ll-builder create [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:731 +#: ../apps/ll-builder/src/main.cpp:792 msgid "Project name" msgstr "项目名称" -#: ../apps/ll-builder/src/main.cpp:739 +#: ../apps/ll-builder/src/main.cpp:800 msgid "Build a linyaps project" msgstr "构建如意玲珑项目" -#: ../apps/ll-builder/src/main.cpp:740 +#: ../apps/ll-builder/src/main.cpp:801 msgid "Usage: ll-builder build [OPTIONS] [COMMAND...]" msgstr "用法: ll-builder build [选项] [命令...]" -#: ../apps/ll-builder/src/main.cpp:741 ../apps/ll-builder/src/main.cpp:782 -#: ../apps/ll-builder/src/main.cpp:809 ../apps/ll-builder/src/main.cpp:847 +#: ../apps/ll-builder/src/main.cpp:802 ../apps/ll-builder/src/main.cpp:843 +#: ../apps/ll-builder/src/main.cpp:870 ../apps/ll-builder/src/main.cpp:908 msgid "File path of the linglong.yaml" msgstr "linglong.yaml的文件路径" -#: ../apps/ll-builder/src/main.cpp:747 -msgid "" -"Enter the container to execute command instead of building applications" +#: ../apps/ll-builder/src/main.cpp:808 +msgid "Enter the container to execute command instead of building applications" msgstr "进入容器执行命令而不是构建应用" -#: ../apps/ll-builder/src/main.cpp:750 +#: ../apps/ll-builder/src/main.cpp:811 msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "仅使用本地文件。这意味着将设置--skip-fetch-source和--skip-pull-depend" -#: ../apps/ll-builder/src/main.cpp:755 +#: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" msgstr "构建完整的开发包,binary是必须的" -#: ../apps/ll-builder/src/main.cpp:759 +#: ../apps/ll-builder/src/main.cpp:820 msgid "Skip fetch sources" msgstr "跳过获取源代码" -#: ../apps/ll-builder/src/main.cpp:762 +#: ../apps/ll-builder/src/main.cpp:823 msgid "Skip pull dependency" msgstr "跳过拉取依赖项" -#: ../apps/ll-builder/src/main.cpp:765 +#: ../apps/ll-builder/src/main.cpp:826 msgid "Skip run container" msgstr "跳过运行容器" -#: ../apps/ll-builder/src/main.cpp:768 +#: ../apps/ll-builder/src/main.cpp:829 msgid "Skip commit build output" msgstr "跳过提交构建输出" -#: ../apps/ll-builder/src/main.cpp:771 +#: ../apps/ll-builder/src/main.cpp:832 msgid "Skip output check" msgstr "跳过输出检查" -#: ../apps/ll-builder/src/main.cpp:774 +#: ../apps/ll-builder/src/main.cpp:835 msgid "Skip strip debug symbols" msgstr "跳过剥离调试符号" -#: ../apps/ll-builder/src/main.cpp:777 +#: ../apps/ll-builder/src/main.cpp:838 msgid "Build in an isolated network environment" msgstr "在隔离网络的环境中构建" #. add builder run -#: ../apps/ll-builder/src/main.cpp:780 +#: ../apps/ll-builder/src/main.cpp:841 msgid "Run built linyaps app" msgstr "运行构建好的应用程序" -#: ../apps/ll-builder/src/main.cpp:781 +#: ../apps/ll-builder/src/main.cpp:842 msgid "Usage: ll-builder run [OPTIONS] [COMMAND...]" msgstr "用法: ll-builder run [选项] [命令...]" -#: ../apps/ll-builder/src/main.cpp:788 +#: ../apps/ll-builder/src/main.cpp:849 msgid "Run specified module. eg: --modules binary,develop" msgstr "运行指定模块。例如: --modules binary,develop" -#: ../apps/ll-builder/src/main.cpp:794 +#: ../apps/ll-builder/src/main.cpp:855 msgid "Enter the container to execute command instead of running application" msgstr "进入容器执行命令而不是运行应用" -#: ../apps/ll-builder/src/main.cpp:797 +#: ../apps/ll-builder/src/main.cpp:858 msgid "Run in debug mode (enable develop module)" msgstr "在调试模式下运行(启用开发模块)" -#: ../apps/ll-builder/src/main.cpp:799 +#: ../apps/ll-builder/src/main.cpp:860 msgid "List built linyaps app" msgstr "列出已构建的应用程序" -#: ../apps/ll-builder/src/main.cpp:800 +#: ../apps/ll-builder/src/main.cpp:861 msgid "Usage: ll-builder list [OPTIONS]" msgstr "用法: ll-builder list [选项]" -#: ../apps/ll-builder/src/main.cpp:801 +#: ../apps/ll-builder/src/main.cpp:862 msgid "Remove built linyaps app" msgstr "删除已构建的应用程序" -#: ../apps/ll-builder/src/main.cpp:802 +#: ../apps/ll-builder/src/main.cpp:863 msgid "Usage: ll-builder remove [OPTIONS] [APP...]" msgstr "用法: ll-builder remove [OPTIONS] [APP...]" #. build export -#: ../apps/ll-builder/src/main.cpp:806 +#: ../apps/ll-builder/src/main.cpp:867 msgid "Export to linyaps layer or uab" msgstr "导出如意玲珑layer或uab" -#: ../apps/ll-builder/src/main.cpp:807 +#: ../apps/ll-builder/src/main.cpp:868 msgid "Usage: ll-builder export [OPTIONS]" msgstr "用法: ll-builder export [选项]" -#: ../apps/ll-builder/src/main.cpp:819 +#: ../apps/ll-builder/src/main.cpp:880 msgid "Uab icon (optional)" msgstr "Uab图标(可选)" -#: ../apps/ll-builder/src/main.cpp:823 +#: ../apps/ll-builder/src/main.cpp:884 msgid "Export uab fully" msgstr "全量导出uab" -#: ../apps/ll-builder/src/main.cpp:827 +#: ../apps/ll-builder/src/main.cpp:888 msgid "Export to linyaps layer file (deprecated)" msgstr "导出如意玲珑layer文件(已弃用)" -#: ../apps/ll-builder/src/main.cpp:830 +#: ../apps/ll-builder/src/main.cpp:891 msgid "Use custom loader" msgstr "使用自定义的loader" -#: ../apps/ll-builder/src/main.cpp:837 +#: ../apps/ll-builder/src/main.cpp:898 msgid "Don't export the develop module" msgstr "不导出develop模块" -#: ../apps/ll-builder/src/main.cpp:839 +#: ../apps/ll-builder/src/main.cpp:900 msgid "Output file" msgstr "输出文件" -#: ../apps/ll-builder/src/main.cpp:845 +#: ../apps/ll-builder/src/main.cpp:906 msgid "Push linyaps app to remote repo" msgstr "推送如意玲珑应用到远程仓库" -#: ../apps/ll-builder/src/main.cpp:846 +#: ../apps/ll-builder/src/main.cpp:907 msgid "Usage: ll-builder push [OPTIONS]" msgstr "用法: ll-builder push [选项]" -#: ../apps/ll-builder/src/main.cpp:850 +#: ../apps/ll-builder/src/main.cpp:911 msgid "Remote repo url" msgstr "远程仓库URL" -#: ../apps/ll-builder/src/main.cpp:853 +#: ../apps/ll-builder/src/main.cpp:914 msgid "Remote repo name" msgstr "远程仓库名" -#: ../apps/ll-builder/src/main.cpp:856 +#: ../apps/ll-builder/src/main.cpp:917 msgid "Push single module" msgstr "推送单个模块" -#: ../apps/ll-builder/src/main.cpp:860 +#: ../apps/ll-builder/src/main.cpp:921 msgid "Import linyaps layer to build repo" msgstr "导入如意玲珑layer文件到构建仓库" -#: ../apps/ll-builder/src/main.cpp:861 +#: ../apps/ll-builder/src/main.cpp:922 msgid "Usage: ll-builder import [OPTIONS] LAYER" msgstr "用法: ll-builder import [选项] LAYER文件" -#: ../apps/ll-builder/src/main.cpp:862 ../apps/ll-builder/src/main.cpp:879 +#: ../apps/ll-builder/src/main.cpp:923 ../apps/ll-builder/src/main.cpp:940 msgid "Layer file path" msgstr "layer文件路径" -#: ../apps/ll-builder/src/main.cpp:869 +#: ../apps/ll-builder/src/main.cpp:930 msgid "Import linyaps layer dir to build repo" msgstr "导入如意玲珑layer目录到构建仓库" -#: ../apps/ll-builder/src/main.cpp:871 +#: ../apps/ll-builder/src/main.cpp:932 msgid "Usage: ll-builder import-dir PATH" msgstr "用法: ll-builder import-dir PATH" -#: ../apps/ll-builder/src/main.cpp:872 +#: ../apps/ll-builder/src/main.cpp:933 msgid "Layer dir path" msgstr "layer目录路径" #. add build extract -#: ../apps/ll-builder/src/main.cpp:877 +#: ../apps/ll-builder/src/main.cpp:938 msgid "Extract linyaps layer to dir" msgstr "将如意玲珑layer文件解压到目录" -#: ../apps/ll-builder/src/main.cpp:878 +#: ../apps/ll-builder/src/main.cpp:939 msgid "Usage: ll-builder extract [OPTIONS] LAYER DIR" msgstr "用法: ll-builder extract [选项] LAYER文件 目录" -#: ../apps/ll-builder/src/main.cpp:882 +#: ../apps/ll-builder/src/main.cpp:943 msgid "Destination directory" msgstr "目标目录" #. add build repo -#: ../apps/ll-builder/src/main.cpp:887 +#: ../apps/ll-builder/src/main.cpp:948 msgid "Display and manage repositories" msgstr "显示和管理仓库" -#: ../apps/ll-builder/src/main.cpp:888 +#: ../apps/ll-builder/src/main.cpp:949 msgid "Usage: ll-builder repo [OPTIONS] SUBCOMMAND" msgstr "用法: ll-builder repo [选项] 子命令" -#: ../apps/ll-builder/src/main.cpp:893 +#: ../apps/ll-builder/src/main.cpp:954 msgid "Usage: ll-builder repo add [OPTIONS] NAME URL" msgstr "用法: ll-builder repo add [选项] 名称 URL" -#: ../apps/ll-builder/src/main.cpp:907 +#: ../apps/ll-builder/src/main.cpp:968 msgid "Usage: ll-builder repo remove [OPTIONS] NAME" msgstr "用法: ll-builder repo remove [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:915 +#: ../apps/ll-builder/src/main.cpp:976 msgid "Usage: ll-builder repo update [OPTIONS] NAME URL" msgstr "用法: ll-builder repo update [选项] 名称 URL" -#: ../apps/ll-builder/src/main.cpp:927 +#: ../apps/ll-builder/src/main.cpp:988 msgid "Usage: ll-builder repo set-default [OPTIONS] NAME" msgstr "用法: ll-builder repo set-default [选项] 名称" -#: ../apps/ll-builder/src/main.cpp:935 +#: ../apps/ll-builder/src/main.cpp:997 +msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" +msgstr "用法: ll-builder repo enable-mirror [选项] 名称" + +#: ../apps/ll-builder/src/main.cpp:1005 +msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" +msgstr "用法: ll-builder repo disable-mirror [选项] 名称" + +#: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" msgstr "用法: ll-builder repo show [选项]" -#: ../apps/ll-builder/src/main.cpp:940 +#: ../apps/ll-builder/src/main.cpp:1017 msgid "linyaps build tool version " msgstr "如意玲珑构建工具版本" From ce305639239ba00c8ddc550486d6f46bd275136b Mon Sep 17 00:00:00 2001 From: ComixHe Date: Fri, 4 Jul 2025 15:22:30 +0800 Subject: [PATCH 080/366] refactor: reimplement reusing container Signed-off-by: ComixHe --- apps/ll-init/CMakeLists.txt | 2 +- apps/ll-init/src/ll-init.cpp | 636 +++++++++++++++--- libs/linglong/src/linglong/cli/cli.cpp | 140 ++-- .../src/linglong/runtime/container_builder.h | 19 +- 4 files changed, 645 insertions(+), 152 deletions(-) diff --git a/apps/ll-init/CMakeLists.txt b/apps/ll-init/CMakeLists.txt index 737070fcb..d56cbc340 100644 --- a/apps/ll-init/CMakeLists.txt +++ b/apps/ll-init/CMakeLists.txt @@ -8,6 +8,6 @@ pfl_add_executable(SOURCES ./src/ll-init.cpp OUTPUT_NAME ll-init LIBEXEC set(LL_INIT_TARGET) get_real_target_name(LL_INIT_TARGET linglong::ll-init) - +target_link_libraries(${LL_INIT_TARGET} PRIVATE stdc++fs) target_link_options(${LL_INIT_TARGET} PRIVATE -static -static-libgcc -static-libstdc++) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp index 1594e9aae..6cafccdeb 100644 --- a/apps/ll-init/src/ll-init.cpp +++ b/apps/ll-init/src/ll-init.cpp @@ -2,35 +2,30 @@ // // SPDX-License-Identifier: LGPL-3.0-or-later +#include #include #include +#include #include #include +#include #include +#include #include -#include #include +#include +#include #include #include // no need to block these signals -constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, - SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ, SIGTTIN, - SIGTTOU, SIGINT, SIGTERM }; +constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, + SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ }; -struct sig_conf -{ - sigset_t cur_set{}; - sigset_t old_set{}; - struct sigaction ttin_action{}; - struct sigaction ttou_action{}; - struct sigaction int_action{}; - struct sigaction term_action{}; -}; - -sig_atomic_t received_signal{ 0 }; +// now, we just inherit the control terminal from the outside and put all the processes in the +// same process group. maybe we need refactor this in the future. namespace { @@ -39,81 +34,223 @@ void print_sys_error(std::string_view msg) noexcept std::cerr << msg << ": " << ::strerror(errno) << std::endl; } +void print_sys_error(std::string_view msg, const std::error_code &ec) noexcept +{ + std::cerr << msg << ": " << ec.message() << std::endl; +} + void print_info(std::string_view msg) noexcept { std::cerr << msg << std::endl; } -// ATTENTION: there is a potential risk that the signal will be overridden if multiple signals are -// received at the same time. -void sig_forward(int signo) noexcept +class sigConf +{ +public: + sigConf() noexcept = default; + sigConf(const sigConf &) = delete; + sigConf(sigConf &&) = delete; + sigConf &operator=(const sigConf &) = delete; + sigConf &operator=(sigConf &&) = delete; + ~sigConf() noexcept = default; + + bool block_signals() noexcept + { + ::sigfillset(&cur_set); + for (auto signal : unblock_signals) { + ::sigdelset(&cur_set, signal); + } + + // ignore the rest of the signals + auto ret = ::sigprocmask(SIG_SETMASK, &cur_set, &old_set); + if (ret == -1) { + print_sys_error("Failed to set signal mask"); + return false; + } + + return true; + } + + [[nodiscard]] bool restore_signals() const noexcept + { + auto ret = ::sigprocmask(SIG_SETMASK, &old_set, nullptr); + if (ret == -1) { + print_sys_error("Failed to restore signal mask"); + return false; + } + + return true; + } + + [[nodiscard]] const sigset_t ¤t_sigset() const noexcept { return cur_set; } + +private: + sigset_t cur_set{}; + sigset_t old_set{}; +}; + +class file_descriptor_wrapper +{ +public: + explicit file_descriptor_wrapper(int fd) noexcept + : fd(fd) + { + } + + file_descriptor_wrapper() noexcept = default; + + file_descriptor_wrapper(const file_descriptor_wrapper &) = delete; + file_descriptor_wrapper &operator=(const file_descriptor_wrapper &) = delete; + + file_descriptor_wrapper(file_descriptor_wrapper &&other) noexcept + : fd(other.fd) + { + other.fd = -1; + } + + file_descriptor_wrapper &operator=(file_descriptor_wrapper &&other) noexcept + { + if (this == &other) { + return *this; + } + + close(); + fd = other.fd; + other.fd = -1; + + return *this; + } + + ~file_descriptor_wrapper() noexcept { close(); } + + void close() noexcept + { + if (fd != -1) { + ::close(fd); + fd = -1; + } + } + + explicit operator bool() const noexcept { return fd != -1; } + + operator int() const noexcept { return fd; } // NOLINT + +private: + int fd{ -1 }; +}; + +file_descriptor_wrapper create_signalfd(const sigset_t &sigset) noexcept { - received_signal = signo; + auto fd = ::signalfd(-1, &sigset, SFD_NONBLOCK); + if (fd == -1) { + print_sys_error("Failed to create signalfd"); + } + + return file_descriptor_wrapper(fd); } -using sig_result = std::variant; +file_descriptor_wrapper create_timerfd() noexcept +{ + auto fd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); + if (fd == -1) { + print_sys_error("Failed to create timerfd"); + } + + return file_descriptor_wrapper(fd); +} -sig_result handle_signals() noexcept +file_descriptor_wrapper create_epoll() noexcept { - sig_conf conf; - ::sigfillset(&conf.cur_set); - for (auto signal : unblock_signals) { - ::sigdelset(&conf.cur_set, signal); + auto fd = ::epoll_create1(0); + if (fd == -1) { + print_sys_error("Failed to create epoll"); } - // ignore the rest of the signals - auto ret = ::sigprocmask(SIG_SETMASK, &conf.cur_set, &conf.old_set); - if (ret == -1) { - print_sys_error("Failed to set signal mask"); - return -1; + return file_descriptor_wrapper(fd); +} + +template +constexpr auto make_array(const char (&str)[N]) noexcept // NOLINT +{ + static_assert(N > 0, "N must be greater than 0"); + std::array arr{}; + for (std::size_t i = 0; i < N - 1; ++i) { + arr[i] = str[i]; } - // background process will be suspended by SIGTTIN and SIGTTOU if it try to read/write from/to - // terminal, so we need to ignore these signals. - struct sigaction ignore{}; - ignore.sa_handler = SIG_IGN; - ignore.sa_flags = 0; + return arr; +} - if (::sigaction(SIGTTIN, &ignore, &conf.ttin_action) == -1) { - print_sys_error("Failed to ignore SIGTTIN"); - return -1; +std::pair get_socket_address() noexcept +{ + constexpr auto fs_addr{ make_array("/run/linglong/init/socket") }; + + struct sockaddr_un addr{}; + addr.sun_family = AF_UNIX; + + std::copy(fs_addr.cbegin(), fs_addr.cend(), &addr.sun_path[0]); + addr.sun_path[fs_addr.size()] = 0; + return std::make_pair(addr, offsetof(sockaddr_un, sun_path) + fs_addr.size()); +} + +file_descriptor_wrapper create_fs_uds() noexcept +{ + auto fd = ::socket(AF_UNIX, SOCK_NONBLOCK | SOCK_SEQPACKET, 0); + file_descriptor_wrapper socket_fd{ fd }; + if (fd == -1) { + print_sys_error("Failed to create unix socket"); + return socket_fd; } - if (::sigaction(SIGTTOU, &ignore, &conf.ttou_action) == -1) { - print_sys_error("Failed to ignore SIGTTOU"); - return -1; + auto [addr, len] = get_socket_address(); + if (len == 0) { + print_info("Failed to get socket address"); + return socket_fd; } - // we only forward SIGINT, SIGTERM to the child process - struct sigaction forward_action{}; - forward_action.sa_handler = sig_forward; - forward_action.sa_flags = 0; + // just in case the socket file exists + ::unlink(addr.sun_path); - if (::sigaction(SIGINT, &forward_action, &conf.int_action) == -1) { - print_sys_error("Failed to forward SIGINT"); - return -1; + auto ret = ::bind(socket_fd, reinterpret_cast(&addr), len); + if (ret == -1) { + print_sys_error("Failed to bind abstract socket"); + return socket_fd; } - if (::sigaction(SIGTERM, &forward_action, &conf.term_action) == -1) { - print_sys_error("Failed to forward SIGTERM"); - return -1; + ret = ::listen(socket_fd, 1); + if (ret == -1) { + print_sys_error("Failed to listen on abstract socket"); + return socket_fd; } - return conf; + return socket_fd; } std::vector parse_args(int argc, char *argv[]) noexcept { std::vector args; int idx{ 1 }; + while (idx < argc) { args.emplace_back(argv[idx++]); } + args.emplace_back(nullptr); return args; } -pid_t run(std::vector args, const sig_conf &conf) noexcept +void print_child_status(int status, const std::string &pid) noexcept +{ + if (WIFEXITED(status)) { + print_info("child " + pid + " exited with status " + std::to_string(WEXITSTATUS(status))); + } else if (WIFSIGNALED(status)) { + print_info("child " + pid + " exited with signal " + std::to_string(WTERMSIG(status))); + } else { + print_info("child " + pid + " exited with unknown status"); + } +} + +pid_t run(std::vector args, const sigConf &conf) noexcept { auto pid = ::fork(); if (pid == -1) { @@ -134,57 +271,303 @@ pid_t run(std::vector args, const sig_conf &conf) noexcept return -1; } - ret = ::sigprocmask(SIG_SETMASK, &conf.old_set, nullptr); - if (ret == -1) { - print_sys_error("Failed to restore signal mask"); + if (!conf.restore_signals()) { return -1; } - ret = ::sigaction(SIGTTIN, &conf.ttin_action, nullptr); + ::execvp(args[0], const_cast(args.data())); + print_sys_error("Failed to run process"); + ::_exit(EXIT_FAILURE); + } + + return pid; +} + +bool handle_sigevent(const file_descriptor_wrapper &sigfd, pid_t &child) noexcept +{ + while (true) { + signalfd_siginfo info{}; + auto ret = ::read(sigfd, &info, sizeof(info)); if (ret == -1) { - print_sys_error("Failed to restore SIGTTIN action"); - return -1; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + break; + } + + print_sys_error("Failed to read from signalfd"); + return false; } - ret = ::sigaction(SIGTTOU, &conf.ttou_action, nullptr); - if (ret == -1) { - print_sys_error("Failed to restore SIGTTOU action"); - return -1; + if (info.ssi_signo != SIGCHLD) { + auto ret = ::kill(child, info.ssi_signo); + if (ret == -1) { + auto msg = std::string("Failed to forward signal ") + ::strsignal(info.ssi_signo); + print_sys_error(msg); + } + + continue; } - ret = ::sigaction(SIGINT, &conf.int_action, nullptr); - if (ret == -1) { - print_sys_error("Failed to restore SIGINT action"); - return -1; + while (true) { + int status{}; + auto ret = ::waitpid(-1, &status, WNOHANG); + if (ret == 0 || (ret == -1 && errno == ECHILD)) { + break; + } + + if (ret == -1) { + print_sys_error("Failed to wait for child"); + return false; + } + + print_child_status(status, std::to_string(ret)); + + if (ret == child) { + // child exited, reset the child pid to -1. + // after that, init will broadcast the forwarded signal to all processes in the + // pid namespace. + child = -1; + } + } + } + + return true; +} + +bool shouldWait() noexcept +{ + std::error_code ec; + auto proc_it = std::filesystem::directory_iterator{ + "/proc", + std::filesystem::directory_options::skip_permission_denied, + ec + }; + + if (ec) { + print_sys_error("Failed to open /proc", ec); + return false; + } + + for (const auto &entry : proc_it) { + if (!entry.is_directory(ec)) { + continue; + } + + if (ec) { + print_sys_error("Failed to stat " + entry.path().string(), ec); + return false; } - ret = ::sigaction(SIGTERM, &conf.term_action, nullptr); + pid_t pid{ -1 }; + try { + pid = std::stoi(entry.path().filename()); + } catch (...) { + continue; + } + + if (pid == 1) { // ignore init process + continue; + } + + // if we get here, it means some process is still alive + return true; + } + + return false; +} + +int handle_timerfdevent(const file_descriptor_wrapper &timerfd) noexcept +{ + // we don't care how many times we read from the timerfd + // just traversal the /proc directory once + while (true) { + uint64_t expir{}; + auto ret = ::read(timerfd, &expir, sizeof(expir)); if (ret == -1) { - print_sys_error("Failed to restore SIGTERM action"); + if (errno == EAGAIN || errno == EWOULDBLOCK) { + break; + } + + print_sys_error("Failed to read from timerfd"); return -1; } + } + + return shouldWait() ? 1 : 0; +} + +file_descriptor_wrapper start_timer(const file_descriptor_wrapper &epfd) noexcept +{ + auto timerfd = create_timerfd(); + if (!timerfd) { + return timerfd; + } + + struct itimerspec timer_spec{}; + auto *interval = ::getenv("LINYAPS_INIT_WAIT_INTERVAL"); + constexpr auto default_interval{ 3 }; + if (interval != nullptr) { + try { + auto interval_int = std::stoi(interval); + timer_spec.it_interval.tv_sec = interval_int; + timer_spec.it_interval.tv_nsec = 0; + } catch (...) { + print_info("Invalid interval, using default 3 seconds"); + timer_spec.it_interval.tv_sec = default_interval; + timer_spec.it_interval.tv_nsec = 0; + } + } else { + timer_spec.it_interval.tv_sec = default_interval; + timer_spec.it_interval.tv_nsec = 0; + } + timer_spec.it_value.tv_sec = default_interval; + timer_spec.it_value.tv_nsec = 0; - args.emplace_back(nullptr); + auto ret = ::timerfd_settime(timerfd, 0, &timer_spec, nullptr); + if (ret == -1) { + print_sys_error("Failed to set timerfd"); + return {}; + } - ::execv(args[0], const_cast(args.data())); + struct epoll_event timer_ev{ .events = EPOLLIN | EPOLLET, .data = { .fd = timerfd } }; // NOLINT + ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, timerfd, &timer_ev); + if (ret == -1) { + print_sys_error("Failed to add timerfd to epoll"); + return {}; + } + + return timerfd; +} + +unsigned long get_arg_max() noexcept +{ + auto arg_max = sysconf(_SC_ARG_MAX); + if (arg_max == -1) { + return static_cast(256 * 1024); + } + + return arg_max - 4096; +} + +int delegate_run(const std::vector &args, const sigConf &conf) noexcept +{ + auto child = fork(); + if (child == -1) { + print_sys_error("Failed to fork child"); + return -1; + } + + if (child == 0) { + std::vector c_args; + c_args.reserve(args.size()); + for (const auto &arg : args) { + c_args.emplace_back(const_cast(arg.c_str())); + } + c_args.emplace_back(nullptr); + + if (!conf.restore_signals()) { + ::_exit(EXIT_FAILURE); + } + + ::execvp(c_args[0], c_args.data()); print_sys_error("Failed to exec"); ::_exit(EXIT_FAILURE); } - return pid; + return 0; +} + +bool handle_client(const file_descriptor_wrapper &unix_socket, const sigConf &conf) noexcept +{ + static const unsigned long arg_max = get_arg_max(); + + const file_descriptor_wrapper client{ ::accept(unix_socket, nullptr, nullptr) }; + if (!client) { + print_sys_error("Failed to accept client"); + return false; + } + + const struct timeval tv{ 3, 0 }; + if (::setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { + print_sys_error("Failed to set recv timeout"); + return false; + } + + std::uint64_t arg_len{ 0 }; + auto ret = ::recv(client, &arg_len, sizeof(arg_len), 0); + if (ret == -1) { + print_sys_error("Failed to read from client"); + return false; + } + + if (arg_len > arg_max) { + print_info("Command too long"); + return false; + } + + std::string command_buffer; + command_buffer.reserve(arg_len); + std::array buffer{}; + while (true) { + auto readBytes = ::recv(client, buffer.data(), buffer.size(), 0); + if (readBytes < 0) { + print_sys_error("Failed to read from client"); + return false; + } + + command_buffer.append(buffer.data(), readBytes); + + if (command_buffer.size() >= arg_len) { + break; + } + } + + if (command_buffer.empty()) { + print_info("Empty command"); + return false; + } + + if (command_buffer.back() != 0) { + command_buffer.push_back(0); + } + + std::vector commands; + auto start = command_buffer.cbegin(); + while (start != command_buffer.end()) { + auto end{ start }; + while (end != command_buffer.end() && *end != 0) { + ++end; + } + + commands.emplace_back(start, end); + start = end + 1; + } + + if (commands.empty()) { + print_info("Command may be invalid"); + return false; + } + + ret = delegate_run(commands, conf); + if (ret == -1) { + print_sys_error("Failed to delegate command"); + } + + if (::send(client, &ret, sizeof(ret), 0) == -1) { + print_sys_error("Failed to send result to client"); + } + + return true; } } // namespace -int main(int argc, char *argv[]) +int main(int argc, char **argv) // NOLINT { - auto sig_ret = handle_signals(); - if (std::holds_alternative(sig_ret)) { - return std::get(sig_ret); + sigConf conf; + if (!conf.block_signals()) { + return -1; } - auto conf = std::get(sig_ret); - auto ret = ::prctl(PR_SET_CHILD_SUBREAPER, 1); if (ret == -1) { print_sys_error("Failed to set child subreaper"); @@ -203,39 +586,90 @@ int main(int argc, char *argv[]) return -1; } - int child_status{}; + auto sigfd = create_signalfd(conf.current_sigset()); + if (!sigfd) { + return -1; + } + + auto unix_socket = create_fs_uds(); + if (!unix_socket) { + return -1; + } + + auto epfd = create_epoll(); + if (!epfd) { + return -1; + } + + struct epoll_event sig_ev{ .events = EPOLLIN | EPOLLET, .data = { .fd = sigfd } }; // NOLINT + ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, + &sig_ev); // NOLINT + if (ret == -1) { + print_sys_error("Failed to add signalfd to epoll"); + return -1; + } + + struct epoll_event server_ev{ .events = EPOLLIN | EPOLLET, + .data = { .fd = unix_socket } }; // NOLINT + ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, unix_socket, &server_ev); + if (ret == -1) { + print_sys_error("Failed to add server socket to epoll"); + return -1; + } + + file_descriptor_wrapper timerfd; + bool done{ false }; + std::array events{}; while (true) { - ret = waitpid(-1, &child_status, 0); - if (ret != -1) { - if (ret == child) { - // if child process already exited, we will send the signal to all processes in this - // pid namespace - child = -1; + ret = ::epoll_wait(epfd, events.data(), events.size(), -1); + if (ret == -1) { + print_sys_error("Failed to wait for events"); + return -1; + } + + for (auto i = 0; i < ret; ++i) { + const auto event = events.at(i); + if (event.data.fd == sigfd) { + const int temp_child{ child }; + if (!handle_sigevent(sigfd, child)) { + return -1; + } + + if (temp_child != child) { + timerfd = start_timer(epfd); + if (!timerfd) { + return -1; + } + } + + continue; } - continue; - } + if (event.data.fd == timerfd) { + ret = handle_timerfdevent(timerfd); + if (ret == -1) { + return -1; + } - if (errno == EINTR) { - ret = ::kill(child, received_signal); - if (ret == -1) { - auto msg = std::string("Failed to forward signal ") + ::strsignal(received_signal); - print_sys_error(msg); + if (ret == 0) { + done = true; + } + + continue; + } + + if (event.data.fd == unix_socket) { + if (handle_client(unix_socket, conf)) { + done = false; + } } } - if (errno == ECHILD) { + if (done) { + unix_socket.close(); break; } } - if (WIFEXITED(child_status)) { - print_info("Last child exited with status " + std::to_string(WEXITSTATUS(child_status))); - } else if (WIFSIGNALED(child_status)) { - print_info("Last child exited with signal " + std::to_string(WTERMSIG(child_status))); - } else { - print_info("Last child exited with unknown status"); - } - return 0; } diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index c505e24c8..7888903df 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -32,6 +32,7 @@ #include "linglong/repo/config.h" #include "linglong/runtime/container_builder.h" #include "linglong/runtime/run_context.h" +#include "linglong/utils/bash_quote.h" #include "linglong/utils/error/error.h" #include "linglong/utils/finally/finally.h" #include "linglong/utils/gettext.h" @@ -42,6 +43,7 @@ #include "ocppi/runtime/Signal.hpp" #include "ocppi/types/ContainerListItem.hpp" +#include #include #include @@ -168,7 +170,7 @@ linglong::utils::error::Result ensureDirectory(const std::filesystem::path return LINGLONG_OK; } -static std::vector getAutoModuleList() noexcept +std::vector getAutoModuleList() noexcept { auto getModuleFromLanguageEnv = [](const std::string &lang) -> std::vector { if (lang.length() < 2) { @@ -242,6 +244,82 @@ static std::vector getAutoModuleList() noexcept return { result.begin(), std::unique(result.begin(), result.end()) }; } +bool delegateToContainerInit(const std::string &containerID, + std::vector commands) noexcept +{ + auto containerSocket = ::socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (containerSocket == -1) { + return false; + } + + auto cleanup = linglong::utils::finally::finally([containerSocket] { + ::close(containerSocket); + }); + + struct sockaddr_un addr{}; + addr.sun_family = AF_UNIX; + + auto bundleDir = linglong::runtime::getBundleDir(containerID); + const std::string socketPath = bundleDir / "init/socket"; + + std::copy(socketPath.begin(), socketPath.end(), &addr.sun_path[0]); + addr.sun_path[socketPath.size() + 1] = 0; + + auto ret = ::connect(containerSocket, + reinterpret_cast(&addr), + offsetof(sockaddr_un, sun_path) + socketPath.size()); + if (ret == -1) { + return false; + } + + std::string bashContent; + for (const auto &command : commands) { + bashContent.append(linglong::utils::quoteBashArg(command)); + bashContent.push_back(' '); + } + + commands.clear(); + commands.push_back(bashContent); + commands.insert(commands.begin(), "-c"); + commands.insert(commands.begin(), "--login"); + commands.insert(commands.begin(), "bash"); + + std::string command_data; + for (const auto &command : commands) { + command_data.append(command); + command_data.push_back('\0'); + } + command_data.push_back('\0'); + + std::uint64_t rest_len = command_data.size(); + ret = ::send(containerSocket, &rest_len, sizeof(rest_len), 0); + if (ret == -1) { + return false; + } + + while (rest_len > 0) { + auto send_len = ::send(containerSocket, command_data.c_str(), rest_len, 0); + if (send_len == -1) { + if (errno == EINTR) { + continue; + } + + break; + } + + rest_len -= send_len; + } + + if (rest_len != 0) { + return false; + } + + int result{ -1 }; + ret = ::recv(containerSocket, &result, sizeof(result), 0); + qDebug() << "delegate result:" << result; + return result == 0; +} + } // namespace namespace linglong::cli { @@ -643,47 +721,12 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) return -1; } - QStringList execArgs; - std::transform(commands.begin(), - commands.end(), - std::back_inserter(execArgs), - [](const std::string &arg) { - return QString::fromStdString(arg); - }); - - // 为避免原始args包含空格,每个arg都使用单引号包裹,并对arg内部的单引号进行转义替换 - std::for_each(execArgs.begin(), execArgs.end(), [](QString &arg) { - arg.replace("'", "'\\''"); - arg.prepend('\''); - arg.push_back('\''); - }); - - // exec命令使用原始args中的进程替换bash进程 - execArgs.prepend("exec"); - - // 在原始args前面添加bash --login -c,这样可以使用/etc/profile配置的环境变量 - commands = std::vector{ "/bin/bash", - "--login", - "-e", - "-c", - execArgs.join(' ').toStdString() }; - - auto opt = ocppi::runtime::ExecOption{ - .uid = uid, - .gid = gid, - }; - - auto result = this->ociCLI.exec(container.id, - commands[0], - { commands.cbegin() + 1, commands.cend() }, - opt); - if (!result) { - auto err = LINGLONG_ERRV(result); - this->printer.printErr(err); - return -1; + if (delegateToContainerInit(container.id, commands)) { + return 0; } - return 0; + // fallback to run + break; } auto *homeEnv = ::getenv("HOME"); @@ -698,6 +741,16 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) this->printer.printErr(res.error()); return -1; } + + std::error_code ec; + auto socketDir = cfgBuilder.getBundlePath() / "init"; + qInfo() << "socket dir" << socketDir.c_str(); + std::filesystem::create_directories(socketDir, ec); + if (ec) { + this->printer.printErr(LINGLONG_ERRV(ec.message().c_str())); + return -1; + } + cfgBuilder.setAppId(curAppRef->id.toStdString()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) @@ -715,7 +768,12 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) .mapPrivate(std::string{ homeEnv } + "/.gnupg", true) .bindIPC() .forwardDefaultEnv() - .enableSelfAdjustingMount(); + .enableSelfAdjustingMount() + .addExtraMount( + ocppi::runtime::config::types::Mount{ .destination = "/run/linglong/init", + .options = std::vector{ "bind" }, + .source = socketDir.string(), + .type = "bind" }); #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); #endif diff --git a/libs/linglong/src/linglong/runtime/container_builder.h b/libs/linglong/src/linglong/runtime/container_builder.h index ef852a8ee..8dd2b8a8c 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -1,19 +1,16 @@ /* - * SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. + * SPDX-FileCopyrightText: 2022 - 2025 UnionTech Software Technology Co., Ltd. * * SPDX-License-Identifier: LGPL-3.0-or-later */ #pragma once -#include "linglong/api/types/v1/OciConfigurationPatch.hpp" #include "linglong/oci-cfg-generators/container_cfg_builder.h" #include "linglong/package/reference.h" #include "linglong/runtime/container.h" #include "linglong/utils/error/error.h" #include "ocppi/cli/CLI.hpp" -#include "ocppi/runtime/config/types/Config.hpp" -#include "ocppi/runtime/config/types/Mount.hpp" #include #include @@ -39,14 +36,18 @@ inline std::string genContainerID(const package::Reference &ref) noexcept } // Used to obtain a clean container bundle directory. -inline utils::error::Result makeBundleDir(const std::string &containerID) -{ - LINGLONG_TRACE("get bundle dir"); - std::filesystem::path runtimeDir = +inline std::filesystem::path getBundleDir(const std::string &containerID) noexcept +{ + const std::filesystem::path runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation).toStdString(); - auto bundle = runtimeDir / "linglong" / containerID; + return runtimeDir / "linglong" / containerID; +} +inline utils::error::Result makeBundleDir(const std::string &containerID) +{ + LINGLONG_TRACE("get bundle dir"); + auto bundle = getBundleDir(containerID); std::error_code ec; if (std::filesystem::exists(bundle, ec)) { std::filesystem::remove_all(bundle, ec); From ab365912e2e3f07d5962af6827fc64e4b5cfed04 Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 10 Jul 2025 19:39:18 +0800 Subject: [PATCH 081/366] fix: handle file descriptor access in layer unpacking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added QTemporaryDir and fstream headers for temporary file operations 2. Implemented fallback mechanism when direct file descriptor access fails 3. Added UUID-based temporary file naming for layer files 4. Improved error handling for file save operations The changes address cases where direct access to file descriptors via /proc may fail (common in containerized environments). The new implementation first attempts direct access, then falls back to copying the file to a temporary location if needed. This makes the unpacking process more robust across different environments. fix: 修复layer解包中文件描述符访问权限问题 1. 添加 QTemporaryDir 和 fstream 头文件以支持临时文件操作 2. 当直接文件描述符访问失败时实现回退机制 3. 为layer文件添加基于UUID的临时文件命名 4. 改进文件保存操作的错误处理 这些改动解决了通过/proc直接访问文件描述符可能失败的情况(在容器环境中常 见)。新实现首先尝试直接访问,如果需要则回退到将文件复制到临时位置。这使 得解包过程在不同环境中更加健壮。 --- .../src/linglong/package/layer_packager.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/package/layer_packager.cpp b/libs/linglong/src/linglong/package/layer_packager.cpp index b36fa76a6..041f3f244 100644 --- a/libs/linglong/src/linglong/package/layer_packager.cpp +++ b/libs/linglong/src/linglong/package/layer_packager.cpp @@ -14,6 +14,7 @@ #include #include +#include #include @@ -127,11 +128,21 @@ utils::error::Result LayerPackager::unpack(LayerFile &file) if (!offset) { return LINGLONG_ERR(offset); } - + auto fdPath = QString{ "/proc/%1/fd/%2" }.arg(::getpid()).arg(file.handle()); + // 测试fdpath是否可读,如果不可读,先复制到临时文件 + std::ifstream f(fdPath.toStdString()); + if (!f.is_open()) { + // 如果不可读,通过文件描述符复制到工作目录 + fdPath = this->workDir.absoluteFilePath(QUuid::createUuid().toString(QUuid::Id128)+".erofs"); + // 如果保存失败,返回错误 + if (!file.saveTo(fdPath)) { + return LINGLONG_ERR("Failed to save layer file to work directory"); + } + } auto ret = utils::command::Exec("erofsfuse", { QString("--offset=%1").arg(*offset), - QString{ "/proc/%1/fd/%2" }.arg(::getpid()).arg(file.handle()), + fdPath, unpackDir.absolutePath() }); if (!ret) { return LINGLONG_ERR(ret); From 0d164e08dfb485e0a7bbea5e42b819dd1a435123 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Fri, 11 Jul 2025 11:02:47 +0800 Subject: [PATCH 082/366] feat: add signleMode for ll-init all of the builder container shouldn't reuse container Signed-off-by: ComixHe --- apps/ll-init/src/ll-init.cpp | 65 ++++++++++++------- .../src/linglong/builder/linglong_builder.cpp | 24 ++++--- libs/linglong/src/linglong/cli/cli.cpp | 1 - .../container_cfg_builder.cpp | 18 ++++- .../container_cfg_builder.h | 9 ++- 5 files changed, 78 insertions(+), 39 deletions(-) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp index 6cafccdeb..ce0aae414 100644 --- a/apps/ll-init/src/ll-init.cpp +++ b/apps/ll-init/src/ll-init.cpp @@ -41,7 +41,10 @@ void print_sys_error(std::string_view msg, const std::error_code &ec) noexcept void print_info(std::string_view msg) noexcept { - std::cerr << msg << std::endl; + static const auto is_debug = ::getenv("LINYAPS_INIT_VERBOSE_OUTPUT") != nullptr; + if (is_debug) { + std::cerr << msg << std::endl; + } } class sigConf @@ -198,7 +201,7 @@ file_descriptor_wrapper create_fs_uds() noexcept auto fd = ::socket(AF_UNIX, SOCK_NONBLOCK | SOCK_SEQPACKET, 0); file_descriptor_wrapper socket_fd{ fd }; if (fd == -1) { - print_sys_error("Failed to create unix socket"); + print_sys_error("Failed to create unix domain socket"); return socket_fd; } @@ -213,13 +216,13 @@ file_descriptor_wrapper create_fs_uds() noexcept auto ret = ::bind(socket_fd, reinterpret_cast(&addr), len); if (ret == -1) { - print_sys_error("Failed to bind abstract socket"); + print_sys_error("Failed to bind unix domain socket"); return socket_fd; } ret = ::listen(socket_fd, 1); if (ret == -1) { - print_sys_error("Failed to listen on abstract socket"); + print_sys_error("Failed to listen on unix domain socket"); return socket_fd; } @@ -559,6 +562,19 @@ bool handle_client(const file_descriptor_wrapper &unix_socket, const sigConf &co return true; } +bool register_event(const file_descriptor_wrapper &epfd, + const file_descriptor_wrapper &fd, + epoll_event ev) noexcept +{ + auto ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); + if (ret == -1) { + print_sys_error("Failed to add event to epoll"); + return false; + } + + return true; +} + } // namespace int main(int argc, char **argv) // NOLINT @@ -580,41 +596,42 @@ int main(int argc, char **argv) // NOLINT return -1; } + auto *singleModeEnv = ::getenv("LINYAPS_INIT_SINGLE_MODE"); + const bool singleMode = singleModeEnv != nullptr && std::string_view{ singleModeEnv } == "1"; + auto child = run(args, conf); if (child == -1) { print_info("Failed to run child process"); return -1; } - auto sigfd = create_signalfd(conf.current_sigset()); - if (!sigfd) { + auto epfd = create_epoll(); + if (!epfd) { return -1; } - auto unix_socket = create_fs_uds(); - if (!unix_socket) { + auto sigfd = create_signalfd(conf.current_sigset()); + if (!sigfd) { return -1; } - auto epfd = create_epoll(); - if (!epfd) { + const struct epoll_event ev{ .events = EPOLLIN | EPOLLET, .data = { .fd = sigfd } }; + if (!register_event(epfd, sigfd, ev)) { return -1; } - struct epoll_event sig_ev{ .events = EPOLLIN | EPOLLET, .data = { .fd = sigfd } }; // NOLINT - ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, - &sig_ev); // NOLINT - if (ret == -1) { - print_sys_error("Failed to add signalfd to epoll"); - return -1; - } + file_descriptor_wrapper unix_socket; + if (!singleMode) { + unix_socket = create_fs_uds(); + if (!unix_socket) { + return -1; + } - struct epoll_event server_ev{ .events = EPOLLIN | EPOLLET, - .data = { .fd = unix_socket } }; // NOLINT - ret = ::epoll_ctl(epfd, EPOLL_CTL_ADD, unix_socket, &server_ev); - if (ret == -1) { - print_sys_error("Failed to add server socket to epoll"); - return -1; + const struct epoll_event ev{ .events = EPOLLIN | EPOLLET, + .data = { .fd = unix_socket } }; // NOLINT + if (!register_event(epfd, unix_socket, ev)) { + return -1; + } } file_descriptor_wrapper timerfd; @@ -658,7 +675,7 @@ int main(int argc, char **argv) // NOLINT continue; } - if (event.data.fd == unix_socket) { + if (unix_socket && event.data.fd == unix_socket) { if (handle_client(unix_socket, conf)) { done = false; } diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 21a42e0ff..337b9a50c 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -895,7 +895,8 @@ utils::error::Result Builder::buildStageBuild(const QStringList &args) noe .addMask({ "/project/linglong/output", "/project/linglong/overlay", - }); + }) + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); if (this->buildOptions.isolateNetWork) { cfgBuilder.isolateNetWork(); @@ -1034,7 +1035,8 @@ utils::error::Result Builder::buildStagePreCommit() noexcept .options = { { "rbind", "rw" } }, .source = this->workingDir.absolutePath().toStdString(), .type = "bind" }) - .forwardDefaultEnv(); + .forwardDefaultEnv() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); if (cfgBuilder.getRuntimePath()) { cfgBuilder.setRuntimePath(runtimeOverlay->mergedDirPath().toStdString(), false); @@ -1907,7 +1909,8 @@ utils::error::Result Builder::run(const QStringList &modules, .addGIdMapping(gid, gid, 1) .bindDefault() .addExtraMounts(applicationMounts) - .enableSelfAdjustingMount(); + .enableSelfAdjustingMount() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); // write ld.so.conf std::string triplet = curRef->arch.getTriplet().toStdString(); @@ -1970,12 +1973,15 @@ utils::error::Result Builder::run(const QStringList &modules, .bindIPC() .forwardDefaultEnv() .addExtraMounts(applicationMounts) - .enableSelfAdjustingMount(); + .enableSelfAdjustingMount() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); + #ifdef LINGLONG_FONT_CACHE_GENERATOR - cfgBuilder.enableFontCache(); + cfgBuilder.enableFontCache() #endif - if (!cfgBuilder.build()) { + if (!cfgBuilder.build()) + { auto err = cfgBuilder.getError(); return LINGLONG_ERR("build cfg error: " + QString::fromStdString(err.reason)); } @@ -2051,7 +2057,8 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, .options = { { "rbind", "ro" } }, .source = ldConfPath, .type = "bind" }) - .enableSelfAdjustingMount(); + .enableSelfAdjustingMount() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); // write ld.so.conf std::string triplet = ref.arch.getTriplet().toStdString(); @@ -2105,7 +2112,8 @@ utils::error::Result Builder::runFromRepo(const package::Reference &ref, .options = { { "rbind", "rw" } }, .source = this->workingDir.absolutePath().toStdString(), .type = "bind" }) - .enableSelfAdjustingMount(); + .enableSelfAdjustingMount() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); if (!cfgBuilder.build()) { auto err = cfgBuilder.getError(); diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 7888903df..d4149d01a 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -744,7 +744,6 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) std::error_code ec; auto socketDir = cfgBuilder.getBundlePath() / "init"; - qInfo() << "socket dir" << socketDir.c_str(); std::filesystem::create_directories(socketDir, ec); if (ec) { this->printer.printErr(LINGLONG_ERRV(ec.message().c_str())); diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 539efce23..210893beb 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -360,6 +360,19 @@ ContainerCfgBuilder::appendEnv(const std::map &envMap) return *this; } +ContainerCfgBuilder &ContainerCfgBuilder::appendEnv(const std::string &env, + const std::string &value, + bool overwrite) noexcept +{ + if (overwrite || envAppend.find(env) == envAppend.end()) { + envAppend[env] = value; + } else { + std::cerr << "env " << env << " is already exist" << std::endl; + } + + return *this; +} + ContainerCfgBuilder &ContainerCfgBuilder::bindHostRoot() noexcept { hostRootMount = { @@ -1770,12 +1783,11 @@ bool ContainerCfgBuilder::shouldFix(int node, std::filesystem::path &fixPath) no }); return find != mount.options->end(); }; - // node should fix if the file + // node should fix if the file // 1. is /etc/localtime or // 2. is not exist or // 3. is not a symlink but mount with option copy-symlink - if (getRelativePath(0, node) == "etc/localtime" - || !std::filesystem::exists(hostPath, ec) + if (getRelativePath(0, node) == "etc/localtime" || !std::filesystem::exists(hostPath, ec) || ((!std::filesystem::is_symlink(hostPath, ec)) && isCopySymlink(node))) { fixPath = std::move(hostPath); return true; diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 0fc5c25e6..7da8f0e71 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -47,7 +47,7 @@ class ContainerCfgBuilder class Error { public: - operator bool() const { return code != BUILD_SUCCESS; } + explicit operator bool() const { return code != BUILD_SUCCESS; } ERROR_CODE code; std::string reason; @@ -62,7 +62,7 @@ class ContainerCfgBuilder int parent_idx; }; - ContainerCfgBuilder &setAppId(std::string id) noexcept + ContainerCfgBuilder &setAppId(const std::string &id) noexcept { appId = id; return *this; @@ -86,7 +86,7 @@ class ContainerCfgBuilder std::optional getRuntimePath() { return runtimePath; } - ContainerCfgBuilder &setBasePath(std::filesystem::path path, bool isRo = true) noexcept + ContainerCfgBuilder &setBasePath(const std::filesystem::path &path, bool isRo = true) noexcept { basePath = path; basePathRo = isRo; @@ -130,6 +130,9 @@ class ContainerCfgBuilder ContainerCfgBuilder &forwardDefaultEnv() noexcept; ContainerCfgBuilder &forwardEnv(const std::vector &envList = {}) noexcept; ContainerCfgBuilder &appendEnv(const std::map &envMap) noexcept; + ContainerCfgBuilder &appendEnv(const std::string &env, + const std::string &value, + bool overwrite = false) noexcept; ContainerCfgBuilder &bindHostRoot() noexcept; ContainerCfgBuilder &bindHostStatics() noexcept; From d01567dad1a350df616612e0737b336c67fa4322 Mon Sep 17 00:00:00 2001 From: ComixHe Date: Fri, 11 Jul 2025 16:48:50 +0800 Subject: [PATCH 083/366] fix(uab): set mount option 'rw' while generating config Signed-off-by: ComixHe --- apps/uab/loader/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/uab/loader/src/main.cpp b/apps/uab/loader/src/main.cpp index fed593967..eb796705e 100644 --- a/apps/uab/loader/src/main.cpp +++ b/apps/uab/loader/src/main.cpp @@ -321,7 +321,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT } builder.setBundlePath(containerBundle) - .setBasePath("/") + .setBasePath("/", false) .enableSelfAdjustingMount() .forwardEnv() .addUIdMapping(uid, uid, 1) From 051380e090ddbcab2da146f0129c5d81072f59c3 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 11 Jul 2025 17:27:44 +0800 Subject: [PATCH 084/366] fix: check directory existence before creation create_directories may fail with an error code if the destination is a symbolic link to a directory. Signed-off-by: reddevillg --- libs/linglong/src/linglong/package/uab_packager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/package/uab_packager.cpp b/libs/linglong/src/linglong/package/uab_packager.cpp index 195c78cc0..d8dbae961 100644 --- a/libs/linglong/src/linglong/package/uab_packager.cpp +++ b/libs/linglong/src/linglong/package/uab_packager.cpp @@ -402,7 +402,8 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo } const auto &info = *infoRet; - // the kind of old org.deepin.base,org.deepin.foundation and com.uniontech.foundation is runtime + // the kind of old org.deepin.base,org.deepin.foundation and com.uniontech.foundation is + // runtime if (info.kind == "base" || info.id == "org.deepin.base" || info.id == "org.deepin.foundation" || info.id == "com.uniontech.foundation") { base = *it; @@ -555,7 +556,9 @@ utils::error::Result UABPackager::prepareBundle(const QDir &bundleDir, boo QString::fromStdString(ec.message()))); } - if (!std::filesystem::create_directories(realDestination.parent_path(), ec) && ec) { + if (!std::filesystem::exists(realDestination.parent_path(), ec) + && !std::filesystem::create_directories(realDestination.parent_path(), ec) + && ec) { return LINGLONG_ERR( "couldn't create directories " % QString::fromStdString(realDestination.parent_path().string() + ":" From 58b0ca4a081d49093fa0c20211899392cded332a Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:43:19 +0800 Subject: [PATCH 085/366] chore: Updates for project Linyaps * i18n: Translate po/en_US.po in ca 96% of minimum 50% translated source file: 'po/en_US.po' on 'ca'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in uk 96% of minimum 50% translated source file: 'po/en_US.po' on 'uk'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 96% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in zh_CN 96% of minimum 50% translated source file: 'po/en_US.po' on 'zh_CN'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in en_GB 73% of minimum 50% translated source file: 'po/en_US.po' on 'en_GB'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pt_BR 96% of minimum 50% translated source file: 'po/en_US.po' on 'pt_BR'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in es 96% of minimum 50% translated source file: 'po/en_US.po' on 'es'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in sq 74% of minimum 50% translated source file: 'po/en_US.po' on 'sq'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in fi 96% of minimum 50% translated source file: 'po/en_US.po' on 'fi'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 98% of minimum 50% translated source file: 'po/en_US.po' on 'pl'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in pl 100% translated source file: 'po/en_US.po' on 'pl'. * i18n: Translate po/en_US.po in ca 100% translated source file: 'po/en_US.po' on 'ca'. * i18n: Translate po/en_US.po in es 99% of minimum 50% translated source file: 'po/en_US.po' on 'es'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * i18n: Translate po/en_US.po in es 100% translated source file: 'po/en_US.po' on 'es'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- po/ca.po | 47 ++++++++++++++++------------------- po/en_GB.po | 35 +++++++++++--------------- po/es.po | 71 ++++++++++++++++++++++++----------------------------- po/fi.po | 46 +++++++++++++++------------------- po/pl.po | 60 ++++++++++++++++++++------------------------ po/pt_BR.po | 54 +++++++++++++++++----------------------- po/sq.po | 32 ++++++++++-------------- po/uk.po | 50 ++++++++++++++++--------------------- po/zh_CN.po | 55 +++++++++++++++++------------------------ 9 files changed, 193 insertions(+), 257 deletions(-) diff --git a/po/ca.po b/po/ca.po index c261ba4d5..1319bf3bd 100644 --- a/po/ca.po +++ b/po/ca.po @@ -2,11 +2,11 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Jaime Muñoz Martín , 2025 # Davidmp , 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -15,12 +15,11 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Davidmp , 2025\n" -"Language-Team: Catalan (https://app.transifex.com/linuxdeepin/teams/3976/" -"ca/)\n" -"Language: ca\n" +"Language-Team: Catalan (https://app.transifex.com/linuxdeepin/teams/3976/ca/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 @@ -111,8 +110,7 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "CLI de linyaps\n" -"Un programa de línia d'ordres per executar aplicacions i gestionar " -"l'aplicació i el temps d'execució\n" +"Un programa de línia d'ordres per executar aplicacions i gestionar l'aplicació i el temps d'execució\n" #: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" @@ -129,8 +127,7 @@ msgstr "Ús: ll-cli [OPCIONS] [SUBORDRE]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si heu trobat algun problema durant l'ús,\n" "podeu informar d'errors a l'equip de linyaps en aquest projecte: \n" @@ -369,8 +366,8 @@ msgstr "Ús: ll-cli upgrade [OPCIONS] [APLICACIÓ]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Especifiqueu l'ID de l'aplicació. Si no s'especifica, s'actualitzaran totes " "les aplicacions." @@ -416,9 +413,7 @@ msgid "Specify the Keywords" msgstr "Especifiqueu les paraules clau." #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" "Filtra el resultat amb el tipus especificat: \"runtime\", \"base\", \"app\" " "o \"all\"." @@ -462,8 +457,7 @@ msgstr "" "ll-cli list --type=base\n" "# mostra els temps d'execució instal·lats\n" "ll-cli list --type=runtime\n" -"# mostra la llista de versions més recents de les aplicacions instal·lades " -"actualment\n" +"# mostra la llista de versions més recents de les aplicacions instal·lades actualment\n" "ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 @@ -567,23 +561,24 @@ msgstr "Prioritat del repositori" #: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 msgid "Enable mirror for the repo" -msgstr "" +msgstr "Habilita la rèplica per al repositori" #: ../apps/ll-cli/src/main.cpp:515 msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Ús: ll-cli repo enable-mirror [OPCIONS] ÀLIES" #: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 msgid "Disable mirror for the repo" -msgstr "" +msgstr "Inhabilita la rèplica per al repositori" #: ../apps/ll-cli/src/main.cpp:522 msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Ús: ll-cli repo disable-mirror [OPCIONS] ÀLIES" #: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" -msgstr "Mostra informació sobre aplicacions instal·lades o entorns d'execució." +msgstr "" +"Mostra informació sobre aplicacions instal·lades o entorns d'execució." #: ../apps/ll-cli/src/main.cpp:533 msgid "Usage: ll-cli info [OPTIONS] APP" @@ -737,8 +732,7 @@ msgstr "Ús: ll-builder [OPCIONS] [SUBORDRE]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si heu trobat algun problema durant l'ús,\n" "podeu informar d'errors a l'equip de linyaps en aquest projecte: \n" @@ -770,7 +764,8 @@ msgid "File path of the linglong.yaml" msgstr "Camí del fitxer linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Entreu al contenidor per executar l'ordre en lloc de construir aplicacions." @@ -970,11 +965,11 @@ msgstr "Ús: ll-builder repo set-default [OPCIONS] NOM" #: ../apps/ll-builder/src/main.cpp:997 msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Ús: ll-builder repo enable-mirror [OPCIONS] ÀLIES" #: ../apps/ll-builder/src/main.cpp:1005 msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Ús: ll-builder repo disable-mirror [OPCIONS] ÀLIES" #: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" diff --git a/po/en_GB.po b/po/en_GB.po index 0f171615f..a9dcb7eda 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -2,10 +2,10 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -14,12 +14,11 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Gary Wang , 2025\n" -"Language-Team: English (United Kingdom) (https://app.transifex.com/" -"linuxdeepin/teams/3976/en_GB/)\n" -"Language: en_GB\n" +"Language-Team: English (United Kingdom) (https://app.transifex.com/linuxdeepin/teams/3976/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 @@ -119,12 +118,10 @@ msgstr "Usage: ll-cli [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -229,7 +226,8 @@ msgstr "Execute commands in the currently running sandbox" #: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" -msgstr "Specify the application running instance(you can get it by ps command)" +msgstr "" +"Specify the application running instance(you can get it by ps command)" #: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" @@ -355,8 +353,8 @@ msgstr "Usage: ll-cli upgrade [OPTIONS] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" #: ../apps/ll-cli/src/main.cpp:374 @@ -387,9 +385,7 @@ msgid "Specify the Keywords" msgstr "Specify the Keywords" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" #: ../apps/ll-cli/src/main.cpp:400 @@ -692,12 +688,10 @@ msgstr "Usage: ll-builder [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -725,7 +719,8 @@ msgid "File path of the linglong.yaml" msgstr "File path of the linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Enter the container to execute command instead of building applications" diff --git a/po/es.po b/po/es.po index de4243602..fbe595305 100644 --- a/po/es.po +++ b/po/es.po @@ -2,12 +2,12 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 # Isaías Gätjens M , 2025 # Zaraza, 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -16,14 +16,12 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Zaraza, 2025\n" -"Language-Team: Spanish (https://app.transifex.com/linuxdeepin/teams/3976/" -"es/)\n" -"Language: es\n" +"Language-Team: Spanish (https://app.transifex.com/linuxdeepin/teams/3976/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " -"1 : 2;\n" +"Language: es\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." @@ -97,8 +95,8 @@ msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" msgstr "" -"Se ha instalado la última versión. Si desea reemplazarla, pruebe con «ll-cli " -"install %1/version --force»." +"Se ha instalado la última versión. Si desea reemplazarla, pruebe con «ll-cli" +" install %1/version --force»." #: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" @@ -113,8 +111,7 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Un programa CLI para ejecutar aplicaciones y gestionar aplicaciones y " -"entornos de ejecución\n" +"Un programa CLI para ejecutar aplicaciones y gestionar aplicaciones y entornos de ejecución\n" #: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" @@ -131,12 +128,10 @@ msgstr "Uso: ll-cli [OPCIONES] [SUBCOMANDO]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si encuentras algún problema durante el uso,\n" -"puede reportar errores al equipo de linyaps en este proyecto: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -216,7 +211,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:236 msgid "Pass file to applications running in a sandbox" -msgstr "Pasar archivo a las aplicaciones que se ejecutan en un entorno aislado" +msgstr "" +"Pasar archivo a las aplicaciones que se ejecutan en un entorno aislado" #: ../apps/ll-cli/src/main.cpp:240 msgid "Pass url to applications running in a sandbox" @@ -252,7 +248,8 @@ msgstr "Especificar la carpeta de trabajo" #: ../apps/ll-cli/src/main.cpp:270 msgid "Enter the namespace where the application is running" -msgstr "Entrar en el espacio de nombres donde se está ejecutando la aplicación" +msgstr "" +"Entrar en el espacio de nombres donde se está ejecutando la aplicación" #: ../apps/ll-cli/src/main.cpp:273 msgid "Usage: ll-cli enter [OPTIONS] INSTANCE [COMMAND...]" @@ -318,8 +315,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Especificar el ID de la aplicación, también puede ser un archivo .uab o ." -"layer" +"Especificar el ID de la aplicación, también puede ser un archivo .uab o " +".layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -372,8 +369,8 @@ msgstr "Uso: ll-cli upgrade [OPCIONES] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Especificar el ID de la aplicación. Si no se especifica, se actualizarán " "todas las aplicaciones" @@ -403,8 +400,7 @@ msgstr "" "Uso: ll-cli search [OPCIONES] PALABRAS CLAVE\n" "\n" "Ejemplo:\n" -"# Buscar aplicaciones, bases o entornos de ejecución de forma remota por " -"palabras clave\n" +"# Buscar aplicaciones, bases o entornos de ejecución de forma remota por palabras clave\n" "ll-cli search org.deepin.demo\n" "# Buscar entornos de ejecución de forma remota por nombre\n" "ll-cli search org.deepin.base --type=runtime\n" @@ -420,12 +416,10 @@ msgid "Specify the Keywords" msgstr "Especificar las Palabras Clave" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" -"Filtrar resultados especificando el tipo: \"tiempo de ejecución\", \"base\", " -"\"aplicación\" o \"todos\"." +"Filtrar resultados especificando el tipo: \"tiempo de ejecución\", \"base\"," +" \"aplicación\" o \"todos\"." #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -572,19 +566,19 @@ msgstr "Prioridad del repositorio" #: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 msgid "Enable mirror for the repo" -msgstr "" +msgstr "Habilitar espejo para el repositorio" #: ../apps/ll-cli/src/main.cpp:515 msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Uso: ll-cli repo enable-mirror [OPCIONES] ALIAS" #: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 msgid "Disable mirror for the repo" -msgstr "" +msgstr "Deshabilitar el espejo para el repositorio" #: ../apps/ll-cli/src/main.cpp:522 msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Uso: ll-cli repo disabled-mirror [OPCIONES] ALIAS" #: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" @@ -744,12 +738,10 @@ msgstr "Uso: ll-builder [OPCIONES] [SUBCOMANDO]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Si encuentras algún problema durante el uso\n" -"Puede reportar errores al equipo de linyaps en este proyecto: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"Puede reportar errores al equipo de linyaps en este proyecto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -777,7 +769,8 @@ msgid "File path of the linglong.yaml" msgstr "Ruta del archivo de linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Entrar en el contenedor para ejecutar comandos en lugar de construir " "aplicaciones" @@ -979,11 +972,11 @@ msgstr "Uso: ll-builder repo set-default [OPCIONES] NOMBRE" #: ../apps/ll-builder/src/main.cpp:997 msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Uso: ll-builder repo enable-mirror [OPCIONES] ALIAS" #: ../apps/ll-builder/src/main.cpp:1005 msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Uso: ll-builder repo disabled-mirror [OPCIONES] ALIAS" #: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" diff --git a/po/fi.po b/po/fi.po index 7ce32b3d0..147129c3e 100644 --- a/po/fi.po +++ b/po/fi.po @@ -2,10 +2,10 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Kimmo Kujansuu , 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -14,12 +14,11 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Kimmo Kujansuu , 2025\n" -"Language-Team: Finnish (https://app.transifex.com/linuxdeepin/teams/3976/" -"fi/)\n" -"Language: fi\n" +"Language-Team: Finnish (https://app.transifex.com/linuxdeepin/teams/3976/fi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 @@ -126,12 +125,10 @@ msgstr "Käyttö: ll-cli [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jos havaitset ongelmia käytön aikana,\n" -"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-" -"Linyaps/linyaps/issues" +"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -309,7 +306,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" -msgstr "Määritä sovelluksen id-tunnus. Voi olla myös .uab- tai .layer-tiedosto" +msgstr "" +"Määritä sovelluksen id-tunnus. Voi olla myös .uab- tai .layer-tiedosto" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -362,8 +360,8 @@ msgstr "Käyttö: ll-cli upgrade [OPTIONS] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Määritä sovelluksen id-tunnus. Jos ei määritetä, kaikki sovellukset " "päivitetään" @@ -373,8 +371,8 @@ msgid "" "Search the applications/runtimes containing the specified text from the " "remote repository" msgstr "" -"Etsi palvelimen arkistosta tietyn tekstin sisältävät sovellukset/" -"ajoympäristöt" +"Etsi palvelimen arkistosta tietyn tekstin sisältävät " +"sovellukset/ajoympäristöt" #: ../apps/ll-cli/src/main.cpp:378 msgid "" @@ -393,8 +391,7 @@ msgstr "" "Käyttö: ll-cli search [OPTIONS] KEYWORDS\n" "\n" "Esimerkki:\n" -"# etsi palvelimelta sovellukse(t), alusta(t) tai ajoympäristö(t) " -"hakusanoilla\n" +"# etsi palvelimelta sovellukse(t), alusta(t) tai ajoympäristö(t) hakusanoilla\n" "ll-cli search org.deepin.demo\n" "# etsi ajoympäristö palvelimelta nimellä\n" "ll-cli search org.deepin.base --type=runtime\n" @@ -410,9 +407,7 @@ msgid "Specify the Keywords" msgstr "Määrittele hakusanat" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" "Suodata tulokset tyypillä. Joku seuraavista: \"runtime\", \"base\", \"app\" " "tai \"all\"" @@ -731,12 +726,10 @@ msgstr "Käyttö: ll-builder [OPTIONS] [SUBCOMMAND]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jos havaitset ongelmia käytön aikana,\n" -"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-" -"Linyaps/linyaps/issues" +"Voit ilmoittaa vioista linyaps-tiimille täällä: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -764,7 +757,8 @@ msgid "File path of the linglong.yaml" msgstr "Tiedoston linglong.yaml tiedostopolku" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Kirjoita kontin nimi, suorittaaksesi komento sovelluksen rakentamisen sijaan" @@ -773,8 +767,8 @@ msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Käytä vain paikallisia tiedostoja. Tarkoittaa, että --skip-fetch-source ja --" -"skip-pull-depend asetetaan" +"Käytä vain paikallisia tiedostoja. Tarkoittaa, että --skip-fetch-source ja " +"--skip-pull-depend asetetaan" #: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" diff --git a/po/pl.po b/po/pl.po index df10cf10b..8009c1063 100644 --- a/po/pl.po +++ b/po/pl.po @@ -2,10 +2,10 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Janusz Ruchała, 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -14,15 +14,12 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Janusz Ruchała, 2025\n" -"Language-Team: Polish (https://app.transifex.com/linuxdeepin/teams/3976/" -"pl/)\n" -"Language: pl\n" +"Language-Team: Polish (https://app.transifex.com/linuxdeepin/teams/3976/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" -"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" -"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." @@ -112,8 +109,7 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Aplikacja wiersza poleceń do uruchamiania i zarządzania aplikacjami oraz " -"środowiskami wykonawczymi\n" +"Aplikacja wiersza poleceń do uruchamiania i zarządzania aplikacjami oraz środowiskami wykonawczymi\n" #: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" @@ -130,8 +126,7 @@ msgstr "Polecenie: ll-cli [OPCJE] [PODKOMENDA]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jeśli znajdziesz jakieś problemy, \n" "możesz zgłosić błąd do zespołu linyaps pod tym adresem: \n" @@ -366,8 +361,8 @@ msgstr "Polecenie: ll-cli upgrade [OPCJE] [APLIKACJA]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Podaj ID aplikacji. Jeśli nie podasz, wszystkie aplikacje zostaną " "zaktualizowane." @@ -413,12 +408,8 @@ msgid "Specify the Keywords" msgstr "Podaj słowa kluczowe" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" -msgstr "" -"Filtruj wyniki wybranego typu. Na przykład \"runtime\", \"base\", \"app\" " -"lub \"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "Filtruj wyniki wybranego typu. Na przykład \"runtime\", \"base\", \"app\" lub \"all\"" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -434,7 +425,8 @@ msgstr "Pokaż wszystkie wersje aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:411 msgid "List installed application(s), base(s) or runtime(s)" -msgstr "Wyświetl listę zainstalowanych aplikacji, baz i środowisk wykonawczych" +msgstr "" +"Wyświetl listę zainstalowanych aplikacji, baz i środowisk wykonawczych" #: ../apps/ll-cli/src/main.cpp:414 msgid "" @@ -467,8 +459,8 @@ msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" msgstr "" -"Wyświetl listę najnowszych wersji zainstalowanych aplikacji, baz i środowisk " -"wykonawczych" +"Wyświetl listę najnowszych wersji zainstalowanych aplikacji, baz i środowisk" +" wykonawczych" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -563,19 +555,19 @@ msgstr "Priorytet repozytorium" #: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 msgid "Enable mirror for the repo" -msgstr "" +msgstr "Włącz mirror dla wybranego repozytorium" #: ../apps/ll-cli/src/main.cpp:515 msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Polecenie: ll-cli repo enable-mirror [OPCJE] ALIAS" #: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 msgid "Disable mirror for the repo" -msgstr "" +msgstr "Wyłącz mirror dla wybranego repozytorium" #: ../apps/ll-cli/src/main.cpp:522 msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Polecenie: ll-cli repo disable-mirror [OPCJE] ALIAS" #: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" @@ -734,8 +726,7 @@ msgstr "Polecenie: ll-builder [OPCJE] [PODKOMENDA]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Jeśli znajdziesz jakieś problemy, \n" "Możesz zgłosić błąd do zespołu linyaps klikając ten link: \n" @@ -767,7 +758,8 @@ msgid "File path of the linglong.yaml" msgstr "Ścieżka pliku linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Wykonuj polecenia wewnątrz kontenera, zamiast ciągle przebudowywać aplikacje" @@ -776,8 +768,8 @@ msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Korzystaj tylko z plików lokalnych. To oznacza, że flagi --skip-fetch-source " -"i --skip-pull-depend będą ustawione" +"Korzystaj tylko z plików lokalnych. To oznacza, że flagi --skip-fetch-source" +" i --skip-pull-depend będą ustawione" #: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" @@ -967,11 +959,11 @@ msgstr "Polecenie: ll-builder repo set-default [OPCJE] NAZWA" #: ../apps/ll-builder/src/main.cpp:997 msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Polecenie: ll-builder repo enable-mirror [OPCJE] ALIAS" #: ../apps/ll-builder/src/main.cpp:1005 msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" -msgstr "" +msgstr "Polecenie: ll-builder repo disable-mirror [OPCJE] ALIAS" #: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" diff --git a/po/pt_BR.po b/po/pt_BR.po index f83e00dfa..0f4cb07bf 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -2,13 +2,13 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Cassiano Molinari , 2025 # Wislley Marçal, 2025 # keven doria, 2025 # Alex, 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -17,14 +17,12 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Alex, 2025\n" -"Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/" -"teams/3976/pt_BR/)\n" -"Language: pt_BR\n" +"Language-Team: Portuguese (Brazil) (https://app.transifex.com/linuxdeepin/teams/3976/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % " -"1000000 == 0 ? 1 : 2;\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." @@ -113,8 +111,7 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Um programa em CLI para executar aplicativos e gerenciar aplicativos e " -"runtimes\n" +"Um programa em CLI para executar aplicativos e gerenciar aplicativos e runtimes\n" #: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" @@ -131,12 +128,10 @@ msgstr "Uso: ll-cli [OPÇÕES] [SUBCOMANDO]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Se encontrar qualquer problema durante o uso,\n" -"Você pode reportar erros para o time linyaps sob este projeto: https://" -"github.com/OpenAtom-Linyaps/linyaps/issues" +"Você pode reportar erros para o time linyaps sob este projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -158,7 +153,8 @@ msgstr "Usar o formato json para o resultado de saída" #: ../apps/ll-cli/src/main.cpp:186 ../apps/ll-cli/src/main.cpp:567 #: ../apps/ll-builder/src/main.cpp:95 msgid "Input parameter is empty, please input valid parameter instead" -msgstr "Parâmetro de entrada está vazio, por favor informe um parâmetro válido" +msgstr "" +"Parâmetro de entrada está vazio, por favor informe um parâmetro válido" #: ../apps/ll-cli/src/main.cpp:209 msgid "Show debug info (verbose logs)" @@ -242,8 +238,8 @@ msgstr "Executar comandos na sandbox atualmente em execução" #: ../apps/ll-cli/src/main.cpp:259 ../apps/ll-cli/src/main.cpp:277 msgid "Specify the application running instance(you can get it by ps command)" msgstr "" -"Especificar a instância de execução do aplicativo (você pode obter isto pelo " -"comando ps)" +"Especificar a instância de execução do aplicativo (você pode obter isto pelo" +" comando ps)" #: ../apps/ll-cli/src/main.cpp:262 ../apps/ll-cli/src/main.cpp:279 msgid "Specify working directory" @@ -316,7 +312,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Especifique o ID do aplicativo, que também pode ser um arquivo .uab ou .layer" +"Especifique o ID do aplicativo, que também pode ser um arquivo .uab ou " +".layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -369,8 +366,8 @@ msgstr "Uso: ll-cli upgrade [OPÇÕES] [APP]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Especifique o ID do aplicativo. Caso não seja especificado, todos os " "aplicativos serão atualizados." @@ -401,8 +398,7 @@ msgstr "" "\n" "Exemplo:\n" "\n" -"# localizar remotamente aplicativo(s), base(s) ou runtime(s) por palavras-" -"chave\n" +"# localizar remotamente aplicativo(s), base(s) ou runtime(s) por palavras-chave\n" "ll-cli search org.deepin.demo\n" "\n" "# localizar remotamente runtime pelo nome\n" @@ -422,9 +418,7 @@ msgid "Specify the Keywords" msgstr "Especifique as palavras-chave" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" "Filtrar os resultados pelo tipo especificado. Um dos valores: \"runtime\", " "\"base\", \"app\" ou \"todos\"" @@ -471,8 +465,7 @@ msgstr "" "# exibir runtimes instalados\n" "ll-cli list --type=runtime\n" "\n" -"# exibir a lista das versões mais recentes dos aplicativos instalados que " -"podem ser atualizados\n" +"# exibir a lista das versões mais recentes dos aplicativos instalados que podem ser atualizados\n" "ll-cli list --upgradable\n" #: ../apps/ll-cli/src/main.cpp:436 @@ -746,12 +739,10 @@ msgstr "Uso: ll-builder [OPÇÕES] [SUBCOMANDO]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Se você encontrar algum problema durante o uso,\n" -"Você pode reportar bugs para a equipe linyaps neste projeto: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"Você pode reportar bugs para a equipe linyaps neste projeto: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -779,7 +770,8 @@ msgid "File path of the linglong.yaml" msgstr "Caminho do arquivo linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Entre no contêiner para executar o comando em vez de construir aplicativos" diff --git a/po/sq.po b/po/sq.po index b26c7fe26..74aed04f9 100644 --- a/po/sq.po +++ b/po/sq.po @@ -2,10 +2,10 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Besnik Bleta , 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -14,12 +14,11 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Besnik Bleta , 2025\n" -"Language-Team: Albanian (https://app.transifex.com/linuxdeepin/teams/3976/" -"sq/)\n" -"Language: sq\n" +"Language-Team: Albanian (https://app.transifex.com/linuxdeepin/teams/3976/sq/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 @@ -120,12 +119,10 @@ msgstr "Përdorimi: ll-cli [MUNDËSI] [NËNURDHRA]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Nëse gjetët çfarëdo problemi gjatë përdorimit\n" -"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -359,8 +356,8 @@ msgstr "Përdorimi: ll-cli upgrade [MUNDËSI] [APLIKACION]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" #: ../apps/ll-cli/src/main.cpp:374 @@ -389,9 +386,7 @@ msgid "Specify the Keywords" msgstr "Jepni Fjalëkyçet" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" #: ../apps/ll-cli/src/main.cpp:400 @@ -694,12 +689,10 @@ msgstr "Përdorimi: ll-builder [MUNDËSI] [NËNURDHËR]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Nëse gjetët çfarëdo problemi gjatë përdorimit\n" -"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"mund të njoftoni të meta te ekipi i linyaps-it te ky projekt: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -727,7 +720,8 @@ msgid "File path of the linglong.yaml" msgstr "Shteg kartele linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "" "Jepni kontejnerin ku të ekzekutohet urdhri, në vend se të montohen " "aplikacione" diff --git a/po/uk.po b/po/uk.po index ab583e5c8..1231cb164 100644 --- a/po/uk.po +++ b/po/uk.po @@ -2,10 +2,10 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Yuri Chornoivan , 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -14,16 +14,12 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: Yuri Chornoivan , 2025\n" -"Language-Team: Ukrainian (https://app.transifex.com/linuxdeepin/teams/3976/" -"uk/)\n" -"Language: uk\n" +"Language-Team: Ukrainian (https://app.transifex.com/linuxdeepin/teams/3976/uk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " -"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " -"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " -"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 msgid "Permission denied, please check whether you are running as root." @@ -106,7 +102,8 @@ msgstr "" msgid "" "The cache generation failed, please uninstall and reinstall the application." msgstr "" -"Не вдалося створити кеш. Будь ласка, вилучіть і повторно встановіть програму." +"Не вдалося створити кеш. Будь ласка, вилучіть і повторно встановіть " +"програму." #: ../apps/ll-cli/src/main.cpp:149 msgid "" @@ -114,8 +111,7 @@ msgid "" "A CLI program to run application and manage application and runtime\n" msgstr "" "linyaps CLI\n" -"Інтерфейс командного рядка для запуску програм і керування програмами та " -"середовищами виконання програм\n" +"Інтерфейс командного рядка для запуску програм і керування програмами та середовищами виконання програм\n" #: ../apps/ll-cli/src/main.cpp:161 ../apps/ll-builder/src/main.cpp:761 msgid "Print this help message and exit" @@ -132,12 +128,10 @@ msgstr "Користування: ll-cli [ПАРАМЕТРИ] [ПІДКОМАН #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Якщо під час користування у вас виникнуть якісь проблеми,\n" -"ви можете повідомити про вади команді розробників linyaps на сторінці " -"проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -318,7 +312,8 @@ msgstr "" #: ../apps/ll-cli/src/main.cpp:322 msgid "Specify the application ID, and it can also be a .uab or .layer file" msgstr "" -"Вказати за ідентифікатором програми, також можна вказати файл .uab або .layer" +"Вказати за ідентифікатором програми, також можна вказати файл .uab або " +".layer" #: ../apps/ll-cli/src/main.cpp:325 msgid "Install a specify module" @@ -371,8 +366,8 @@ msgstr "Користування: ll-cli upgrade [ПАРАМЕТРИ] [ПРОГ #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "" "Вказати ідентифікатор програми. Якщо не вказано, буде оновлено усі програми" @@ -417,9 +412,7 @@ msgid "Specify the Keywords" msgstr "Вказати ключові слова" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" msgstr "" "Фільтрувати результат за типом. Одне зі значень, «runtime», «base», «app» " "або «all»" @@ -738,12 +731,10 @@ msgstr "Користування: ll-builder [ПАРАМЕТРИ] [ПІДКОМ #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "Якщо під час користування у вас виникнуть якісь проблеми,\n" -"ви можете повідомити про вади команді розробників linyaps на сторінці " -"проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" +"ви можете повідомити про вади команді розробників linyaps на сторінці проєкту: https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -771,7 +762,8 @@ msgid "File path of the linglong.yaml" msgstr "Шлях до файла linglong.yaml" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "Введіть контейнер для виконання команди замість збирання програм" #: ../apps/ll-builder/src/main.cpp:811 @@ -779,8 +771,8 @@ msgid "" "Only use local files. This implies --skip-fetch-source and --skip-pull-" "depend will be set" msgstr "" -"Використовувати лише локальні файли. Неявно припускає, що буде встановлено --" -"skip-fetch-source і --skip-pull-depend" +"Використовувати лише локальні файли. Неявно припускає, що буде встановлено " +"--skip-fetch-source і --skip-pull-depend" #: ../apps/ll-builder/src/main.cpp:816 msgid "Build full develop packages, runtime requires" diff --git a/po/zh_CN.po b/po/zh_CN.po index e947ac79f..81125eb6f 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -2,11 +2,11 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Gary Wang , 2025 # chang Gao, 2025 -# +# #, fuzzy msgid "" msgstr "" @@ -15,12 +15,11 @@ msgstr "" "POT-Creation-Date: 2025-07-10 14:05+0800\n" "PO-Revision-Date: 2025-04-11 01:38+0000\n" "Last-Translator: chang Gao, 2025\n" -"Language-Team: Chinese (China) (https://app.transifex.com/linuxdeepin/" -"teams/3976/zh_CN/)\n" -"Language: zh_CN\n" +"Language-Team: Chinese (China) (https://app.transifex.com/linuxdeepin/teams/3976/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../libs/linglong/src/linglong/cli/cli.cpp:71 @@ -92,9 +91,7 @@ msgstr "安装模块时不允许指定版本。" msgid "" "The latest version has been installed. If you want to replace it, try using " "'ll-cli install %1/version --force'" -msgstr "" -"当前已安装最新版本。如需覆盖安装,请尝试使用命令:ll-cli install %1/version " -"--force" +msgstr "当前已安装最新版本。如需覆盖安装,请尝试使用命令:ll-cli install %1/version --force" #: ../libs/linglong/src/linglong/cli/cli.cpp:2672 msgid "" @@ -124,12 +121,10 @@ msgstr "用法: ll-cli [选项] [子命令]" #: ../apps/ll-cli/src/main.cpp:164 msgid "" "If you found any problems during use,\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "如果在使用过程中遇到任何问题,\n" -"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-" -"Linyaps/linyaps/issues" +"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" #. add flags #: ../apps/ll-cli/src/main.cpp:171 ../apps/ll-builder/src/main.cpp:786 @@ -358,8 +353,8 @@ msgstr "用法: ll-cli upgrade [选项] [应用]" #: ../apps/ll-cli/src/main.cpp:367 msgid "" -"Specify the application ID. If it not be specified, all applications will be " -"upgraded" +"Specify the application ID. If it not be specified, all applications will be" +" upgraded" msgstr "指定应用程序名。如果未指定,将升级所有可升级的应用程序" #: ../apps/ll-cli/src/main.cpp:374 @@ -401,11 +396,8 @@ msgid "Specify the Keywords" msgstr "指定搜索关键词" #: ../apps/ll-cli/src/main.cpp:396 ../apps/ll-cli/src/main.cpp:430 -msgid "" -"Filter result with specify type. One of \"runtime\", \"base\", \"app\" or " -"\"all\"" -msgstr "" -"按指定类型过滤结果。可选类型:\"runtime\"、\"base\"、\"app\"或 \"all\"。" +msgid "Filter result with specify type. One of \"runtime\", \"base\", \"app\" or \"all\"" +msgstr "按指定类型过滤结果。可选类型:\"runtime\"、\"base\"、\"app\"或 \"all\"。" #: ../apps/ll-cli/src/main.cpp:400 msgid "Specify the repo" @@ -453,9 +445,7 @@ msgstr "" msgid "" "Show the list of latest version of the currently installed application(s), " "base(s) or runtime(s)" -msgstr "" -"显示当前已安装的应用(application)、基础环境(base)或运行时(runtime)的最" -"新版本" +msgstr "显示当前已安装的应用(application)、基础环境(base)或运行时(runtime)的最新版本" #: ../apps/ll-cli/src/main.cpp:443 msgid "Display or modify information of the repository currently using" @@ -550,19 +540,19 @@ msgstr "仓库优先级" #: ../apps/ll-cli/src/main.cpp:514 ../apps/ll-builder/src/main.cpp:996 msgid "Enable mirror for the repo" -msgstr "启用仓库镜像" +msgstr "" #: ../apps/ll-cli/src/main.cpp:515 msgid "Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS" -msgstr "用法: ll-cli repo enable-mirror [选项] 名称" +msgstr "" #: ../apps/ll-cli/src/main.cpp:521 ../apps/ll-builder/src/main.cpp:1004 msgid "Disable mirror for the repo" -msgstr "禁用仓库镜像" +msgstr "" #: ../apps/ll-cli/src/main.cpp:522 msgid "Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS" -msgstr "用法: ll-cli repo disable-mirror [选项] 名称" +msgstr "" #: ../apps/ll-cli/src/main.cpp:530 msgid "Display information about installed apps or runtimes" @@ -720,12 +710,10 @@ msgstr "用法: ll-builder [选项] [子命令]" #: ../apps/ll-builder/src/main.cpp:766 msgid "" "If you found any problems during use\n" -"You can report bugs to the linyaps team under this project: https://github." -"com/OpenAtom-Linyaps/linyaps/issues" +"You can report bugs to the linyaps team under this project: https://github.com/OpenAtom-Linyaps/linyaps/issues" msgstr "" "如果在使用过程中遇到任何问题,\n" -"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-" -"Linyaps/linyaps/issues" +"您可以通过此项目向如意玲珑项目团队报告错误:https://github.com/OpenAtom-Linyaps/linyaps/issues" #: ../apps/ll-builder/src/main.cpp:790 msgid "Create linyaps build template project" @@ -753,7 +741,8 @@ msgid "File path of the linglong.yaml" msgstr "linglong.yaml的文件路径" #: ../apps/ll-builder/src/main.cpp:808 -msgid "Enter the container to execute command instead of building applications" +msgid "" +"Enter the container to execute command instead of building applications" msgstr "进入容器执行命令而不是构建应用" #: ../apps/ll-builder/src/main.cpp:811 @@ -948,11 +937,11 @@ msgstr "用法: ll-builder repo set-default [选项] 名称" #: ../apps/ll-builder/src/main.cpp:997 msgid "Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS" -msgstr "用法: ll-builder repo enable-mirror [选项] 名称" +msgstr "" #: ../apps/ll-builder/src/main.cpp:1005 msgid "Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS" -msgstr "用法: ll-builder repo disable-mirror [选项] 名称" +msgstr "" #: ../apps/ll-builder/src/main.cpp:1012 msgid "Usage: ll-builder repo show [OPTIONS]" From bbb65678e869fac2565fe690d1a70c0f655a6ead Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 14 Jul 2025 10:18:58 +0800 Subject: [PATCH 086/366] chore: update linyaps-box Signed-off-by: ComixHe --- linglong.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linglong.yaml b/linglong.yaml index 4baa80aa1..dfca00696 100644 --- a/linglong.yaml +++ b/linglong.yaml @@ -21,8 +21,8 @@ sources: url: https://github.com/libfuse/libfuse/releases/download/fuse-3.17.1/fuse-3.17.1.tar.gz digest: 2d8ae87a4525fbfa1db5e5eb010ff6f38140627a7004554ed88411c1843d51b2 - kind: archive - url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.0-rc.5.tar.gz - digest: 109bf9e8539ce5818f52be4283de12bf9a1adf4d6a7ae422f02a3e66cc5ab0e6 + url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.1.tar.gz + digest: a1e128736ff53f5da6613eb698789ed93df1e1d48dd808c50def1afbfcf1c130 build: | echo "$PREFIX" @@ -43,7 +43,7 @@ build: | make install # build static ll-box - cd /project/linglong/sources/2.0.0-rc.5.tar.gz/linyaps-box-2.0.0-rc.5/ + cd /project/linglong/sources/2.0.1.tar.gz/linyaps-box-2.0.1/ cmake --preset static cmake --build build-static -j$(nproc) cmake --install build-static --prefix=$PREFIX From 8e4d963f9a62c03ab89be1f16df3d9ced624efd9 Mon Sep 17 00:00:00 2001 From: myml Date: Mon, 14 Jul 2025 11:21:15 +0800 Subject: [PATCH 087/366] fix: disable static deltas in OSTree pull operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added "disable-static-deltas" option set to true in OSTree pull operations 2. This change prevents the use of static deltas which can cause issues with certain repository configurations 3. The modification was made in both pull operation variants for consistency 4. Static deltas can sometimes lead to corrupted downloads or inefficient storage usage fix: 在OSTree拉取操作中禁用静态增量 1. 在OSTree拉取操作中添加了"disable-static-deltas"选项并设为true 2. 此变更防止使用静态增量,某些仓库配置下会导致问题 3. 修改在两个拉取操作变体中保持一致 4. 静态增量有时会导致下载损坏或存储使用效率低下 --- docs/mirrors.md | 68 +++++++++++++++++++ .../src/linglong/repo/ostree_repo.cpp | 16 ++++- 2 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 docs/mirrors.md diff --git a/docs/mirrors.md b/docs/mirrors.md new file mode 100644 index 000000000..24c9064f9 --- /dev/null +++ b/docs/mirrors.md @@ -0,0 +1,68 @@ +# 玲珑仓库 mirror 功能设计 + +在ll-cli和ll-builder中添加了enable-mirror和disable-mirror命令,用于启用和禁用镜像功能。 + +在对某个仓库启用mirror功能时,会更新ostree的config文件,添加contenturl配置项: + +```diff +url=$repo_url/repos/$repo_name +gpg-verify=false +http2=false ++ contenturl=mirrorlist=$repo_url/api/v2/mirrors/$repo_name +``` + +当添加contenturl配置项后,ostree会优先使用contenturl下载静态文件如files, url仅用于获取元数据如summary, contenturl支持file://、http://、https://三种协议。 + +如果在url前面添加mirrorlist=,则ostree会先从url获取按行分割的镜像列表,然后从镜像列表中选择镜像用于下载文件,具体逻辑见 [ostree_pull](#ostree-pull-步骤) 章节。 + +/api/v2/mirrors/$repo_name 是玲珑服务器的一个API接口,通过客户端IP获取客户端所在国家,从配置文件获取对应国家的镜像列表,然后返回给ostree,这样就实现了根据用户所在国家自动分流仓库文件下载的功能更。 + + +## 镜像站配置 + +玲珑的镜像站只提供仓库静态文件的https访问即可,玲珑仓库支持rsync和ostree两种同步协议。 + +### 使用 rsync 同步配置 + +优点是同步速度快,缺点是需从支持rsync协议的镜像站或官方仓库同步仓库。 + +```bash +rsync rsync://rsync.linyaps.org.cn/repos/stable $www_root/repos/stable +``` + +### 使用 ostree 同步配置 + +优点是无需协议支持,可从任意镜像站同步仓库,缺点是同步速度较慢。 + +保存下面脚本,并命名为 sync.sh,然后执行`sh sync.sh https://mirror-repo-linglong.deepin.com/repos/stable/ $www_root/repos/stable` + +```bash +#!/bin/bash +set -e +url=$1 +dir=$2 +echo sync $url to $dir +sleep 3 +ostree init --repo=$dir --mode archive +ostree --repo=$dir remote add --if-not-exists --no-sign-verify remote $url +for ref in $(ostree --repo=$dir remote refs remote); do + echo pull $ref; + ostree --repo=$dir pull --mirror $ref; +done +``` + +## ostree pull 步骤 + +### 判断镜像是否可用 +在pull时,ostree 先从contenturl获取镜像列表,然后从每个url获取/config文件,如果获取不到/config文件,则认为该mirror不可用,如果获取到/config文件,则认为该mirror可用。如果没有可用mirror,pull失败。 + +### 获取summary文件 +ostree会从url获取summary文件,如果获取不到summary文件,或者summary文件不存在ref,pull失败。 + +### delta-indexes文件获取 + +ostree会在每个可用的mirror中获取delta-indexes,如果mirror服务器返回4xx或5xx,则在下一个mirror中获取delta-indexes,如果最后的mirror返回5xx,则pull失败,如果最后的mirror返回4xx,则跳过dalta步骤直接拉取files。 + +### files文件获取 + +ostree会按顺序从可用的mirror中获取files,如果mirror服务器返回403, 404, 410,则认为错误不可恢复,pull失败,如果mirror服务器返回其他错误码,则使用下一个mirror获取files。如果所有mirror都无法获取files,则pull失败。 \ No newline at end of file diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index d2e6dfb60..b353bb054 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1302,6 +1302,10 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, "{s@v}", "append-user-agent", g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); + g_variant_builder_add(&builder, + "{s@v}", + "disable-static-deltas", + g_variant_new_variant(g_variant_new_boolean(true))); g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); // 这里不能使用g_main_context_push_thread_default,因为会阻塞Qt的事件循环 @@ -1345,6 +1349,10 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, "{s@v}", "append-user-agent", g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); + g_variant_builder_add(&builder, + "{s@v}", + "disable-static-deltas", + g_variant_new_variant(g_variant_new_boolean(true))); g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); @@ -1997,7 +2005,8 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, if (is_regular_file) { // 如果有指定的后缀名,则只处理指定后缀名的文件 if (fileSuffix.has_value() - && !endWithFunc(std::string_view(source_path.string()), std::string_view(fileSuffix.value()))) { + && !endWithFunc(std::string_view(source_path.string()), + std::string_view(fileSuffix.value()))) { continue; } @@ -2042,7 +2051,7 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, if (ec) { return LINGLONG_ERR("copy file failed: " + sourceNewPath, ec); } - + // TODO 这部分代码可以删除 exists = std::filesystem::exists(sourceNewPath, ec); if (ec) { @@ -2061,7 +2070,8 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, return LINGLONG_ERR("get hard link count", ec); } if (hard_link_count > 1) { - auto ret = IniLikeFileRewrite(QFileInfo(sourceNewPath.c_str()), appID.c_str()); + auto ret = + IniLikeFileRewrite(QFileInfo(sourceNewPath.c_str()), appID.c_str()); if (!ret) { qWarning() << "rewrite file failed: " << ret.error().message(); continue; From c698fb61d07b141bc3ee60d356e5a68298758882 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 14 Jul 2025 18:14:42 +0800 Subject: [PATCH 088/366] fix: Set LINGLONG_LD_SO_CACHE for compatibility Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 337b9a50c..b0ede7374 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -957,6 +957,12 @@ utils::error::Result Builder::buildStageBuild(const QStringList &args) noe process.cwd = "/project"; process.env = { { "PREFIX=" + installPrefix, + // During the build stage, we use overlayfs where /etc/ld.so.cache is safe + // to serve as the dynamic library cache. This allows direct invocation of + // ldconfig without the -C option. + // + // Note: LINGLONG_LD_SO_CACHE is retained here solely for backward compatibility. + "LINGLONG_LD_SO_CACHE=/etc/ld.so.cache", "TRIPLET=" + triplet, } }; process.noNewPrivileges = true; From 8c4f5864a83f949f98f9f1141fe019000490d363 Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 15 Jul 2025 15:30:25 +0800 Subject: [PATCH 089/366] chore: update smoketest Adds a basic smoke test for the Linglong package manager using a dedicated development repository. --- tools/test-linglong.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/test-linglong.sh b/tools/test-linglong.sh index 60f1d9261..32385897b 100755 --- a/tools/test-linglong.sh +++ b/tools/test-linglong.sh @@ -6,6 +6,15 @@ set -xe +echo "开始玲珑冒烟测试" + +# 修改仓库为冒烟测试仓库 +ll-cli repo add smoketesting https://repo-dev.cicd.getdeepin.org +ll-cli repo set-default smoketesting + +ll-builder repo add smoketesting https://repo-dev.cicd.getdeepin.org +ll-builder repo set-default smoketesting + #创建玲珑项目 ll-builder create org.dde.demo @@ -37,6 +46,7 @@ ll-cli uninstall org.dde.demo || true ./org.dde.demo_x86_64_0.0.0.1_main.uab #安装构建的应用 +ll-cli install org.dde.demo_x86_64_0.0.0.1_main.uab ll-cli uninstall org.dde.demo || true ll-cli install org.dde.demo_0.0.0.1_x86_64_binary.layer @@ -103,8 +113,6 @@ ll-cli list | grep org.dde.calendar | grep -vq lang-ja #测试versionV1 升级到 versionV2 echo "测试versionV1 升级到 versionV2" -ll-cli repo add stable https://repo-dev.cicd.getdeepin.org --alias test-stable -ll-cli repo set-default test-stable ll-cli search org.deepin.semver.demo # 安装 @@ -128,3 +136,5 @@ ll-cli list | grep org.deepin.semver.demo #重置默认仓库 ll-cli repo set-default stable ll-cli uninstall org.deepin.semver.demo + +echo "成功执行玲珑冒烟测试" From 33ac90db39aad856015f2727c54072803313d2af Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 15 Jul 2025 16:29:28 +0800 Subject: [PATCH 090/366] fix: fix compiler on gcc-8 Signed-off-by: reddevillg --- apps/uab/loader/src/main.cpp | 78 +++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/apps/uab/loader/src/main.cpp b/apps/uab/loader/src/main.cpp index eb796705e..e3c13c6d2 100644 --- a/apps/uab/loader/src/main.cpp +++ b/apps/uab/loader/src/main.cpp @@ -187,29 +187,30 @@ bool processLDConfig(linglong::generator::ContainerCfgBuilder &builder, } } - builder.addExtraMounts({ { - .destination = "/etc/" + randomFile.filename().string(), - .options = { { "ro", "rbind" } }, - .source = randomFile, - .type = "bind", - }, - { - .destination = "/etc/ld.so.conf.d/zz_deepin-linglong.ld.so.conf", - .options = { { "ro", "rbind" } }, - .source = ldConf, - .type = "bind", - } }); - - builder.setStartContainerHooks( - { { - .args = std::vector{ "/sbin/ldconfig", "-C", "/tmp/ld.so.cache" }, - .path = "/sbin/ldconfig", - }, - { - .args = - std::vector{ "/bin/sh", "-c", "cat /tmp/ld.so.cache > /etc/ld.so.cache" }, - .path = "/bin/sh", - } }); + builder.addExtraMounts(std::vector{ + ocppi::runtime::config::types::Mount{ + .destination = "/etc/" + randomFile.filename().string(), + .options = { { "ro", "rbind" } }, + .source = randomFile, + .type = "bind", + }, + ocppi::runtime::config::types::Mount{ + .destination = "/etc/ld.so.conf.d/zz_deepin-linglong.ld.so.conf", + .options = { { "ro", "rbind" } }, + .source = ldConf, + .type = "bind", + } }); + + builder.setStartContainerHooks(std::vector{ + ocppi::runtime::config::types::Hook{ + .args = std::vector{ "/sbin/ldconfig", "-C", "/tmp/ld.so.cache" }, + .path = "/sbin/ldconfig", + }, + ocppi::runtime::config::types::Hook{ + .args = + std::vector{ "/bin/sh", "-c", "cat /tmp/ld.so.cache > /etc/ld.so.cache" }, + .path = "/bin/sh", + } }); return true; } @@ -326,18 +327,19 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT .forwardEnv() .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) - .addExtraMounts({ { - .destination = "/etc/ld.so.cache", - .options = { { "rbind" } }, - .source = runtimeLD, - .type = "bind", - }, - { - .destination = "/tmp", - .options = { { "rbind" } }, - .source = "/tmp", - .type = "bind", - } }); + .addExtraMounts( + std::vector{ ocppi::runtime::config::types::Mount{ + .destination = "/etc/ld.so.cache", + .options = { { "rbind" } }, + .source = runtimeLD, + .type = "bind", + }, + ocppi::runtime::config::types::Mount{ + .destination = "/tmp", + .options = { { "rbind" } }, + .source = "/tmp", + .type = "bind", + } }); auto extraDir = bundleDir / "extra"; if (!std::filesystem::exists(extraDir, ec)) { @@ -469,8 +471,10 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) // NOLINT auto linux_ = json["linux"].get(); linux_.namespaces = std::vector{ - { .type = ocppi::runtime::config::types::NamespaceType::User }, - { .type = ocppi::runtime::config::types::NamespaceType::Mount } + ocppi::runtime::config::types::NamespaceReference{ + .type = ocppi::runtime::config::types::NamespaceType::User }, + ocppi::runtime::config::types::NamespaceReference{ + .type = ocppi::runtime::config::types::NamespaceType::Mount } }; json["linux"] = std::move(linux_); From bfdd30d72bf5d9269b5b62cd02c3ea09b7a4485d Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 15 Jul 2025 16:32:02 +0800 Subject: [PATCH 091/366] fix: fix compiler error on nlohmann_json 3.9.1 Signed-off-by: reddevillg --- libs/linglong/src/linglong/cli/cli.cpp | 2 +- libs/linglong/src/linglong/package/layer_file.cpp | 2 +- libs/utils/src/linglong/utils/serialize/json.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index d4149d01a..505df5ab0 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -2550,7 +2550,7 @@ Cli::RequestDirectories(const api::types::v1::PackageInfoV2 &info) noexcept auto rawData = dialogProc.read(4); auto *len = reinterpret_cast(rawData.data()); rawData = dialogProc.read(*len); - auto version = utils::serialize::LoadJSON(rawData); + auto version = utils::serialize::LoadJSON(rawData.data()); if (!version) { dialogProc.kill(); return LINGLONG_ERR("error reply from dialog:" + version.error().message()); diff --git a/libs/linglong/src/linglong/package/layer_file.cpp b/libs/linglong/src/linglong/package/layer_file.cpp index f35ad25a6..7e884c879 100644 --- a/libs/linglong/src/linglong/package/layer_file.cpp +++ b/libs/linglong/src/linglong/package/layer_file.cpp @@ -78,7 +78,7 @@ utils::error::Result LayerFile::metaInfo() noexcept auto rawData = this->read(qint64(*ret)); - auto layerInfo = utils::serialize::LoadJSON(rawData); + auto layerInfo = utils::serialize::LoadJSON(rawData.data()); if (!layerInfo) { return LINGLONG_ERR(layerInfo); } diff --git a/libs/utils/src/linglong/utils/serialize/json.h b/libs/utils/src/linglong/utils/serialize/json.h index 86cc3bbb7..54b36d9cc 100644 --- a/libs/utils/src/linglong/utils/serialize/json.h +++ b/libs/utils/src/linglong/utils/serialize/json.h @@ -101,7 +101,7 @@ error::Result LoadJSONFile(QFile &file) noexcept return LINGLONG_ERR("read all", file); } - return LoadJSON(content); + return LoadJSON(content.data()); } template From 6e3d3771743562bf1bcc2b1e18f4c677adf7667a Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 15 Jul 2025 16:38:27 +0800 Subject: [PATCH 092/366] fix: add rbind option alongside copy-symlink Signed-off-by: reddevillg --- .../linglong/oci-cfg-generators/container_cfg_builder.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 210893beb..062c9f3db 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -1193,8 +1193,9 @@ bool ContainerCfgBuilder::buildMountLocalTime() noexcept isSymLink = true; } localtimeMount->emplace_back(Mount{ .destination = localtime.string(), - .options = isSymLink ? string_list{ "copy-symlink" } - : string_list{ "rbind", "ro" }, + .options = isSymLink + ? string_list{ "rbind", "copy-symlink" } + : string_list{ "rbind", "ro" }, .source = localtime, .type = "bind" }); } @@ -1239,7 +1240,7 @@ bool ContainerCfgBuilder::buildMountNetworkConf() noexcept } networkConfMount->emplace_back(Mount{ .destination = resolvConf.string(), - .options = string_list{ "copy-symlink" }, + .options = string_list{ "rbind", "copy-symlink" }, .source = bundleResolvConf, .type = "bind" }); } else { From 3dd66a9a7900343aa8f32331f362b8f13ac560af Mon Sep 17 00:00:00 2001 From: reddevillg Date: Tue, 15 Jul 2025 16:42:50 +0800 Subject: [PATCH 093/366] fix: clean sources directory on every build Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index b0ede7374..372f34d38 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -519,10 +519,10 @@ utils::error::Result Builder::buildStageFetchSource() noexcept if (!qEnvironmentVariableIsEmpty("LINGLONG_FETCH_CACHE")) { fetchCacheDir = qgetenv("LINGLONG_FETCH_CACHE"); } - auto result = fetchSources(*this->project.sources, - fetchCacheDir, - this->workingDir.absoluteFilePath("linglong/sources"), - this->cfg); + // clean sources directory on every build + auto fetchSourcesDir = QDir(this->workingDir.absoluteFilePath("linglong/sources")); + fetchSourcesDir.removeRecursively(); + auto result = fetchSources(*this->project.sources, fetchCacheDir, fetchSourcesDir, this->cfg); if (!result) { return LINGLONG_ERR(result); From 36c92617e0fb83e5081a59bf20d708c29a4ab657 Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 15 Jul 2025 21:21:37 +0800 Subject: [PATCH 094/366] fix: update linglong test script with cleanup and improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added environment cleanup at start (remove old demo, reset repos) 2. Changed org.dde.demo to org.deepin.demo for consistency 3. Reduced sleep time from 20s to 5s for faster testing 4. Simplified process killing using appid instead of version/arch 5. Fixed module test sequence by moving uninstall before install 6. Improved overall script reliability with better cleanup steps fix: 更新玲珑测试脚本并添加清理和改进 1. 在开始时添加环境清理(移除旧demo,重置仓库) 2. 将org.dde.demo改为org.deepin.demo保持一致性 3. 将等待时间从20秒减少到5秒以加快测试 4. 简化进程终止逻辑,直接使用appid而非版本/架构 5. 修复模块测试顺序,将卸载操作移到安装前 6. 通过更好的清理步骤提高脚本整体可靠性 --- tools/test-linglong.sh | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/test-linglong.sh b/tools/test-linglong.sh index 32385897b..913db7b8b 100755 --- a/tools/test-linglong.sh +++ b/tools/test-linglong.sh @@ -6,6 +6,13 @@ set -xe +# 清理环境 +rm -rf org.deepin.demo || true +ll-cli repo set-default stable +ll-cli repo remove smoketesting || true +ll-builder repo set-default stable +ll-builder repo remove smoketesting || true + echo "开始玲珑冒烟测试" # 修改仓库为冒烟测试仓库 @@ -16,10 +23,10 @@ ll-builder repo add smoketesting https://repo-dev.cicd.getdeepin.org ll-builder repo set-default smoketesting #创建玲珑项目 -ll-builder create org.dde.demo +ll-builder create org.deepin.demo #构建玲珑应用 -pushd org.dde.demo +pushd org.deepin.demo ll-builder build #导出layer文件 @@ -42,19 +49,19 @@ export DBUS_SYSTEM_BUS_ADDRESS="unix:path=/var/run/dbus/system_bus_socket,test=2 ll-builder run -- bash -c "export" | grep DBUS_SYSTEM_BUS_ADDRESS | grep test=2 #运行并安装uab -ll-cli uninstall org.dde.demo || true -./org.dde.demo_x86_64_0.0.0.1_main.uab +ll-cli uninstall org.deepin.demo || true +./org.deepin.demo_x86_64_0.0.0.1_main.uab #安装构建的应用 -ll-cli install org.dde.demo_x86_64_0.0.0.1_main.uab -ll-cli uninstall org.dde.demo || true -ll-cli install org.dde.demo_0.0.0.1_x86_64_binary.layer +ll-cli install org.deepin.demo_x86_64_0.0.0.1_main.uab +ll-cli uninstall org.deepin.demo || true +ll-cli install org.deepin.demo_0.0.0.1_x86_64_binary.layer #运行安装好的demo -timeout 10 ll-cli run org.dde.demo +timeout 10 ll-cli run org.deepin.demo popd -rm -rf org.dde.demo -ll-cli uninstall org.dde.demo +rm -rf org.deepin.demo +ll-cli uninstall org.deepin.demo #列出已经安装的应用 ll-cli list @@ -87,14 +94,13 @@ ll-cli upgrade "$appid" #运行玲珑应用 ll-cli run "$appid" & -sleep 20 +sleep 5 -cur_version=$(ll-cli info "$appid" | jq '.version' | xargs) -arch=$(uname -m) -ll-cli kill "main:$appid/$cur_version/$arch" +ll-cli kill -9 "$appid" +sleep 3 +ll-cli uninstall org.dde.calendar # 测试module安装 -ll-cli uninstall org.dde.calendar ll-cli install org.dde.calendar/5.14.4.102 ll-cli install --module develop org.dde.calendar ll-cli install --module unuse org.dde.calendar From 19111373910932eb964220034ef8fd19cd9504dd Mon Sep 17 00:00:00 2001 From: myml Date: Wed, 16 Jul 2025 10:32:19 +0800 Subject: [PATCH 095/366] fix: correct kill command in linglong test script Updated the process termination command in the test-linglong.sh script from 'll-cli kill -9' to 'll-cli kill -kill 9' for proper syntax and functionality. --- tools/test-linglong.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/test-linglong.sh b/tools/test-linglong.sh index 913db7b8b..35bd91aba 100755 --- a/tools/test-linglong.sh +++ b/tools/test-linglong.sh @@ -96,7 +96,7 @@ ll-cli upgrade "$appid" ll-cli run "$appid" & sleep 5 -ll-cli kill -9 "$appid" +ll-cli kill -s 9 "$appid" sleep 3 ll-cli uninstall org.dde.calendar From 466faea89515b0bc7525ca24386d099d9ced134b Mon Sep 17 00:00:00 2001 From: dengbo Date: Wed, 16 Jul 2025 10:17:05 +0800 Subject: [PATCH 096/366] refactor: extends ll-cli dir command with module support Adds support for specifying a module when using the `ll-cli dir` command. This allows users to retrieve the layer directory for a specific module within an application. --- apps/ll-cli/src/main.cpp | 4 ++++ libs/linglong/src/linglong/cli/cli.cpp | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/ll-cli/src/main.cpp b/apps/ll-cli/src/main.cpp index 2f55599cb..3b449a973 100644 --- a/apps/ll-cli/src/main.cpp +++ b/apps/ll-cli/src/main.cpp @@ -583,9 +583,13 @@ ll-cli list --upgradable auto cliLayerDir = commandParser.add_subcommand("dir", "Get the layer directory of app(base or runtime)") ->group(CliHiddenGroup); + cliLayerDir->footer("This subcommand is for internal use only currently"); cliLayerDir->add_option("APP", options.appid, _("Specify the installed app(base or runtime)")) ->required() ->check(validatorString); + cliLayerDir->add_option("--module", options.module, _("Specify a module")) + ->type_name("MODULE") + ->check(validatorString); auto res = transformOldExec(argc, argv); CLI11_PARSE(commandParser, std::move(res)); diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 505df5ab0..06699d497 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -2794,13 +2794,18 @@ int Cli::dir([[maybe_unused]] CLI::App *subcommand) return -1; } - auto layerItem = this->repository.getLayerItem(*ref); - if (!layerItem) { - this->printer.printErr(layerItem.error()); + std::string module = "binary"; + if (!options.module.empty()) { + module = options.module; + } + + auto layerDir = this->repository.getLayerDir(*ref, module); + if (!layerDir) { + this->printer.printErr(layerDir.error()); return -1; } - std::cout << layerItem->commit << std::endl; + std::cout << layerDir->absolutePath().toStdString() << std::endl; return 0; } From 2ae89a44d89eaddacd08d9e23af8cbae5e7e1553 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 16 Jul 2025 14:38:46 +0800 Subject: [PATCH 097/366] fix: Return exit code of initial child process The init process will now exit with the same code as the initial child process it manages. This is crucial for environments like the builder, where the success or failure of a command must be detected. Add missing LINYAPS_INIT_SINGLE_MODE in handling process build depends. Signed-off-by: reddevillg --- apps/ll-init/src/ll-init.cpp | 38 ++++++++++++++----- .../src/linglong/builder/linglong_builder.cpp | 3 +- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/ll-init/src/ll-init.cpp b/apps/ll-init/src/ll-init.cpp index ce0aae414..c7bf80a0f 100644 --- a/apps/ll-init/src/ll-init.cpp +++ b/apps/ll-init/src/ll-init.cpp @@ -29,6 +29,12 @@ constexpr std::array unblock_signals{ SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV namespace { +struct WaitPidResult +{ + pid_t pid; + int status; +}; + void print_sys_error(std::string_view msg) noexcept { std::cerr << msg << ": " << ::strerror(errno) << std::endl; @@ -286,7 +292,9 @@ pid_t run(std::vector args, const sigConf &conf) noexcept return pid; } -bool handle_sigevent(const file_descriptor_wrapper &sigfd, pid_t &child) noexcept +bool handle_sigevent(const file_descriptor_wrapper &sigfd, + pid_t child, + struct WaitPidResult &waitChild) noexcept { while (true) { signalfd_siginfo info{}; @@ -325,10 +333,8 @@ bool handle_sigevent(const file_descriptor_wrapper &sigfd, pid_t &child) noexcep print_child_status(status, std::to_string(ret)); if (ret == child) { - // child exited, reset the child pid to -1. - // after that, init will broadcast the forwarded signal to all processes in the - // pid namespace. - child = -1; + waitChild.pid = child; + waitChild.status = status; } } } @@ -637,6 +643,8 @@ int main(int argc, char **argv) // NOLINT file_descriptor_wrapper timerfd; bool done{ false }; std::array events{}; + WaitPidResult waitChild{ .pid = child }; + int childExitCode = 0; while (true) { ret = ::epoll_wait(epfd, events.data(), events.size(), -1); if (ret == -1) { @@ -647,12 +655,24 @@ int main(int argc, char **argv) // NOLINT for (auto i = 0; i < ret; ++i) { const auto event = events.at(i); if (event.data.fd == sigfd) { - const int temp_child{ child }; - if (!handle_sigevent(sigfd, child)) { + if (!handle_sigevent(sigfd, waitChild.pid, waitChild)) { return -1; } - if (temp_child != child) { + if (waitChild.pid == child) { + // Init process will propagate received signals to all child processes (using + // pid -1) after initial child exits + if (WIFEXITED(waitChild.status)) { + waitChild.pid = -1; + childExitCode = WEXITSTATUS(waitChild.status); + } else if (WIFSIGNALED(waitChild.status)) { + waitChild.pid = -1; + childExitCode = 128 + WTERMSIG(waitChild.status); + } + + if (!shouldWait()) { + done = true; + } timerfd = start_timer(epfd); if (!timerfd) { return -1; @@ -688,5 +708,5 @@ int main(int argc, char **argv) // NOLINT } } - return 0; + return childExitCode; } diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 372f34d38..448226a57 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -760,7 +760,8 @@ utils::error::Result Builder::processBuildDepends() noexcept .options = { { "rbind", "ro" } }, .source = this->workingDir.absolutePath().toStdString(), .type = "bind" }) - .forwardDefaultEnv(); + .forwardDefaultEnv() + .appendEnv("LINYAPS_INIT_SINGLE_MODE", "1"); // overwrite runtime overlay directory if (cfgBuilder.getRuntimePath()) { From 594703597c57ccbd8f43dbb419b1b9e68b6c4b9b Mon Sep 17 00:00:00 2001 From: ComixHe Date: Wed, 16 Jul 2025 15:32:44 +0800 Subject: [PATCH 098/366] chore: update linyaps-box to 2.0.2 Signed-off-by: ComixHe --- linglong.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/linglong.yaml b/linglong.yaml index dfca00696..bcf9a4cb4 100644 --- a/linglong.yaml +++ b/linglong.yaml @@ -9,20 +9,18 @@ package: kind: app description: | Utils for ll-builder - command: [/opt/apps/cn.org.linyaps.builder.utils/files/bin/ll-builder-export] - base: org.deepin.base/25.2.0 sources: - kind: archive - url: https://github.com/erofs/erofs-utils/archive/refs/tags/v1.8.6.tar.gz + url: https://github.com/erofs/erofs-utils/archive/refs/tags/v1.8.6.tar.gz digest: 5b221dc3fd6d151425b30534ede46fb7a90dc233a8659cba0372796b0a066547 - kind: archive - url: https://github.com/libfuse/libfuse/releases/download/fuse-3.17.1/fuse-3.17.1.tar.gz + url: https://github.com/libfuse/libfuse/releases/download/fuse-3.17.1/fuse-3.17.1.tar.gz digest: 2d8ae87a4525fbfa1db5e5eb010ff6f38140627a7004554ed88411c1843d51b2 - kind: archive - url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.1.tar.gz - digest: a1e128736ff53f5da6613eb698789ed93df1e1d48dd808c50def1afbfcf1c130 + url: https://github.com/OpenAtom-Linyaps/linyaps-box/archive/refs/tags/2.0.2.tar.gz + digest: 13100b8d9b1c0775e23ab4fb9b9fd9726a27df04bd112b303b6abf18df53ce60 build: | echo "$PREFIX" @@ -43,7 +41,7 @@ build: | make install # build static ll-box - cd /project/linglong/sources/2.0.1.tar.gz/linyaps-box-2.0.1/ + cd /project/linglong/sources/2.0.2.tar.gz/linyaps-box-2.0.2/ cmake --preset static cmake --build build-static -j$(nproc) cmake --install build-static --prefix=$PREFIX From e5c882f039f86a442b144847b37f9b4a2410007c Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 17 Jul 2025 16:42:12 +0800 Subject: [PATCH 099/366] chore: adds DeepSource configuration and badge Adds a DeepSource configuration file for static analysis and includes a DeepSource badge in the README files to display the project's code quality status. --- .deepsource.toml | 37 +++++++++++++++++++++++++++++++++++++ README.md | 1 + README.zh_CN.md | 1 + 3 files changed, 39 insertions(+) create mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 000000000..1b02247cd --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: None +# +# SPDX-License-Identifier: CC0-1.0 + +version = 1 + +[[analyzers]] +name = "cxx" +enabled = true + +[analyzers.meta] +environment = ["CMAKE_CXX_STANDARD=17", "CMAKE_CXX_STANDARD_REQUIRED=ON"] +include_paths = ["libs/*/src/", "apps/*/src/", "external/*/include/", "build/"] +compile_commands = "build/compile_commands.json" + +[[analyzers]] +name = "shell" +enabled = true + +[[analyzers]] +name = "secrets" +enabled = true + +[[analyzers]] +name = "test-coverage" +enabled = false + +[[transformers]] +name = "clang-format" +enabled = true + +[[transformers]] +name = "prettier" +enabled = true + +[transformers.meta] +include_patterns = ["**/*.md", "**/*.json", "**/*.yaml", "**/*.yml"] diff --git a/README.md b/README.md index 0a511a74f..283108625 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![Latest Release](https://img.shields.io/github/v/release/OpenAtom-Linyaps/linyaps?style=flat&color=brightgreen)](https://github.com/OpenAtom-Linyaps/linyaps/releases) [![Powered by Linyaps](https://img.shields.io/badge/powered%20by-Linyaps-ff69b4)](https://github.com/OpenAtom-Linyaps/linyaps) [![Build Status](https://build.deepin.com/projects/linglong:CI:latest/packages/linyaps/badge.svg?type=default)](https://build.deepin.com/projects/linglong:CI:latest) +[![DeepSource](https://app.deepsource.com/gh/OpenAtom-Linyaps/linyaps.svg/?label=active+issues&show_trend=true&token=REPLACE_WITH_TOKEN)](https://app.deepsource.com/gh/OpenAtom-Linyaps/linyaps/) [![GitHub Stars](https://img.shields.io/github/stars/OpenAtom-Linyaps/linyaps?style=social)](https://github.com/OpenAtom-Linyaps/linyaps/stargazers) [![GitHub Forks](https://img.shields.io/github/forks/OpenAtom-Linyaps/linyaps?style=social&label=Fork)](https://github.com/OpenAtom-Linyaps/linyaps/network/members) diff --git a/README.zh_CN.md b/README.zh_CN.md index ea6830570..c827e5fa3 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -9,6 +9,7 @@ [![Latest Release](https://img.shields.io/github/v/release/OpenAtom-Linyaps/linyaps?style=flat&color=brightgreen)](https://github.com/OpenAtom-Linyaps/linyaps/releases) [![Powered by Linyaps](https://img.shields.io/badge/powered%20by-Linyaps-ff69b4)](https://github.com/OpenAtom-Linyaps/linyaps) [![Build Status](https://build.deepin.com/projects/linglong:CI:latest/packages/linyaps/badge.svg?type=default)](https://build.deepin.com/projects/linglong:CI:latest) +[![DeepSource](https://app.deepsource.com/gh/OpenAtom-Linyaps/linyaps.svg/?label=active+issues&show_trend=true&token=REPLACE_WITH_TOKEN)](https://app.deepsource.com/gh/OpenAtom-Linyaps/linyaps/) [![GitHub Stars](https://img.shields.io/github/stars/OpenAtom-Linyaps/linyaps?style=social)](https://github.com/OpenAtom-Linyaps/linyaps/stargazers) [![GitHub Forks](https://img.shields.io/github/forks/OpenAtom-Linyaps/linyaps?style=social&label=Fork)](https://github.com/OpenAtom-Linyaps/linyaps/network/members) From b89b6435e869a51b419cf99a1cd3f1c8fe2512c4 Mon Sep 17 00:00:00 2001 From: dengbo Date: Thu, 17 Jul 2025 16:55:10 +0800 Subject: [PATCH 100/366] chore: removes meta analyzer configuration Removes the meta analyzer configuration from the DeepSource configuration file. --- .deepsource.toml | 5 --- docs/pages/guide/lessons/build-offline-src.md | 31 +++++++++++++------ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.deepsource.toml b/.deepsource.toml index 1b02247cd..0097ef53b 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -8,11 +8,6 @@ version = 1 name = "cxx" enabled = true -[analyzers.meta] -environment = ["CMAKE_CXX_STANDARD=17", "CMAKE_CXX_STANDARD_REQUIRED=ON"] -include_paths = ["libs/*/src/", "apps/*/src/", "external/*/include/", "build/"] -compile_commands = "build/compile_commands.json" - [[analyzers]] name = "shell" enabled = true diff --git a/docs/pages/guide/lessons/build-offline-src.md b/docs/pages/guide/lessons/build-offline-src.md index cbbde437f..a6fc5b22e 100644 --- a/docs/pages/guide/lessons/build-offline-src.md +++ b/docs/pages/guide/lessons/build-offline-src.md @@ -1,4 +1,5 @@ # 将基于Qt5的开源应用--qBittorrent 适配为支持自动化的玲珑应用构建工程 + 在学习上一章节 `在玲珑容器中编译基于Qt5的开源应用--qBittorrent` 后, 我们已经大概了解了在玲珑容器中通过怎么样的操作可以将基于Qt5的开源应用--qBittorrent项目源代码编译为可以运行的二进制程序文件. 今天, 我们在此基础上补齐 `玲珑应用构建基本步骤` 中的最后步骤--编写一份完整的玲珑应用构建工程配置文件 `linglong.yaml`, 主要实现以下的目标: @@ -8,6 +9,7 @@ 3. 自动执行编译构建、安装操作 ## 前期准备 + 根据 `玲珑应用构建工程基础知识` 中对于 `玲珑应用构建工程通用资源的规范` 要求, 我们应当为一款图形化应用同时提供保障桌面用户体验的 `icons` 图标文件及 `desktop` 启动文件 因此, 我们今天为了能够编写自动编译 `qBittorrent` 的完整 `linglong.yaml`,需要额外准备以下材料: @@ -17,6 +19,7 @@ 3. 第三方运行库 libtorrent 开源项目的仓库git信息、tag版本、commit信息 ### 通用资源准备 + 由于在上节课堂中我们在玲珑容器内已经成功编译并运行了 `qBittorrent`, 并且这款应用在安装到$PREFIX之后一并提供了icons目录、desktop启动文件 我们对这两项进行检查, 确认均符合 `Freedesktop XDG规范`, 因此我们仅需要直接从容器中复制到本地即可, 即复制到构建目录 `/project` 中. @@ -31,6 +34,7 @@ qbittorrent.png ``` 于是, 我们得到了 `非二进制文件通用资源`, 为了方便被构建组件使用, 我这里将这些文件放到了构建目录的 `template_app` 子目录中, 现在呈现此类结构: + ``` template_app ├── linglong.yaml @@ -54,8 +58,10 @@ template_app ``` ### desktop 启动文件定制 + 根据基础知识课程的 `玲珑应用构建工程通用资源的规范`, 我们需要确保当前的desktop文件符合相关规范 我们打开从容器中导出的desktop文件, 检查Exec和Icon字段, 得出以下结果: + ``` [Desktop Entry] Categories=Network;FileTransfer;P2P;Qt; @@ -71,12 +77,11 @@ Icon=qbittorrent 2. Exec字段值不为玲珑容器内编译的结果, 需要修改为符合 `玲珑应用构建工程通用资源的规范` 的内容, 这里替换为绝对路径指向容器中的具体二进制文件, 用于唤醒容器并启动该应用 ## 构建工程配置文件 `linglong.yaml` 准备 + 在准备图形化应用所必备的通用资源后, 我们着手编写构建规则 由于在上节课程中我们已经准备了一版简单但不具备完整构建功能的 `linglong.yaml`, 因此我们可以在其基础上进行定制, 现在是初始状态: + ```yaml -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later version: "4.6.7.2" @@ -109,6 +114,7 @@ build: | 以下是正式开始改造的过程: 1. 通过 `普通操作` 窗口使用 `git` 将 `qBittorrent` 和 `libtorrent-rasterbar` 源码拉取或解压到构建目录中, 我这里通过源码压缩包单独解压到子目录中 + ``` ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ tar -xvf qBittorrent-4.6.7-git-origin-src.tar.zst -C src/ ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ tar -xvf libtorrent-rasterbar-2.0.9.tar.gz -C 3rd/ @@ -116,24 +122,25 @@ ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ tar -xvf libtorr ``` 2. 从 `玲珑应用目录结构规范` 得知, 构建目录会被映射为 `/project`, 因此我们需要将上节课程中使用的手动编译命令写入 `build` 模块中 + ``` build: | mkdir -p ${PREFIX}/bin/ ${PREFIX}/share/ - ##Build 3rd libs 注释:进入 `libtorrent-rasterbar` 源码目录并编译安装到容器内 + ##Build 3rd libs 注释:进入 `libtorrent-rasterbar` 源码目录并编译安装到容器内 mkdir /project/3rd/libtorrent-rasterbar-2.0.9/build cd /project/3rd/libtorrent-rasterbar-2.0.9/build cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX .. make -j$(nproc) make install - ##Build main 注释:进入 `qBittorrent` 源码目录并编译安装到容器内 + ##Build main 注释:进入 `qBittorrent` 源码目录并编译安装到容器内 mkdir /project/src/qBittorrent-release-4.6.7-szbt2/build cd /project/src/qBittorrent-release-4.6.7-szbt2/build cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=$PREFIX .. make -j$(nproc) make install - ##Extract common res 注释: 将通用文件复制安装到容器对应目录内, 符合 `玲珑应用目录结构规范` + ##Extract common res 注释: 将通用文件复制安装到容器对应目录内, 符合 `玲珑应用目录结构规范` cp -rf /project/template_app/* ${PREFIX}/share/ ``` @@ -143,10 +150,8 @@ build: | ### 本地一站构建测试 在补全 `build` 模块后, 此时的 `linglong.yaml` 状态: + ```yaml -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later version: "2" @@ -195,23 +200,29 @@ ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ ll-builder build ``` 得益于在玲珑容器中的编译笔记, 此次构建很快就成功结束了, 我们执行以下指令来将容器导出为玲珑应用安装包 `binary.layer` : + ``` ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ ll-builder export --layer ``` ## 本地构建结果测试 + 在得到玲珑应用安装包后, 我在不同支持玲珑环境的主流发行版上尝试体验, 来确认通过玲珑容器构建的二进制程序是否存在通用性 ### deepin 23 + ![deepin 23](image/3-test-1.png) ### openKylin 2.0 + ![openKylin 2.0](image/3-test-2.png) ### Ubuntu 2404 + ![Ubuntu 2404](image/3-test-3.png) ### OpenEuler 2403 + ![OpenEuler 2403](image/3-test-4.png) -至此, 足以证明 `基于Qt5的开源应用--qBittorrent` 可以构建完成后, 在支持 `如意玲珑` 应用方案的第三方发行版中成功运行! \ No newline at end of file +至此, 足以证明 `基于Qt5的开源应用--qBittorrent` 可以构建完成后, 在支持 `如意玲珑` 应用方案的第三方发行版中成功运行! From d08c84bd6e1ded4c615b9f20cd4f7ddfb0c0d320 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Thu, 17 Jul 2025 11:39:52 +0800 Subject: [PATCH 101/366] Fix: Correct build order and fix private mounting Move buildMountHome after buildPrivateDir, because it depends on private directory that are initialized within buildPrivateDir. Correct private config, cache, state directory mounting. Signed-off-by: reddevillg --- .../container_cfg_builder.cpp | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 062c9f3db..4072de82c 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -716,12 +716,25 @@ bool ContainerCfgBuilder::buildMountHome() noexcept } environment["XDG_DATA_HOME"] = containerDataHome; + auto checkPrivatePath = [this](const std::filesystem::path &path) -> std::filesystem::path { + if (!privateMount) { + return std::filesystem::path{}; + } + + std::error_code ec; + if (std::filesystem::exists(privateAppDir / path, ec)) { + return privateAppDir / path; + } + + return std::filesystem::path{}; + }; + value = getenv("XDG_CONFIG_HOME"); std::filesystem::path XDG_CONFIG_HOME = value ? std::filesystem::path{ value } : *homePath / ".config"; std::filesystem::path XDGConfigHome = XDG_CONFIG_HOME; - auto privateConfigPath = privatePath / "config"; - if (std::filesystem::exists(privateConfigPath, ec)) { + auto privateConfigPath = checkPrivatePath("config"); + if (!privateConfigPath.empty()) { XDGConfigHome = privateConfigPath; } std::string containerConfigHome = containerHome + "/.config"; @@ -738,8 +751,8 @@ bool ContainerCfgBuilder::buildMountHome() noexcept std::filesystem::path XDG_CACHE_HOME = value ? std::filesystem::path{ value } : *homePath / ".cache"; std::filesystem::path XDGCacheHome = XDG_CACHE_HOME; - auto privateCachePath = privatePath / "cache"; - if (std::filesystem::exists(privateCachePath, ec)) { + auto privateCachePath = checkPrivatePath("cache"); + if (!privateCachePath.empty()) { XDGCacheHome = privateCachePath; } std::string containerCacheHome = containerHome + "/.cache"; @@ -755,8 +768,8 @@ bool ContainerCfgBuilder::buildMountHome() noexcept value = getenv("XDG_STATE_HOME"); std::filesystem::path XDG_STATE_HOME = value ? std::filesystem::path{ value } : *homePath / ".local" / "state"; - auto privateStatePath = privatePath / "state"; - if (std::filesystem::exists(privateStatePath, ec)) { + auto privateStatePath = checkPrivatePath("state"); + if (!privateStatePath.empty()) { XDG_STATE_HOME = privateStatePath; } std::string containerStateHome = containerHome + "/.local/state"; @@ -2037,7 +2050,7 @@ bool ContainerCfgBuilder::build() noexcept return false; } - if (!buildMountHome() || !buildTmp() || !buildPrivateDir() || !buildPrivateMapped()) { + if (!buildTmp() || !buildPrivateDir() || !buildMountHome() || !buildPrivateMapped()) { return false; } From a196beae6cf09191ade486328f1b6fb07504d394 Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 17 Jul 2025 19:29:50 +0800 Subject: [PATCH 102/366] feat: add commit size calculation for pull progress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added new fields needed_archived, needed_unpacked, and needed_objects to ostreeUserData struct 2. Implemented getCommitSize method to fetch commit metadata and calculate download requirements 3. Modified progress_changed to use needed_objects for more accurate progress reporting 4. Integrated size calculation into pull operation to improve progress tracking 5. Added error handling for cases where size calculation fails The changes improve download progress reporting by: - Getting actual commit sizes from server before download begins - Calculating exact number of objects needed for download - Providing more accurate progress percentage during download - Maintaining backward compatibility when size info isn't available feat: 添加提交大小计算以改进拉取进度显示 1. 在ostreeUserData结构体中新增needed_archived、needed_unpacked和 needed_objects字段 2. 实现getCommitSize方法获取提交元数据并计算下载需求 3. 修改progress_changed函数使用needed_objects实现更精确的进度报告 4. 将大小计算集成到pull操作中以改进进度跟踪 5. 添加了大小计算失败时的错误处理 这些改进通过以下方式提升了下载进度报告的准确性: - 在下载开始前从服务器获取实际提交大小 - 计算需要下载的精确对象数量 - 在下载过程中提供更准确的进度百分比 - 当大小信息不可用时保持向后兼容 --- .../src/linglong/repo/ostree_repo.cpp | 102 +++++++++++++++++- libs/linglong/src/linglong/repo/ostree_repo.h | 2 +- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index b353bb054..054b5cd93 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -89,6 +89,9 @@ struct ostreeUserData guint64 total_delta_part_usize{ 0 }; char *ostree_status{ nullptr }; service::PackageTask *taskContext{ nullptr }; + guint64 needed_archived{ 0 }; + guint64 needed_unpacked{ 0 }; + guint64 needed_objects{ 0 }; std::string status{ "Beginning to pull data" }; long double progress{ 0 }; long double last_total{ 0 }; @@ -229,7 +232,8 @@ void progress_changed(OstreeAsyncProgress *progress, gpointer user_data) data->status = "Downloading files"; } } - Q_EMIT data->taskContext->PartChanged(data->fetched, data->requested); + auto requested = data->needed_objects ? data->needed_objects : data->requested; + Q_EMIT data->taskContext->PartChanged(data->fetched, requested); new_progress = total > 0 ? 5 + ((total_transferred / total) * 92) : 97; new_progress += (data->outstanding_writes > 0 ? (3.0 / data->outstanding_writes) : 3.0); } @@ -1266,6 +1270,91 @@ utils::error::Result OSTreeRepo::prune() return LINGLONG_OK; } +// 在pull之前获取commit size,用于计算进度,需要服务器支持ostree.sizes +utils::error::Result> +OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refString) noexcept +{ + LINGLONG_TRACE("get commit size " + QString::fromStdString(refString)); +#if OSTREE_CHECK_VERSION(2020, 1) + g_autoptr(GError) gErr = nullptr; + // 获取commit的metadata + std::array refs{ refString.c_str(), nullptr }; + std::string userAgent = "linglong/" LINGLONG_VERSION; + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, + "{s@v}", + "refs", + g_variant_new_variant(g_variant_new_strv(refs.data(), -1))); + g_variant_builder_add(&builder, + "{s@v}", + "append-user-agent", + g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); + // 设置flags只获取commit的metadata + g_variant_builder_add( + &builder, + "{s@v}", + "flags", + g_variant_new_variant(g_variant_new_int32(OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY))); + g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); + auto status = ostree_repo_pull_with_options(this->ostreeRepo.get(), + remote.c_str(), + pull_options, + nullptr, + nullptr, + &gErr); + if (status == FALSE) { + return LINGLONG_ERR("ostree_repo_pull", gErr); + } + // 使用refString获取commit的sha256 + g_autofree char *resolved_rev = NULL; + if (!ostree_repo_resolve_rev(this->ostreeRepo.get(), refs[0], FALSE, &resolved_rev, &gErr)) { + return LINGLONG_ERR("ostree_repo_resolve_rev", gErr); + } + // 使用sha256获取commit id + g_autoptr(GVariant) commit = NULL; + if (!ostree_repo_load_variant(this->ostreeRepo.get(), + OSTREE_OBJECT_TYPE_COMMIT, + resolved_rev, + &commit, + &gErr)) { + return LINGLONG_ERR("ostree_repo_load_variant", gErr); + } + g_autoptr(GPtrArray) sizes = NULL; + // 获取commit中的所有对象大小 + if (!ostree_commit_get_object_sizes(commit, &sizes, &gErr)) + return LINGLONG_ERR("ostree_commit_get_object_sizes", gErr); + // 计算需要下载的文件大小 + guint64 needed_archived = 0; + // 计算需要解压的文件大小 + guint64 needed_unpacked = 0; + // 计算需要下载的文件数量 + guint64 needed_objects = 0; + // 遍历commit中的所有对象,如果对象不存在,则需要下载 + for (guint i = 0; i < sizes->len; i++) { + OstreeCommitSizesEntry *entry = (OstreeCommitSizesEntry *)sizes->pdata[i]; + gboolean exists; + if (!ostree_repo_has_object(this->ostreeRepo.get(), + entry->objtype, + entry->checksum, + &exists, + NULL, + &gErr)) + return LINGLONG_ERR("ostree_repo_has_object", gErr); + + // Object not in local repo, so we need to download it + if (!exists) { + needed_archived += entry->archived; + needed_unpacked += entry->unpacked; + needed_objects++; + } + } + return std::vector{ needed_archived, needed_unpacked, needed_objects }; +#else + return LINGLONG_ERR("ostree_repo_pull_with_options is not supported"); +#endif +} + void OSTreeRepo::pull(service::PackageTask &taskContext, const package::Reference &reference, const std::string &module, @@ -1285,6 +1374,16 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, std::array refs{ refString.c_str(), nullptr }; ostreeUserData data{ .taskContext = &taskContext }; + + auto sizes = this->getCommitSize(pullRepo.alias.value_or(pullRepo.name), refString); + if (!sizes.has_value()) { + qWarning() << "get commit size error: " << sizes.error().message(); + } else if(sizes->size() >= 3) { + data.needed_archived = sizes->at(0); + data.needed_unpacked = sizes->at(1); + data.needed_objects = sizes->at(2); + } + g_autoptr(OstreeAsyncProgress) progress = ostree_async_progress_new_and_connect(progress_changed, (void *)&data); Q_ASSERT(progress != nullptr); @@ -1306,7 +1405,6 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, "{s@v}", "disable-static-deltas", g_variant_new_variant(g_variant_new_boolean(true))); - g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); // 这里不能使用g_main_context_push_thread_default,因为会阻塞Qt的事件循环 diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index ad9569531..d9636aaba 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -82,7 +82,7 @@ class OSTreeRepo : public QObject const std::string &url, const package::Reference &reference, const std::string &module = "binary") const noexcept; - + utils::error::Result> getCommitSize(const std::string &remote, const std::string &refString) noexcept; void pull(service::PackageTask &taskContext, const package::Reference &reference, const std::string &module = "binary", From 4d8d4c7640c268cdf12d904f2576ec47c00025b4 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 02:50:28 +0000 Subject: [PATCH 103/366] style: format code with ClangFormat and Prettier This commit fixes the style issues introduced in a196bea according to the output from ClangFormat and Prettier. Details: None --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 2 +- libs/linglong/src/linglong/repo/ostree_repo.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 054b5cd93..62d74ff82 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1378,7 +1378,7 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, auto sizes = this->getCommitSize(pullRepo.alias.value_or(pullRepo.name), refString); if (!sizes.has_value()) { qWarning() << "get commit size error: " << sizes.error().message(); - } else if(sizes->size() >= 3) { + } else if (sizes->size() >= 3) { data.needed_archived = sizes->at(0); data.needed_unpacked = sizes->at(1); data.needed_objects = sizes->at(2); diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index d9636aaba..c755cf092 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -82,7 +82,8 @@ class OSTreeRepo : public QObject const std::string &url, const package::Reference &reference, const std::string &module = "binary") const noexcept; - utils::error::Result> getCommitSize(const std::string &remote, const std::string &refString) noexcept; + utils::error::Result> getCommitSize(const std::string &remote, + const std::string &refString) noexcept; void pull(service::PackageTask &taskContext, const package::Reference &reference, const std::string &module = "binary", From 941b502118a1393ac6a07cc522ac26c8b3786f63 Mon Sep 17 00:00:00 2001 From: dengbo Date: Fri, 18 Jul 2025 14:22:40 +0800 Subject: [PATCH 104/366] chore: Configures DeepSource analysis and formatting - Adds global exclusion patterns to ignore specific directories and files. - Enables and configures the C++, Shell, Secrets, and Test Coverage analyzers. - Configures the clang-format and prettier transformers for code formatting, including specifying include and exclude patterns. --- .deepsource.toml | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/.deepsource.toml b/.deepsource.toml index 0097ef53b..503642fd7 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -4,29 +4,73 @@ version = 1 +# 全局排除配置 +exclude_patterns = [ + "external/**", + "build/**", + "obj-*/**", + ".cache/**", + ".obs/**", + ".tx/**", + "**/*.generated.*", + "**/CMakeCache.txt", + "**/compile_commands.json", + "debian/patches/**", + "po/*.po", + "po/*.pot", + "tools/openapi-c-libcurl-client/**", +] + +# C++ 分析器配置 [[analyzers]] name = "cxx" enabled = true +[analyzers.meta] +misra_compliance = true +cyclomatic_complexity_threshold = "medium" + +# Shell 脚本分析器配置 [[analyzers]] name = "shell" enabled = true +[analyzers.meta] +# 只保留官方支持的选项 +dialect = "bash" + +# 密钥检测分析器配置 [[analyzers]] name = "secrets" enabled = true +# secrets 分析器不支持任何 meta 配置 +# 测试覆盖率分析器配置 [[analyzers]] name = "test-coverage" -enabled = false +enabled = true +# 代码格式化器配置 [[transformers]] name = "clang-format" enabled = true +[transformers.meta] +exclude_patterns = ["external/**", "build/**", "obj-*/**", "**/*.generated.*"] + [[transformers]] name = "prettier" enabled = true [transformers.meta] include_patterns = ["**/*.md", "**/*.json", "**/*.yaml", "**/*.yml"] +exclude_patterns = [ + "external/**", + "build/**", + "obj-*/**", + ".cache/**", + "po/**", + "**/*.generated.*", + "package-lock.json", + "yarn.lock", +] From f4277e2b74a086eab421b82f8e458afb826ca169 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 06:53:21 +0000 Subject: [PATCH 105/366] style: format code with ClangFormat and Prettier This commit fixes the style issues introduced in 941b502 according to the output from ClangFormat and Prettier. Details: None --- README.zh_CN.md | 23 +- apps/ll-builder/src/main.cpp | 6 +- apps/ll-cli/src/main.cpp | 6 +- apps/uab/README.md | 2 +- docs/mirrors.md | 9 +- docs/pages/en/guide/debug/faq.md | 21 +- docs/pages/en/guide/debug/ll-pica-faq.md | 4 +- .../ll-appimage-convert/convert-appimage.md | 2 + docs/pages/en/guide/ll-builder/build.md | 3 +- docs/pages/en/guide/ll-builder/export.md | 20 +- .../guide/ll-builder/linyaps_package_spec.md | 98 +++-- docs/pages/en/guide/ll-builder/manifests.md | 124 +++--- docs/pages/en/guide/ll-cli/exec.md | 1 + docs/pages/en/guide/ll-cli/install.md | 4 + docs/pages/en/guide/ll-cli/list.md | 1 + docs/pages/en/guide/ll-cli/update.md | 2 - docs/pages/en/guide/ll-pica/adep.md | 2 +- docs/pages/en/guide/ll-pica/init.md | 4 +- docs/pages/en/guide/ll-pica/manifests.md | 10 +- docs/pages/en/guide/start/how_to_use.md | 2 +- docs/pages/en/guide/start/whatis.md | 56 +-- docs/pages/en/index.md | 4 +- docs/pages/guide/debug/debug.md | 6 +- docs/pages/guide/debug/faq.md | 23 +- docs/pages/guide/debug/ll-builder-faq.md | 18 +- docs/pages/guide/debug/ll-pica-faq.md | 4 +- docs/pages/guide/lessons/basic-notes.md | 96 ++-- docs/pages/guide/lessons/build-git-patch.md | 19 +- docs/pages/guide/lessons/build-in-env.md | 28 +- docs/pages/guide/lessons/build-offline-src.md | 5 +- .../guide/lessons/test-with-toolchains.md | 36 +- docs/pages/guide/ll-builder/export.md | 18 +- .../guide/ll-builder/linyaps_package_spec.md | 40 +- docs/pages/guide/ll-builder/manifests.md | 127 +++--- docs/pages/guide/ll-cli/exec.md | 1 - docs/pages/guide/ll-pica/convert.md | 2 +- docs/pages/guide/ll-pica/manifests.md | 2 +- docs/pages/guide/start/install.md | 12 +- docs/pages/guide/start/whatis.md | 50 +-- docs/ref.md | 4 +- docs/rootfs.md | 2 +- docs/test/unit-testing.md | 6 +- docs/uab-build.md | 2 +- .../src/linglong/package/layer_packager.cpp | 13 +- .../src/linglong/repo/config_test.cpp | 4 +- libs/ocppi/include/ocppi/runtime/Signal.hpp | 3 +- linglong.yaml | 23 +- misc/lib/linglong/container/README.md | 11 +- tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp | 411 ++++++++++-------- 49 files changed, 774 insertions(+), 596 deletions(-) diff --git a/README.zh_CN.md b/README.zh_CN.md index c827e5fa3..a8d31a266 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -1,4 +1,5 @@ + # 如意玲珑图标如意玲珑:更先进的 Linux 跨发行版软件包管理工具集 ## :package: 介绍 @@ -21,7 +22,7 @@ ### :sparkles: 亮点 - **独创的非全量运行时(Runtime)设计**:基于标准化沙箱 Runtime,应用一次构建即可覆盖所有 Linux 发行版。Runtime 多版本共存且文件共享减少冗余,启动时通过动态库共享复用已加载资源,**速度提升显著,避免依赖冲突**。 -- **非特权沙箱与双层隔离**:默认无 root 权限运行,通过内核 Namespace 隔离(进程/文件系统/网络等)构建**安全沙箱**。通过 OSTree 仓库提供原子化增量更新与版本回滚,相比全量沙箱方案,**资源占用更低**。 +- **非特权沙箱与双层隔离**:默认无 root 权限运行,通过内核 Namespace 隔离(进程/文件系统/网络等)构建**安全沙箱**。通过 OSTree 仓库提供原子化增量更新与版本回滚,相比全量沙箱方案,**资源占用更低**。 ### :flags: 进展 @@ -122,16 +123,16 @@ ll-cli run cn.org.linyaps.demo 由于在运行时和沙箱上的优化,玲珑有着比较显著的启动时间优势: | 测试次数 | linyaps 间隔帧数 | linyaps 启动耗时(ms) | Flatpak 间隔帧数 | Flatpak 启动耗时(ms) | AppImage 间隔帧数 | AppImage 启动耗时(ms) | Snap 间隔帧数 | Snap 启动耗时(ms) | -| -------- | ----------------- | ----------------------- | ---------------- | ---------------------- | ----------------- | ----------------------- | ------------- | ------------------- | -| 1 | 9 | 149.4 | 14 | 232.4 | 16 | 265.6 | 42 | 697.2 | -| 2 | 9 | 149.4 | 13 | 215.8 | 17 | 282.2 | 41 | 680.6 | -| 3 | 8 | 132.8 | 9 | 149.4 | 15 | 249 | 40 | 664 | -| 4 | 9 | 149.4 | 13 | 215.8 | 15 | 249 | 41 | 680.6 | -| 5 | 8 | 132.8 | 14 | 232.4 | 16 | 265.6 | 42 | 697.2 | -| 6 | 8 | 132.8 | 13 | 215.8 | 15 | 249 | 39 | 664 | -| 7 | 9 | 149.4 | 12 | 199.2 | 15 | 249 | 39 | 647.4 | -| 8 | 8 | 132.8 | 14 | 232.4 | 16 | 265.6 | 40 | 680.6 | -| 平均 | 8.5 | 141.1 | 12.8 | 213.7 | 15.6 | 261.6 | 40.5 | 676.2 | +| -------- | ---------------- | ---------------------- | ---------------- | ---------------------- | ----------------- | ----------------------- | ------------- | ------------------- | +| 1 | 9 | 149.4 | 14 | 232.4 | 16 | 265.6 | 42 | 697.2 | +| 2 | 9 | 149.4 | 13 | 215.8 | 17 | 282.2 | 41 | 680.6 | +| 3 | 8 | 132.8 | 9 | 149.4 | 15 | 249 | 40 | 664 | +| 4 | 9 | 149.4 | 13 | 215.8 | 15 | 249 | 41 | 680.6 | +| 5 | 8 | 132.8 | 14 | 232.4 | 16 | 265.6 | 42 | 697.2 | +| 6 | 8 | 132.8 | 13 | 215.8 | 15 | 249 | 39 | 664 | +| 7 | 9 | 149.4 | 12 | 199.2 | 15 | 249 | 39 | 647.4 | +| 8 | 8 | 132.8 | 14 | 232.4 | 16 | 265.6 | 40 | 680.6 | +| 平均 | 8.5 | 141.1 | 12.8 | 213.7 | 15.6 | 261.6 | 40.5 | 676.2 | ## :incoming_envelope: 获取帮助 diff --git a/apps/ll-builder/src/main.cpp b/apps/ll-builder/src/main.cpp index ce9997957..e3f3ecd83 100644 --- a/apps/ll-builder/src/main.cpp +++ b/apps/ll-builder/src/main.cpp @@ -995,7 +995,8 @@ You can report bugs to the linyaps team under this project: https://github.com/O auto buildRepoEnableMirror = buildRepo->add_subcommand("enable-mirror", _("Enable mirror for the repo")); buildRepoEnableMirror->usage(_("Usage: ll-builder repo enable-mirror [OPTIONS] ALIAS")); - buildRepoEnableMirror->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) + buildRepoEnableMirror + ->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) ->required() ->check(validatorString); @@ -1003,7 +1004,8 @@ You can report bugs to the linyaps team under this project: https://github.com/O auto buildRepoDisableMirror = buildRepo->add_subcommand("disable-mirror", _("Disable mirror for the repo")); buildRepoDisableMirror->usage(_("Usage: ll-builder repo disable-mirror [OPTIONS] ALIAS")); - buildRepoDisableMirror->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) + buildRepoDisableMirror + ->add_option("ALIAS", repoCmdOpts.repoOptions.repoAlias, _("Alias of the repo name")) ->required() ->check(validatorString); diff --git a/apps/ll-cli/src/main.cpp b/apps/ll-cli/src/main.cpp index 3b449a973..0dabc922d 100644 --- a/apps/ll-cli/src/main.cpp +++ b/apps/ll-cli/src/main.cpp @@ -513,14 +513,16 @@ ll-cli list --upgradable auto *repoEnableMirror = cliRepo->add_subcommand("enable-mirror", _("Enable mirror for the repo")); repoEnableMirror->usage(_("Usage: ll-cli repo enable-mirror [OPTIONS] ALIAS")); - repoEnableMirror->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) + repoEnableMirror + ->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) ->required() ->check(validatorString); // add repo sub command disable mirror auto *repoDisableMirror = cliRepo->add_subcommand("disable-mirror", _("Disable mirror for the repo")); repoDisableMirror->usage(_("Usage: ll-cli repo disable-mirror [OPTIONS] ALIAS")); - repoDisableMirror->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) + repoDisableMirror + ->add_option("ALIAS", options.repoOptions.repoAlias, _("Alias of the repo name")) ->required() ->check(validatorString); diff --git a/apps/uab/README.md b/apps/uab/README.md index 690e5c589..095d86e14 100644 --- a/apps/uab/README.md +++ b/apps/uab/README.md @@ -1,6 +1,6 @@ # uab-header -**uab-header** is a template binary which is used by ll-builder to build uab *(Universal Application Bundle)*. +**uab-header** is a template binary which is used by ll-builder to build uab _(Universal Application Bundle)_. Due to one of the goals of Uab is to depends as few runtime dependencies as possible, uab-header will **statically link all dependent libraries** at compile time. It is important to note that when some of the system's base libraries are upgraded, it may cause uab to fail to run properly diff --git a/docs/mirrors.md b/docs/mirrors.md index 24c9064f9..e3b37d6f7 100644 --- a/docs/mirrors.md +++ b/docs/mirrors.md @@ -17,7 +17,6 @@ http2=false /api/v2/mirrors/$repo_name 是玲珑服务器的一个API接口,通过客户端IP获取客户端所在国家,从配置文件获取对应国家的镜像列表,然后返回给ostree,这样就实现了根据用户所在国家自动分流仓库文件下载的功能更。 - ## 镜像站配置 玲珑的镜像站只提供仓库静态文件的https访问即可,玲珑仓库支持rsync和ostree两种同步协议。 @@ -45,8 +44,8 @@ echo sync $url to $dir sleep 3 ostree init --repo=$dir --mode archive ostree --repo=$dir remote add --if-not-exists --no-sign-verify remote $url -for ref in $(ostree --repo=$dir remote refs remote); do - echo pull $ref; +for ref in $(ostree --repo=$dir remote refs remote); do + echo pull $ref; ostree --repo=$dir pull --mirror $ref; done ``` @@ -54,9 +53,11 @@ done ## ostree pull 步骤 ### 判断镜像是否可用 + 在pull时,ostree 先从contenturl获取镜像列表,然后从每个url获取/config文件,如果获取不到/config文件,则认为该mirror不可用,如果获取到/config文件,则认为该mirror可用。如果没有可用mirror,pull失败。 ### 获取summary文件 + ostree会从url获取summary文件,如果获取不到summary文件,或者summary文件不存在ref,pull失败。 ### delta-indexes文件获取 @@ -65,4 +66,4 @@ ostree会在每个可用的mirror中获取delta-indexes,如果mirror服务器 ### files文件获取 -ostree会按顺序从可用的mirror中获取files,如果mirror服务器返回403, 404, 410,则认为错误不可恢复,pull失败,如果mirror服务器返回其他错误码,则使用下一个mirror获取files。如果所有mirror都无法获取files,则pull失败。 \ No newline at end of file +ostree会按顺序从可用的mirror中获取files,如果mirror服务器返回403, 404, 410,则认为错误不可恢复,pull失败,如果mirror服务器返回其他错误码,则使用下一个mirror获取files。如果所有mirror都无法获取files,则pull失败。 diff --git a/docs/pages/en/guide/debug/faq.md b/docs/pages/en/guide/debug/faq.md index 17330a372..a3acc4770 100644 --- a/docs/pages/en/guide/debug/faq.md +++ b/docs/pages/en/guide/debug/faq.md @@ -9,64 +9,83 @@ SPDX-License-Identifier: LGPL-3.0-or-later 1. When the application runs to read the application installation resource file under `/usr/share`, why does the reading fail? linyaps applications run in a container, and the application data will be mounted to `/opt/apps/`/. Only system data will exist in the `/usr/share` directory, and there will be no application-related data. Therefore, reading directly from `/usr/share` will fail. Suggested processing: Use the `XDG_DATA_DIRS` environment variable to read resources, and `/opt/apps//files/share` will exist in this environment variable search path. + 2. The font library file cannot be found when the application is running. Why can the corresponding font library be read when the `deb` package is installed? When the `deb` package is installed, it will depend on the corresponding font library file. The linyaps package format adopts a self-sufficient packaging format. Except for the basic system library, `Qt` library and `DTK` library files provided in `runtime`, do not need to be provided by yourself, other dependent data files need to be provided by yourself. It is recommended to put the corresponding data file under `files/share`, and use the environment variable `XDG_DATA_DIRS` to read the path. + 3. What is in the linyaps application `runtime`? Can you add some library files to it? At present, the `runtime` that linyaps application depends on provides the `Qt` library and the `DTK` library. Because `runtime` has a strict size limit, adding additional library files to `runtime` is currently not allowed. + 4. The application runs in the container. Can a configuration file be created in any path of the container during the running process? You can create configuration files under `XDG_CONFIG_HOME`. + 5. Where is app data saved? Where can I find it outside the container? Because linyaps applications follow the principle of non-interference, the `XDG_DATA_HOME`, `XDG_CONFIG_HOME`, `XDG_CACHE_HOME` environment variables are defined in the corresponding path of the host machine, `~/.linglong/`/. So the user application data will be saved under this path. When writing data while the application is running, it should also be able to read the corresponding environment variable to write the data. Prohibit reading and writing configurations of other applications. + 6. The application provides the `dbus service` file, where do I place it? What does the `Exec` field write? When the application provides the `dbus service` file, it needs to be placed in the `entries/dbus-1/services` directory. If `Exec` executes the binary in the linyaps package, use the `--exec` option parameter to execute the corresponding binary. + 7. After the app is installed, the launcher cannot find it? TryExec=xxx, if xxx does not exist in the $PATH, the application is considered non-existent and will not be displayed. + 8. Why is the Icon displayed as a small black dot? The desktop file has an 'Icon' field written, but the Icon field name is incorrect or an absolute path is being used."。 + 9. Why is the Icon field as a gear? The desktop file does not provide Icon field. + 10. Where are the icons stored? - svg → $PREFIX/share/icons/hicolor/scalable/apps/ + svg → $PREFIX/share/icons/hicolor/scalable/apps/ Other formats are stored according to resolution, such as 16x16. png/xpm → $PREFIX/share/icons/hicolor/16X16/apps/ + 11. Why do `xdg-open` and `xdg-email` that come with the application fail? linyaps specially handles `xdg-open` and `xdg-email` in `runtime`, so the application is forbidden to execute the executable file or script of `xdg-open` and `xdg-email` that it carries. + 12. Why doesn't the system environment variable used by the application take effect? When using environment variables, you need to confirm whether there are corresponding environment variables in the container. If not, you need to contact the linyaps team for processing. + 13. The library files required for the application to run were not found. How can I provide them? The resource files that the application needs to use and the library files both need to be provided by the application itself. The library files are placed in the `$PREFIX/lib` path. + 14. Why has the `Qt WebEngine` rendering process crashed when the application is running? Due to the system upgrade of `glibc`, the application fails to use the built-in browser, and the application needs to be re-adapted. A temporary solution is to set the environment variable: `export QTWEBENGINE_DISABLE_SANDBOX=1`. + 15. When the application is running, the `libqxcb.so` library cannot be found or the `qtwebengine` error is reported. What can I do? When a `qt.conf` file exists, you need to configure the correct path in the file or use the `QTWEBENGINEPROCESS_PATH`, `QTWEBENGINE_RESOURCES_PATH`, `QT_QPA_PLATFORM_PLUGIN_PATH`, and `QT_PLUGIN_PATH` environment variables to configure the search path. + 16. Can the application carry the database file by itself and write data to the database during operation? The file system in the container is a read-only file system and does not allow data to be written to application resource files. + 17. Why does the execution of binary with `suid` and `guid` permissions fail? In order to ensure system security, linyaps container prohibits the execution of such permission binaries in the container. + 18. Can the input method of uab offline package format not be used under Debian and Ubuntu? It is recommended to install the `fictx` input method to experience it. + 19. How can I know which packages are installed in a container environment? Enter the container environment using the command `ll-builder run --exec bash`. To view the pre-installed packages, utilize the command `cat /var/lib/dpkg/status | grep "^Package: "`. Additionally, for libraries compiled from source code, you can inspect them using `cat /runtime/packages.list`. + 20. Why is the application tray not displayed after the application is launched? This issue might be caused by applications registering to the system tray using the same service name. According to the KDE/freedesktop StatusNotifierItem specification, applications register with a service name in the format of org.kde.StatusNotifierItem-``-``. In the case of the linyaps application, the PID during runtime is 19. You can check whether there's a registered service using the following command: `dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.NameHasOwner string:org.kde.StatusNotifierItem-19-1` If the reply contains boolean true, it indicates that the service has been registered. diff --git a/docs/pages/en/guide/debug/ll-pica-faq.md b/docs/pages/en/guide/debug/ll-pica-faq.md index d04079285..3509dab5b 100644 --- a/docs/pages/en/guide/debug/ll-pica-faq.md +++ b/docs/pages/en/guide/debug/ll-pica-faq.md @@ -3,16 +3,18 @@ 1. Where is the default configuration located for the `linglong.yaml` file generated by `ll-pica`? The configuration file for `ll-pica` is located at `~/.pica/config.json`. + 2. Does ll-pica fail to convert software such as Wine, Android apps, input methods, or security applications? linyaps applications currently do not support this type of application, and consequently, ll-pica cannot convert them either. + 3. Why is there no sound from software that requires audio? Prompt "libpulsecommon-12.2.so not found" can be addressed by adding a line in the `build` section of the linglong.yaml file: `mv $PREFIX/lib/$TRIPLET/pulseaudio/* $PREFIX/lib/$TRIPLET`. + 4. Why is the `command` field empty in the generated `linglong.yaml` file? ll-pica retrieves the 'Exec' field from the desktop file within the deb package. If the command is empty, please verify if the desktop file path within the deb package exists in the following locations. - - /opt/apps/$appid/entries/applications - /usr/share/applications diff --git a/docs/pages/en/guide/ll-appimage-convert/convert-appimage.md b/docs/pages/en/guide/ll-appimage-convert/convert-appimage.md index ffed46ea1..cf5159579 100644 --- a/docs/pages/en/guide/ll-appimage-convert/convert-appimage.md +++ b/docs/pages/en/guide/ll-appimage-convert/convert-appimage.md @@ -62,6 +62,7 @@ ll-appimage-convert convert -f ~/Downloads/BrainWaves-0.15.1.AppImage --name "io ``` The converted directory structure is as follows: + ```text ├── io.github.brainwaves_x86_64_0.15.1.0_main.uab ├── linglong @@ -75,6 +76,7 @@ ll-appimage-convert convert -f ~/Downloads/BrainWaves-0.15.1.AppImage --name "io ``` The converted directory structure is as follows: + ```text ├── io.github.brainwaves_0.15.1.0_x86_64_binary.layer ├── io.github.brainwaves_0.15.1.0_x86_64_develop.layer diff --git a/docs/pages/en/guide/ll-builder/build.md b/docs/pages/en/guide/ll-builder/build.md index 280b3cb3d..e72ebc7f3 100644 --- a/docs/pages/en/guide/ll-builder/build.md +++ b/docs/pages/en/guide/ll-builder/build.md @@ -38,7 +38,8 @@ Options: --skip-strip-symbols Skip strip debug symbols ``` -The `ll-builder build` command can be run in two ways: +The `ll-builder build` command can be run in two ways: + 1. the root directory of the project, where the `linglong.yaml` file is located. 2. specify the linglong.yaml file path with the `--file` parameter. diff --git a/docs/pages/en/guide/ll-builder/export.md b/docs/pages/en/guide/ll-builder/export.md index dec84ef65..c220a8c7d 100644 --- a/docs/pages/en/guide/ll-builder/export.md +++ b/docs/pages/en/guide/ll-builder/export.md @@ -15,19 +15,20 @@ ll-builder export [OPTIONS] ``` To view all available options and their detailed descriptions, run: + ```bash ll-builder export --help ``` ## Main Options -* `-f, --file FILE`: Specify the path to the `linglong.yaml` configuration file (default: `./linglong.yaml`). The directory containing `linglong.yaml` serves as the project's working directory. -* `-o, --output FILE`: Specify the output file path. For UAB, this is typically the full path or filename of the `.uab` file. For layers, this is the prefix for the output filenames. -* `-z, --compressor X`: Specify the compression algorithm. Supports `lz4` (UAB default), `lzma` (layer default), `zstd`. -* `--icon FILE`: Specify an icon for the exported UAB file (UAB mode only, mutually exclusive with `--layer`). -* `--loader FILE`: Specify a custom loader for the exported UAB file (UAB mode only, mutually exclusive with `--layer`). -* `--layer`: **(Deprecated)** Export as layer file format instead of UAB (mutually exclusive with `--icon`, `--loader`). -* `--no-develop`: When exporting layer files, do not include the `develop` module. +- `-f, --file FILE`: Specify the path to the `linglong.yaml` configuration file (default: `./linglong.yaml`). The directory containing `linglong.yaml` serves as the project's working directory. +- `-o, --output FILE`: Specify the output file path. For UAB, this is typically the full path or filename of the `.uab` file. For layers, this is the prefix for the output filenames. +- `-z, --compressor X`: Specify the compression algorithm. Supports `lz4` (UAB default), `lzma` (layer default), `zstd`. +- `--icon FILE`: Specify an icon for the exported UAB file (UAB mode only, mutually exclusive with `--layer`). +- `--loader FILE`: Specify a custom loader for the exported UAB file (UAB mode only, mutually exclusive with `--layer`). +- `--layer`: **(Deprecated)** Export as layer file format instead of UAB (mutually exclusive with `--icon`, `--loader`). +- `--no-develop`: When exporting layer files, do not include the `develop` module. ## Exporting UAB Files (Recommended) @@ -64,8 +65,9 @@ ll-builder export --layer -o my-app ``` Exporting layer files generates the following files: -* `*_binary.layer`: Contains the basic files required for the application to run. -* `*_develop.layer`: (Optional) Contains files for development and debugging. This file is not generated if the `--no-develop` option is used. + +- `*_binary.layer`: Contains the basic files required for the application to run. +- `*_develop.layer`: (Optional) Contains files for development and debugging. This file is not generated if the `--no-develop` option is used. ## Advanced Notes diff --git a/docs/pages/en/guide/ll-builder/linyaps_package_spec.md b/docs/pages/en/guide/ll-builder/linyaps_package_spec.md index 760dd0de5..e2f4151d9 100644 --- a/docs/pages/en/guide/ll-builder/linyaps_package_spec.md +++ b/docs/pages/en/guide/ll-builder/linyaps_package_spec.md @@ -4,16 +4,16 @@ The explanations of the keywords **must**, **prohibited**, **necessary**, **shou The correspondence between these keywords and the English words in the original text is shown in the following table: -| Chinese | English | -|------------|-------------| -| **Must** | MUST | -| **Prohibited** | MUST NOT | -| **Necessary** | REQUIRED | -| **Should** | SHALL | -| **Should not** | SHALL NOT | +| Chinese | English | +| --------------- | ----------- | +| **Must** | MUST | +| **Prohibited** | MUST NOT | +| **Necessary** | REQUIRED | +| **Should** | SHALL | +| **Should not** | SHALL NOT | | **Recommended** | RECOMMENDED | -| **Allowed** | MAY | -| **Optional** | OPTIONAL | +| **Allowed** | MAY | +| **Optional** | OPTIONAL | [rfc-2119]: https://datatracker.ietf.org/doc/html/rfc2119 @@ -112,15 +112,16 @@ $(INSTALL_PROGRAM) path/to/my/internal/executable "$(DESTDIR)$(libexecdir)"/exec - Static libraries -```makefile +````makefile install: $(INSTALL) -d "$(DESTDIR)$(libdir)" $(INSTALL_DATA) path/to/my/library.a "$(DESTDIR)$(libdir)"/library.a ``` - pkg-config configuration file ```makefile pc_dir ?= $(libdir)/pkgconfig ifeq ($(findstring $(pc_dir), $(subst :, , $(shell \ $(PKG_CONFIG) --variable=pc_path)), ) $(warning pc_dir="$(pc_dir)" \ is not in the search path of current pkg-config installation) endif .PHONY: install-pkg-config install-pkg-config: $(INSTALL) -d "$(DESTDIR)$(pc_dir)" $(INSTALL_DATA) path/to/your.pc "$(DESTDIR)$(pc_dir)"/your.pc -``` +```` If you are sure that the file is available across architectures, you can use `$(datarootdir)` instead of `$(libdir)`. -- systemd system level unit ```makefile systemd_system_unit_dir ?= $(shell \ $(PKG_CONFIG) --define-variable=prefix=$(prefix) \ systemd --variable=systemd_system_unit_dir) ifeq ($(findstring $(systemd_system_unit_dir), $(subst :, , $(shell \ $(PKG_CONFIG) systemd --variable=systemd_system_unit_path))), ) $(warning systemd_system_unit_dir="$(systemd_system_unit_dir)" \ is not in the system unit search path of current systemd installation) endif .PHONY: install-systemd-system-unit install-systemd-system-unit: $(INSTALL) -d "$(DESTDIR)$(systemd_system_unit_dir)" $(INSTALL_DATA) path/to/your.service "$(DESTDIR)$(systemd_system_unit_dir)"/your.service ``` - systemd user-level unit ```makefile systemd_user_unit_dir ?= $(shell \ $(PKG_CONFIG) --define-variable=prefix=$(prefix) \ systemd --variable=systemd_user_unit_dir) ifeq ($(findstring $(systemd_user_unit_dir), $(subst :, , $(shell \ $(PKG_CONFIG) systemd --variable=systemd_user_unit_path))), ) $(warning systemd_user_unit_dir="$(systemd_user_unit_dir)" \ is not in the user unit search path of current systemd installation) endif .PHONY: install-systemd-user-unit install-systemd-user-unit: $(INSTALL) -d "$(DESTDIR)$(systemd_user_unit_dir)" $(INSTALL_DATA) path/to/your.service "$(DESTDIR)$(systemd_user_unit_dir)"/your.service -``` +- systemd system level unit `makefile systemd_system_unit_dir ?= $(shell \ $(PKG_CONFIG) --define-variable=prefix=$(prefix) \ systemd --variable=systemd_system_unit_dir) ifeq ($(findstring $(systemd_system_unit_dir), $(subst :, , $(shell \ $(PKG_CONFIG) systemd --variable=systemd_system_unit_path))), ) $(warning systemd_system_unit_dir="$(systemd_system_unit_dir)" \ is not in the system unit search path of current systemd installation) endif .PHONY: install-systemd-system-unit install-systemd-system-unit: $(INSTALL) -d "$(DESTDIR)$(systemd_system_unit_dir)" $(INSTALL_DATA) path/to/your.service "$(DESTDIR)$(systemd_system_unit_dir)"/your.service ` - systemd user-level unit ```makefile systemd_user_unit_dir ?= $(shell \ $(PKG_CONFIG) --define-variable=prefix=$(prefix) \ systemd --variable=systemd_user_unit_dir) ifeq ($(findstring $(systemd_user_unit_dir), $(subst :, , $(shell \ $(PKG_CONFIG) systemd --variable=systemd_user_unit_path))), ) $(warning systemd_user_unit_dir="$(systemd_user_unit_dir)" \ is not in the user unit search path of current systemd installation) endif .PHONY: install-systemd-user-unit install-systemd-user-unit: $(INSTALL) -d "$(DESTDIR)$(systemd_user_unit_dir)" $(INSTALL_DATA) path/to/your.service "$(DESTDIR)$(systemd_user_unit_dir)"/your.service + +```` - desktop file @@ -128,7 +129,7 @@ If you are sure that the file is available across architectures, you can use `$( install: $(INSTALL) -d "$(DESTDIR)$(datarootdir)"/applications $(INSTALL_PROGRAM) path/to/your.desktop "$(DESTDIR)$(datarootdir)"/applications/your.desktop -``` +```` - desktop file corresponding icon @@ -140,7 +141,7 @@ At least **need** to install a 48x48 size png to ensure the normal basic functio - If the installed icon is a vector version, it is **recommended** to use svg format -```makefile +````makefile install: $(INSTALL) -d "$(DESTDIR)$(datarootdir)"/icons/hicolor/48x48/apps $(INSTALL_DATA) path/to/your.png "$(DESTDIR)$(datarootdir)"/icons/hicolor/48x48/apps/your.png # Add more size of .png icons here... $(INSTALL) -d "$(DESTDIR)$(datarootdir)"/icons/hicolor/scalable/apps $(INSTALL_DATA) path/to/your.svg "$(DESTDIR)$(datarootdir)"/icons/hicolor/scalable/apps/your.svg ``` #### CMake This section is mainly written with reference to the relevant content in and . @@ -151,7 +152,7 @@ The writing logic is consistent with the relevant content in the Makefile sectio ```cmake include(GNUInstallDirs) -``` +```` - Executable files @@ -183,7 +184,7 @@ To be added - systemd system-level unit -```cmake +````cmake find_package(PkgConfig) if(NOT SYSTEMD_SYSTEM_UNIT_DIR) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.28") @@ -198,13 +199,13 @@ DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/48x48/apps) install(FILES path/to/your.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps) -``` +```` ### Configuration file #### desktop file -It is **not** recommended** to have `-` in the desktop file name. After removing the .desktop suffix, it should comply with the relevant specifications described in the application name section. +It is **not** recommended\*\* to have `-` in the desktop file name. After removing the .desktop suffix, it should comply with the relevant specifications described in the application name section. - **Recommended** Fill in the [`TryExec` field][key-tryexec] to ensure that the desktop file is no longer valid after the application has been uninstalled - **Recommended** Fill in the [`WMClass` field][key-startupwmclass] to ensure that basic desktop environment functions such as the taskbar based on window and application matching can work properly @@ -212,7 +213,6 @@ It is **not** recommended** to have `-` in the desktop file name. After removing - **Not recommended** Use the absolute path when filling in the [`Icon` field][key-icon] [key-tryexec]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-tryexec - [key-startupwmclass]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-startupwmclass [key-exec]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-exec [key-icon]: https://specifications.freedesktop.org/desktop-entry-spec/ @@ -232,10 +232,11 @@ latest/recognized-keys.html#key-icon - **Recommend** that the file name of the service file with BusName is consistent with BusName - **Recommend** that the absolute path is used in the ExecStart field -When using absolute paths in the above configuration files, **hard-coded paths are **not recommended**. The path **should** be consistent with the final installation path. **Recommend** that the template file be written in the project first, and the placeholder is used to represent the absolute path. The final configuration file is generated by replacing the placeholder through the build system. +When using absolute paths in the above configuration files, **hard-coded paths are **not recommended**. The path **should** be consistent with the final installation path. **Recommend\*\* that the template file be written in the project first, and the placeholder is used to represent the absolute path. The final configuration file is generated by replacing the placeholder through the build system. Here, taking the desktop file as an example, several examples of generating the final configuration file under common build systems are given. Assume that the final product `org.deepin.demo.desktop` has the following content: + ```ini [Desktop Entry] Name=demo @@ -255,7 +256,9 @@ Exec=@BINDIR@/demo Type=Application Terminal=false ``` + 2. Write the corresponding makefile rules. + ```makefile DESKTOP_TEMPLATE = org.deepin.demo.desktop.in DESKTOP_FILE = org.deepin.demo.desktop @@ -276,7 +279,9 @@ all: desktop ``` - If using CMake as build system. + 1. Write the desktop template file. + ```desktop [Desktop Entry] Name=demo @@ -284,7 +289,9 @@ Exec=@CMAKE_INSTALL_BINDIR@/demo Type=Application Terminal=false ``` + 2. Write the corresponding cmake rules. + ```cmake set(DESKTOP_FILE "org.deepin.demo.desktop") # Use configure_file to replace placeholders @@ -296,15 +303,16 @@ ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE} install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE} DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) ``` + ### Header files and link libraries Linglong's environment consists of up to three parts. Taking the compilation of `org.deepin.demo` under the `x86_64` architecture as an example, the default search path for header files and library files includes the following parts: -| **Composition** | **Package name** | **Header file** | **Library files** | -| ----------------------------------------------- | ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------ | -| base | org.deepin.base | /usr/include | /usr/lib
/usr/lib/x86_64-linux-gnu | -| runtime (optional) | org.deepin.runtime.dtk | /runtime/include | /runtime/lib
/runtime/lib/x86_64-linux-gnu | -| app | org.deepin.demo | /opt/apps/org.deepin.demo/files/include | /opt/apps/org.deepin.demo/files/lib
/opt/apps/org.deepin.demo/files/lib/x86_64-linux-gnu | +| **Composition** | **Package name** | **Header file** | **Library files** | +| ------------------ | ---------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------- | +| base | org.deepin.base | /usr/include | /usr/lib
/usr/lib/x86_64-linux-gnu | +| runtime (optional) | org.deepin.runtime.dtk | /runtime/include | /runtime/lib
/runtime/lib/x86_64-linux-gnu | +| app | org.deepin.demo | /opt/apps/org.deepin.demo/files/include | /opt/apps/org.deepin.demo/files/lib
/opt/apps/org.deepin.demo/files/lib/x86_64-linux-gnu | Priority is in order from top to bottom. If a header file exists in both `org.deepin.base` and `org.deepin.demo`, the file in `org.deepin.base` will be matched first when used. The same applies to library files. @@ -315,6 +323,7 @@ Common configuration files include `.pc`, `.cmake`, etc. How to use it depends o #### Makefile ##### Use `.pc` file + ```makefile # Common variables, inherit the environment variable CXXFLAGS and append content CXX = g++ @@ -381,7 +390,7 @@ As mentioned in the section `Header files and link libraries`, the Linglong envi Introducing dependencies through source code is a **recommended** practice, which can greatly ensure the stability and maintainability of the build process. The disadvantage is that this may take developers a lot of time to write yaml files, because the dependencies may also have their own dependencies. -*If developers find that the dependencies are complex and repeatedly used by other applications, they should consider integrating the dependencies into a runtime type package. * +_If developers find that the dependencies are complex and repeatedly used by other applications, they should consider integrating the dependencies into a runtime type package. _ When the dependency is compiled in the Linglong environment, its configuration file is usually "reliable". After compilation and installation, developers can use it directly in the project. @@ -418,6 +427,7 @@ This is a "shortcut". If the developer does not consider the subsequent updates 5. Press Ctrl+Shift+P to search and execute the linglong: Gen deb sources command After execution, the yaml file will automatically write the following content: + ```yaml build: # Unzip and import deb, install_dep file is automatically downloaded by the plugin @@ -468,13 +478,13 @@ The total length of the version number after automatically adding to four groups Linglong application **must** select a base as the basic running environment. Available base: | **Base library** | **Package name/version** | -| ----------------------------------------------- | ------------------------------------------------ | -| glibc(2.38) | org.deepin.base/23.1.0.0 | +| ---------------- | ------------------------ | +| glibc(2.38) | org.deepin.base/23.1.0.0 | If you need to use additional frameworks other than the base environment, you should use the appropriate runtime. Available runtime: -| **Framework** | **Package name/version** | -| ----------------------------------------------- | ------------------------------------------------ | +| **Framework** | **Package name/version** | +| ------------------- | ------------------------------- | | QT(5.15) + DTK(5.6) | org.deepin.runtime.dtk/23.1.0.0 | When using base or runtime, it is recommended to fill in the first three digits of the version number, such as '23.1.0', to facilitate subsequent updates. Filling in the full 4-digit version means that base or runtime updates are prohibited. @@ -565,7 +575,8 @@ When the application is running, these files or directories will be mapped to th info.json is the application description file defined by Linglong. This file is automatically generated by the build tool and it **should** not be modified manually. Its content is as follows: ```json { "id": "org.deepin.demo", "arch": [ "x86_64" ], "base": "main:org.deepin.foundation/23.0.0/x86_64", "channel": "main", "command": [ "/opt/apps/org.deepin.demo/files/bin/demo" ], "description": "simple Qt demo.\n", "kind": "app", "module": "runtime", "name": "demo", "runtime": "main:org.deepin.Runtime/23.0.1/x86_64", "size": 118763, "version": "0.0.0.1" } -``` + +```` The following is a description of each field in info.json: @@ -616,7 +627,7 @@ When the application is installed on the host, Linglong Package Manager will lin ```bash $ ls /var/lib/linglong/entries/share/applications/ -l lrwxrwxrwx 1 deepin-linglong deepin-linglong 101 July 30 11:13 org.deepin.demo.desktop -> ../../../layers/main/org.deepin.demo/0.0.0.1/x86_64/runtime/entries/share/applications/org.deep in.demo.desktop -``` +```` ##### applications directory @@ -639,11 +650,12 @@ Name=demo TryExec=/usr/bin/ll-cli Type=Application ``` + An application can have multiple desktop files. **Path correspondence:** -| **Packaging path** | **Installation path** | +| **Packaging path** | **Installation path** | | -------------------------------------------------- | --------------------------------------------------------- | | $PREFIX/share/applications/org.deepin.demo.desktop | $XDG_DATA_DIRS/share/applications/org.deepin.demo.desktop | @@ -669,9 +681,9 @@ An application can be configured with multiple services, and the service name mu **Path correspondence:** -| **Packaging path** | **Installation path** | +| **Packaging path** | **Installation path** | | ---------------------------------------------------- | ----------------------------------------------------------- | -| $PREFIX/share/services/org.deepin.demo.service | $XDG_DATA_DIRS/dbus-1/service/org.deepin.demo.service | +| $PREFIX/share/services/org.deepin.demo.service | $XDG_DATA_DIRS/dbus-1/service/org.deepin.demo.service | | $PREFIX/share/services/org.deepin.demo.hello.service | $XDG_DATA_DIRS/dbus-1/service/org.deepin.demo.hello.service | ##### User-level systemd service @@ -707,12 +719,12 @@ ExecStart = ll-cli run org.deepin.demo -- demo WantedBy=user-session.target ``` -Unlike dbus service, files installed to ```$PREFIX/lib/systemd/user``` will be automatically copied to ```$PREFIX/share/systemd/user```. +Unlike dbus service, files installed to `$PREFIX/lib/systemd/user` will be automatically copied to `$PREFIX/share/systemd/user`. **Path correspondence:** -| **Packaging path** | **Installation path** | -| ------------------------------------------------------------- | -------------------------------------------------------------- | +| **Packaging path** | **Installation path** | +| ------------------------------------------------ | --------------------------------------------------- | | $PREFIX/lib/systemd/user/org.deepin.demo.service | $XDG_DATA_DIRS/systemd/user/org.deepin.demo.service | ##### icons directory @@ -721,11 +733,11 @@ The directory for storing application icons should be consistent with the system **Path correspondence:** -| **Packaging path** | **Installation path** | +| **Packaging path** | **Installation path** | | ------------------------------------------------------------- | -------------------------------------------------------------- | | $PREFIX/share/icons/hicolor/scalable/apps/org.deepin.demo.svg | $XDG_DATA_DIRS/icons/hicolor/scalable/apps/org.deepin.demo.svg | -| $PREFIX/share/icons/hicolor/24x24/apps/org.deepin.demo.png | $XDG_DATA_DIRS/icons/hicolor/24x24/apps/org.deepin.demo.png | -| $PREFIX/share/icons/hicolor/16x16/apps/org.deepin.demo.png | $XDG_DATA_DIRS/icons/hicolor/16x16/apps/org.deepin.demo.png | +| $PREFIX/share/icons/hicolor/24x24/apps/org.deepin.demo.png | $XDG_DATA_DIRS/icons/hicolor/24x24/apps/org.deepin.demo.png | +| $PREFIX/share/icons/hicolor/16x16/apps/org.deepin.demo.png | $XDG_DATA_DIRS/icons/hicolor/16x16/apps/org.deepin.demo.png | ##### mime directory @@ -733,7 +745,7 @@ MIME (Multipurpose Internet Mail Extensions) Multipurpose Internet Mail Extensio **Path correspondence:** -| **Packaging path** | **Installation path** | +| **Packaging path** | **Installation path** | | ----------------------------------------------- | ------------------------------------------------ | | $PREFIX/share/mime/packages/org.deepin.demo.xml | $XDG_DATA_DIRS/mime/packages/org.deepin.demo.xml | diff --git a/docs/pages/en/guide/ll-builder/manifests.md b/docs/pages/en/guide/ll-builder/manifests.md index f98670905..e4bd9c818 100644 --- a/docs/pages/en/guide/ll-builder/manifests.md +++ b/docs/pages/en/guide/ll-builder/manifests.md @@ -27,11 +27,11 @@ SPDX-License-Identifier: LGPL-3.0-or-later The `linglong.yaml` file structure follows specific specifications. First, you need to declare the configuration file version at the top level: ```yaml -version: '1' +version: "1" ``` -| Name | Description | Required | -| ------- | ------------------------------------------ | -------- | +| Name | Description | Required | +| ------- | ---------------------------------------------------------- | -------- | | version | The version of the build configuration file, currently '1' | Yes | Next are the main configuration blocks. Among them, `package`, `base`, and `build` must be defined. @@ -49,18 +49,18 @@ package: description: | calculator for deepin os. architecture: amd64 # Optional - channel: stable # Optional + channel: stable # Optional ``` -| Name | Description | Required | -| -------------- | --------------------------------------------------------------- | -------- | -| id | Unique name of the build artifact (e.g., `org.deepin.calculator`) | Yes | -| name | Name of the build artifact (e.g., `deepin-calculator`) | Yes | -| version | Version of the build artifact, four digits recommended (e.g., `5.7.21.0`) | Yes | -| kind | Type of the build artifact: `app` (Application), `runtime` (Runtime) | Yes | -| description | Detailed description of the build artifact | Yes | -| architecture | Target architecture of the build artifact (e.g., `amd64`, `arm64`) | No | -| channel | Channel of the build artifact (e.g., `stable`, `beta`) | No | +| Name | Description | Required | +| ------------ | ------------------------------------------------------------------------- | -------- | +| id | Unique name of the build artifact (e.g., `org.deepin.calculator`) | Yes | +| name | Name of the build artifact (e.g., `deepin-calculator`) | Yes | +| version | Version of the build artifact, four digits recommended (e.g., `5.7.21.0`) | Yes | +| kind | Type of the build artifact: `app` (Application), `runtime` (Runtime) | Yes | +| description | Detailed description of the build artifact | Yes | +| architecture | Target architecture of the build artifact (e.g., `amd64`, `arm64`) | No | +| channel | Channel of the build artifact (e.g., `stable`, `beta`) | No | ### Command (`command`) @@ -72,8 +72,8 @@ command: # - --some-argument # More arguments can be added ``` -| Name | Description | Required | -| ------- | --------------------------------------------------------------------------- | -------- | +| Name | Description | Required | +| ------- | ----------------------------------------------------------------------------------------------------------------- | -------- | | command | Defines the executable path and its argument list for starting the application. Usually required for `kind: app`. | No | ### Base Environment (`base`) @@ -84,9 +84,9 @@ Specifies the minimum root filesystem required for building and running. This fi base: org.deepin.base/23.1.0 ``` -| Name | Description | Required | -| ------- | ------------------------------------------------ | -------- | -| base | Identifier for the base, format `id/version`. Version number supports three-digit fuzzy matching. | Yes | +| Name | Description | Required | +| ---- | ------------------------------------------------------------------------------------------------- | -------- | +| base | Identifier for the base, format `id/version`. Version number supports three-digit fuzzy matching. | Yes | ### Runtime (`runtime`) @@ -96,9 +96,9 @@ Application runtime dependencies, which are also build dependencies. runtime: org.deepin.runtime.dtk/23.1.0 ``` -| Name | Description | -| ------- | ------------------------------------------------------ | -| id | Unique name of the runtime | +| Name | Description | +| ------- | -------------------------------------------------------- | +| id | Unique name of the runtime | | version | Runtime version, three digits can fuzzy match the fourth | ### Sources (`sources`) @@ -116,12 +116,12 @@ sources: name: deepin-calculator.git # Optional, specifies the directory name after download ``` -| Name | Description | Required (within a single source) | -| ------- | --------------------------------------------------------------------------- | --------------------------------- | -| kind | `git`, indicates download using the git tool. | Yes | -| url | Source repository address | Yes | -| version | Branch or tag of the source repository | No (defaults to the main branch) | -| commit | Hash value of a specific commit, used for precise checkout | No | +| Name | Description | Required (within a single source) | +| ------- | ---------------------------------------------------------------------------------- | --------------------------------- | +| kind | `git`, indicates download using the git tool. | Yes | +| url | Source repository address | Yes | +| version | Branch or tag of the source repository | No (defaults to the main branch) | +| commit | Hash value of a specific commit, used for precise checkout | No | | name | Optional, specifies the subdirectory name under `linglong/sources` after download. | No | #### File Type @@ -134,12 +134,12 @@ sources: name: my-data.dat # Optional, specifies the filename after download ``` -| Name | Description | Required (within a single source) | -| ------ | --------------------------------------------------------------------------- | --------------------------------- | -| kind | `file`, indicates direct file download. | Yes | -| url | File download address | Yes | -| digest | Optional, sha256 hash of the file, used for verification. | No | -| name | Optional, specifies the filename under `linglong/sources` after download. | No | +| Name | Description | Required (within a single source) | +| ------ | ------------------------------------------------------------------------- | --------------------------------- | +| kind | `file`, indicates direct file download. | Yes | +| url | File download address | Yes | +| digest | Optional, sha256 hash of the file, used for verification. | No | +| name | Optional, specifies the filename under `linglong/sources` after download. | No | #### Archive Type @@ -151,12 +151,12 @@ sources: name: deepin-calculator-6.5.4 # Optional, specifies the directory name after extraction ``` -| Name | Description | Required (within a single source) | -| ------ | --------------------------------------------------------------------------- | --------------------------------- | +| Name | Description | Required (within a single source) | +| ------ | ------------------------------------------------------------------------------------------------- | --------------------------------- | | kind | `archive`, downloads and automatically extracts the archive. Supports common compression formats. | Yes | -| url | Archive download address | Yes | -| digest | Optional, sha256 hash of the archive file, used for verification. | No | -| name | Optional, specifies the directory name under `linglong/sources` after extraction. | No | +| url | Archive download address | Yes | +| digest | Optional, sha256 hash of the archive file, used for verification. | No | +| name | Optional, specifies the directory name under `linglong/sources` after extraction. | No | #### DSC Type @@ -168,11 +168,11 @@ sources: name: deepin-calculator-dsc # Optional, specifies the directory name after download and extraction ``` -| Name | Description | Required (within a single source) | -| ------ | --------------------------------------------------------------------------- | --------------------------------- | -| kind | `dsc`, handles Debian source package description files and associated files. | Yes | -| url | `.dsc` file download address | Yes | -| digest | Optional, sha256 hash of the `.dsc` file, used for verification. | No | +| Name | Description | Required (within a single source) | +| ------ | ---------------------------------------------------------------------------------------------- | --------------------------------- | +| kind | `dsc`, handles Debian source package description files and associated files. | Yes | +| url | `.dsc` file download address | Yes | +| digest | Optional, sha256 hash of the `.dsc` file, used for verification. | No | | name | Optional, specifies the directory name under `linglong/sources` after download and extraction. | No | ### Export Rules (`exclude`/`include`) @@ -188,9 +188,9 @@ include: - /usr/share/locale/zh_CN.UTF-8 # Used with exclude to export only specific files under a folder ``` -| Name | Description | -| ------- | ------------------------------------------------------------------------ | -| exclude | Absolute path within the container, can be a file or folder, used for exclusion. | +| Name | Description | +| ------- | ------------------------------------------------------------------------------------------------------------------------------ | +| exclude | Absolute path within the container, can be a file or folder, used for exclusion. | | include | Absolute path within the container, files that must be included in the UAB package (even if the parent directory is excluded). | ### Build Rules (`build`) @@ -206,8 +206,8 @@ build: | make install ``` -| Name | Description | Required | -| ----- | --------------------------------------------------------------------------- | -------- | +| Name | Description | Required | +| ----- | ------------------------------------------------------------------------------------------ | -------- | | build | Shell script executed during the build phase. Runs inside the container build environment. | Yes | ### Build Extensions (`buildext`) @@ -226,12 +226,12 @@ buildext: - libglib2.0-0 ``` -| Name | Description | Required | -| ----------- | ------------------------------------------------------------------------- | -------- | -| buildext | Container block for build extension configurations. | No | -| apt | Extension configuration using the apt package manager. | No | +| Name | Description | Required | +| ------------- | -------------------------------------------------------------------------------------------- | -------- | +| buildext | Container block for build extension configurations. | No | +| apt | Extension configuration using the apt package manager. | No | | build_depends | A list of strings listing packages needed at build time, not included in the final artifact. | No | -| depends | A list of strings listing packages needed at runtime, included in the final artifact. | No | +| depends | A list of strings listing packages needed at runtime, included in the final artifact. | No | ### Modules (`modules`) @@ -253,11 +253,11 @@ modules: - share/my-app/optional-data/ ``` -| Name | Description | Required | -| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| modules | List defining the rules for splitting the application into modules. | No | -| name | Name of the module. Each module requires a unique name. | Yes (within each module item) | -| files | A list of strings listing files or directories belonging to this module. Paths are relative to `${PREFIX}`. | Yes (within each module item) | +| Name | Description | Required | +| ------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------- | +| modules | List defining the rules for splitting the application into modules. | No | +| name | Name of the module. Each module requires a unique name. | Yes (within each module item) | +| files | A list of strings listing files or directories belonging to this module. Paths are relative to `${PREFIX}`. | Yes (within each module item) | **Note:** All files installed under `${PREFIX}` will be assigned to a module. When `modules` is not defined, the build system automatically generates default `binary` and `develop` modules. @@ -265,10 +265,10 @@ modules: Describes variables that can be used during the build process. -| Name | Description | -| ------- | ------------------------------------------------------------------------------------------------------------- | +| Name | Description | +| ------- | ------------------------------------------------------------------------------------------------------------------------------------- | | PREFIX | Environment variable used under the `build` field; provides the installation path during build, e.g., /opt/apps/org.deepin.calculator | -| TRIPLET | Environment variable used under the `build` field; provides a triplet containing architecture information, e.g., x86_64-linux-gnu | +| TRIPLET | Environment variable used under the `build` field; provides a triplet containing architecture information, e.g., x86_64-linux-gnu | ## Complete Example @@ -277,7 +277,7 @@ Describes variables that can be used during the build process. #### Calculator ```yaml -version: '1' +version: "1" package: id: org.deepin.calculator diff --git a/docs/pages/en/guide/ll-cli/exec.md b/docs/pages/en/guide/ll-cli/exec.md index 2fda1a2e8..244979276 100644 --- a/docs/pages/en/guide/ll-cli/exec.md +++ b/docs/pages/en/guide/ll-cli/exec.md @@ -46,6 +46,7 @@ main:org.dde.calendar/5.14.5.0/x86_64 c3b5ce363172 539537 ``` 2. enter the org.dde.calendar container + ```bash ll-cli exec main:org.dde.calendar/5.14.5.0/x86_64 /bin/bash ``` diff --git a/docs/pages/en/guide/ll-cli/install.md b/docs/pages/en/guide/ll-cli/install.md index 927e25d49..f3996f8d5 100644 --- a/docs/pages/en/guide/ll-cli/install.md +++ b/docs/pages/en/guide/ll-cli/install.md @@ -74,18 +74,22 @@ After the application is installed, the installation result will be displayed. The layer or uab files we export using the `ll-builder export` command can be installed using the `ll-cli install` command. `.layer` + ```bash ll-cli install ./com.baidu.baidunetdisk_4.17.7.0_x86_64_runtime.layer ``` `.uab` There are two ways to install uab files + - use `ll-cli install` to install + ```bash ll-cli install com.baidu.baidunetdisk_x86_64_4.17.7.0_main.uab ``` - Execute `uab` on a machine with linyaps environment to install the application. + ```bash ./com.baidu.baidunetdisk_x86_64_4.17.7.0_main.uab ``` diff --git a/docs/pages/en/guide/ll-cli/list.md b/docs/pages/en/guide/ll-cli/list.md index 248638c86..a9e2167a4 100644 --- a/docs/pages/en/guide/ll-cli/list.md +++ b/docs/pages/en/guide/ll-cli/list.md @@ -51,6 +51,7 @@ id name version org.dde.calendar dde-calendar 5.14.5.0 x86_64 main binary calendar for deepin os. org.deepin.browser deepin-browser 6.5.5.4 x86_64 main binary browser for deepin os. ``` + To view the installed runtime, run `ll-cli list --type=runtime`: ```bash diff --git a/docs/pages/en/guide/ll-cli/update.md b/docs/pages/en/guide/ll-cli/update.md index 9036df4fb..dd85bdb3f 100644 --- a/docs/pages/en/guide/ll-cli/update.md +++ b/docs/pages/en/guide/ll-cli/update.md @@ -52,5 +52,3 @@ Here is the output: Upgrade main:org.deepin.calculator/5.7.21.3/x86_64 to main:org.deepin.calculator/5.7.21.4/x86_64 success:100% Please restart the application after saving the data to experience the new version. ``` - - diff --git a/docs/pages/en/guide/ll-pica/adep.md b/docs/pages/en/guide/ll-pica/adep.md index 3315efddb..031cf0b4e 100644 --- a/docs/pages/en/guide/ll-pica/adep.md +++ b/docs/pages/en/guide/ll-pica/adep.md @@ -1,7 +1,7 @@ ## Add dependency linyaps applications may lack package dependencies, which can currently - be addressed by adding the corresponding package dependencies in the `linglong.yaml` file. +be addressed by adding the corresponding package dependencies in the `linglong.yaml` file. The `ll-pica adep` command is used to add package dependencies to the `linglong.yaml` file. diff --git a/docs/pages/en/guide/ll-pica/init.md b/docs/pages/en/guide/ll-pica/init.md index bfd8a2242..4a9cc8a41 100644 --- a/docs/pages/en/guide/ll-pica/init.md +++ b/docs/pages/en/guide/ll-pica/init.md @@ -63,8 +63,8 @@ Detailed Field Reference: [Manifests](../manifests.md) :::tip The default configuration file `~/.pica/config.json` - is set to use Deepin v23. If you need to specify UOS 20 as the BASE and - RUNTIME, modify the default configuration using the following command. +is set to use Deepin v23. If you need to specify UOS 20 as the BASE and +RUNTIME, modify the default configuration using the following command. Please update the link below, [https://professional-packages.chinauos.com/desktop-professional](https://professional-packages.chinauos.com/desktop-professional), to a version that does not require authentication. ::: diff --git a/docs/pages/en/guide/ll-pica/manifests.md b/docs/pages/en/guide/ll-pica/manifests.md index bbff4bb8e..472114462 100644 --- a/docs/pages/en/guide/ll-pica/manifests.md +++ b/docs/pages/en/guide/ll-pica/manifests.md @@ -29,13 +29,13 @@ runtime: arch: amd64 ``` -| name | description | -| -------------- | ------------------------------------------------------------------------------------------- | +| name | description | +| -------------- | ------------------------------------------------------------------------------------------ | | version | Runtime version, A three-digit number can be loosely matched with a potential fourth digit | | base_version | Base version, A three-digit number can be loosely matched with a potential fourth digit | -| source | Obtain the sources used by the dependencies of a deb package. | -| distro_version | The codename of a distribution." | -| arch | The architecture required by a deb package. | +| source | Obtain the sources used by the dependencies of a deb package. | +| distro_version | The codename of a distribution." | +| arch | The architecture required by a deb package. | ### Deb package informationeb diff --git a/docs/pages/en/guide/start/how_to_use.md b/docs/pages/en/guide/start/how_to_use.md index 232a783e6..068f1d2a6 100644 --- a/docs/pages/en/guide/start/how_to_use.md +++ b/docs/pages/en/guide/start/how_to_use.md @@ -109,7 +109,7 @@ ll-builder run --exec /bin/bash # Conversion application -Here, we use baidunetdisk as an example. We will introduce the process of converting DEB packages into linyaps packages +Here, we use baidunetdisk as an example. We will introduce the process of converting DEB packages into linyaps packages ## Obtain software package diff --git a/docs/pages/en/guide/start/whatis.md b/docs/pages/en/guide/start/whatis.md index d3c0d62eb..79c46b242 100644 --- a/docs/pages/en/guide/start/whatis.md +++ b/docs/pages/en/guide/start/whatis.md @@ -25,32 +25,32 @@ linyaps, an open source package format developed by UnionTech Software, is desig ## Comparison -| Features | Linglong | Flatpak | Snap | AppImage | -| ------------------------------------------- | ----------------------------------------------- | --------------------------- | --------------------------- | --------------------------------------------------------- | -| Package desktop apps | ✔ | ✔ | ✔ | ✔ | -| Package terminal apps | ✔ | ✔ | ✔ | ✔ | -| Deal with server apps | ✔ | ✘ | ✔ | ✘ | -| Package system services (root access) | ✘ | ✘ | ✔ | ✘ | -| Normal themes | ✔ | ✔ | ✔ | ✔ | -| Library hosting services | ✔ | ✘ | ✘ | ✘ | -| Source of libraries/dependencies | In packages | | | | -| Host system | In packages | | | | -| SDK | In packages | | | | -| snap base | | | | | -| Commercial support | ✔ | ✘ | ✔ | ✘ | -| Apps quantity | About 3000+ | 1400+ | 6600+ | 1300+ | -| Development tools | | GNOME Builder | electron-builder | | -| GNOME Builder | electron-builder | | | | -| Sandbox | ✔ | ✔ | ✔ | ◐ (Not officially available, but technically feasible) | -| Rootless sandbox | ✔ | ✘ | ✘ | ✘ | -| Run without installation | ✔ (Offer Bundle packages) | ✘ | ✘ | ✔ | -| Run without decompression | ✔ (Offer Bundle packages) | ✘ | ✔ | ✔ | -| Self-distribution/Green-format distribution | ◐ (Technically feasible, but system limits it) | ✘ | ✘ | ✔ | +| Features | Linglong | Flatpak | Snap | AppImage | +| ------------------------------------------- | ---------------------------------------------- | -------------------------- | -------------------------- | -------------------------------------------------------- | +| Package desktop apps | ✔ | ✔ | ✔ | ✔ | +| Package terminal apps | ✔ | ✔ | ✔ | ✔ | +| Deal with server apps | ✔ | ✘ | ✔ | ✘ | +| Package system services (root access) | ✘ | ✘ | ✔ | ✘ | +| Normal themes | ✔ | ✔ | ✔ | ✔ | +| Library hosting services | ✔ | ✘ | ✘ | ✘ | +| Source of libraries/dependencies | In packages | | | | +| Host system | In packages | | | | +| SDK | In packages | | | | +| snap base | | | | | +| Commercial support | ✔ | ✘ | ✔ | ✘ | +| Apps quantity | About 3000+ | 1400+ | 6600+ | 1300+ | +| Development tools | | GNOME Builder | electron-builder | | +| GNOME Builder | electron-builder | | | | +| Sandbox | ✔ | ✔ | ✔ | ◐ (Not officially available, but technically feasible) | +| Rootless sandbox | ✔ | ✘ | ✘ | ✘ | +| Run without installation | ✔ (Offer Bundle packages) | ✘ | ✘ | ✔ | +| Run without decompression | ✔ (Offer Bundle packages) | ✘ | ✔ | ✔ | +| Self-distribution/Green-format distribution | ◐ (Technically feasible, but system limits it) | ✘ | ✘ | ✔ | | Run Wine apps | ◐ (Adapting now) | ◐ (Theoretically possible) | ◐ (Theoretically possible) | ◐ (Use LD to modify open calls, with poor compatibility) | -| Support offline environment | ✔ | ✔ | ✔ | ✔ | -| Permission management | ✔ | ✔ | ✔ | ✘ | -| Center repository | mirror-repo-linglong.deepin.com | FlatHub | Snap Store | AppImageHub | -| | | | | | -| Multi-version coexistence | ✔ | ✔ | ✔ | ✔ | -| Peer-to-peer distribution | ✔ | ✔ | ✔ | ✔ | -| App upgrades | By repository | By repository | By repository | By official tool | +| Support offline environment | ✔ | ✔ | ✔ | ✔ | +| Permission management | ✔ | ✔ | ✔ | ✘ | +| Center repository | mirror-repo-linglong.deepin.com | FlatHub | Snap Store | AppImageHub | +| | | | | | +| Multi-version coexistence | ✔ | ✔ | ✔ | ✔ | +| Peer-to-peer distribution | ✔ | ✔ | ✔ | ✔ | +| App upgrades | By repository | By repository | By repository | By official tool | diff --git a/docs/pages/en/index.md b/docs/pages/en/index.md index 571bb5396..6373a9f7c 100644 --- a/docs/pages/en/index.md +++ b/docs/pages/en/index.md @@ -5,5 +5,5 @@ SPDX-License-Identifier: LGPL-3.0-or-later --> --- -title: Home ---- \ No newline at end of file + +## title: Home diff --git a/docs/pages/guide/debug/debug.md b/docs/pages/guide/debug/debug.md index 4f6c63816..cda0fc8c4 100644 --- a/docs/pages/guide/debug/debug.md +++ b/docs/pages/guide/debug/debug.md @@ -132,6 +132,7 @@ cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外 由于base镜像中没有包含调试符号,如果需要调试应用的系统依赖库,需要从base对应的debian仓库手动下载调试符号包。具体步骤如下: 1. 使用以下命令之一进入容器命令行环境: + ```bash ll-builder run --bash # 或 @@ -139,6 +140,7 @@ cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外 ``` 2. 查看base镜像使用的仓库地址: + ```bash cat /etc/apt/sources.list ``` @@ -148,6 +150,7 @@ cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外 - 完整的下载地址为: 仓库地址 + deb包路径 例如,要下载libgtk-3-0的调试符号包: + ```bash apt-cache show libgtk-3-0 | grep Filename # 输出: pool/main/g/gtk+3.0/libgtk-3-0_3.24.41-1deepin3_amd64.deb @@ -159,6 +162,7 @@ cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外 - `-dbg.deb` 5. 下载并解压调试符号包: + ```bash dpkg-deb -R -dbgsym.deb /tmp/ ``` @@ -169,4 +173,4 @@ cmake 会自动使用 cflags 和 cxxflags 环境变量,所以不需要额外 ${workspaceFolder}/linglong/output/develop/files/lib/debug:/tmp//usr/lib/debug ``` -这样调试器就能在解压的目录中找到系统依赖库的调试符号了。 \ No newline at end of file +这样调试器就能在解压的目录中找到系统依赖库的调试符号了。 diff --git a/docs/pages/guide/debug/faq.md b/docs/pages/guide/debug/faq.md index b00bfab73..76e49629b 100644 --- a/docs/pages/guide/debug/faq.md +++ b/docs/pages/guide/debug/faq.md @@ -9,64 +9,83 @@ SPDX-License-Identifier: LGPL-3.0-or-later 1. 应用运行读取 `/usr/share`下应用安装资源文件,为什么读取失败? 如意玲珑应用是在容器环境中运行,应用数据会挂载到 `/opt/apps/`/下,`/usr/share`目录下只会存在系统数据,不会存在应用相关数据。因此直接读取 `/usr/share` 会失败。建议处理:采用 `XDG_DATA_DIRS` 环境变量读取资源,`/opt/apps//files/share`会存在在此环境变量搜索路径中。 + 2. 应用运行时找不到字体库文件?为什么 `deb`包安装时能读取到对应的字体库? `deb`包安装时,会依赖带入对应的字体库文件。而如意玲珑包格式采用自给自足打包格式。除了基本的系统库,`runtime`里面提供的 `Qt`库与 `DTK`库文件不用自己提供外,其他依赖数据文件,均需自己提供。建议对应的数据文件放入 `files/share`下,采用环境变量 `XDG_DATA_DIRS`读取路径。 + 3. 如意玲珑应用 `runtime`里面有什么?能不能往里面添加一些库文件进去? 目前如意玲珑应用依赖的 `runtime`里面提供的是 `Qt`库与 `DTK`库。因 `runtime`有严格的大小限制。目前不允许往 `runtime`里面添加额外的库文件。 + 4. 应用在容器内运行,运行过程中能不能往容器任意路径下创建配置文件? 可以在 `XDG_CONFIG_HOME` 下创建配置文件。 + 5. 应用数据保存到哪里?在容器外哪里能找到? 因如意玲珑应用遵循互不干涉原则,`XDG_DATA_HOME`、`XDG_CONFIG_HOME`、`XDG_CACHE_HOME`环境变量被定义到宿主机 `~/.linglong/`/对应的路径下,因此用户应用数据会保存在此路径下,应用运行过程中写入数据时,也应该读取对应的环境变量写入数据。禁止读写其它应用的配置。 + 6. 应用提供了 `dbus service`文件,如何放置?`Exec`字段写什么? 应用提供 `dbus service`文件时,需要放到 `entries/dbus-1/services`目录下,如果 `Exec`执行如意玲珑包内二进制,使用 `--exec`选项参数执行对应的二进制。 + 7. 应用安装后,启动器无法找到? TryExec=xxx, 当xxx 在 $PATH 路径中不存在时,会认为该应用不存在不予显示。 + 8. 为什么图标显示为小黑点? desktop 写了 Icon 字段,Icon 字段名称错误或者使用了绝对路径。 + 9. 为什么图标显示为齿轮? desktop 未提供 Icon 字段。 + 10. 图标存放在哪个路径? - svg → $PREFIX/share/icons/hicolor/scalable/apps/ + svg → $PREFIX/share/icons/hicolor/scalable/apps/ 其他格式按分辨率存放,如16X16 png/xpm → $PREFIX/share/icons/hicolor/16X16/apps/ + 11. 应用自带的 `xdg-open`、`xdg-email`为什么失效? `runtime`中如意玲珑特殊处理了 `xdg-open`、`xdg-email`,因此应用禁止执行自己携带的xdg-open、xdg-email可执行文件或者脚本。 + 12. 应用使用系统环境变量未生效,为什么? 当使用环境变量时,需要确认容器内是否存在对应的环境变量,如果没有,需要联系如意玲珑团队处理。 + 13. 应用运行需要的库文件没找到,如何提供? 应用需要使用的资源文件,与库文件需要应用自身提供。库文件放到 `$PREFIX/lib` 路径下。 + 14. 应用运行时,为什么 `Qt WebEngine`渲染进程已崩溃? 因系统升级了 `glibc`,导致应用使用内置浏览器时失败,需要应用重新适配。临时解决方案是设置环境变量:`export QTWEBENGINE_DISABLE_SANDBOX=1`。 + 15. 应用运行时,找不到 `libqxcb.so`库或者 `qtwebengine` 报错? 存在 `qt.conf`文件时,在文件中配置正确路径,或者使用 `QTWEBENGINEPROCESS_PATH`、`QTWEBENGINE_RESOURCES_PATH`、`QT_QPA_PLATFORM_PLUGIN_PATH`、`QT_PLUGIN_PATH`环境变量配置搜索路径。 + 16. 应用能否自己携带数据库文件,并在运行中往数据库中写入数据? 容器内文件系统是只读文件系统,不允许往应用资源文件中写入数据。 + 17. 为什么执行携带 `suid`、`guid`权限二进制失效? 如意玲珑容器为保证系统安全,容器内禁止执行此类权限二进制。 + 18. uab离线包格式在 Debian、Ubuntu 下输入法无法使用? 建议安装 `fictx`输入法后体验。 + 19. 怎么知道容器环境中安装了哪些包? - `ll-builder run --exec bash` 进入容器环境,使用 `cat /var/lib/dpkg/status | grep "^Package: "` 命令查看预装的软件包,另外源码编译的库可以使用 `cat /runtime/packages.list` 查看。 + `ll-builder run --exec bash` 进入容器环境,使用 `cat /var/lib/dpkg/status | grep "^Package: "` 命令查看预装的软件包,另外源码编译的库可以使用 `cat /runtime/packages.list` 查看。 + 20. 应用启动后,为什么不显示应用托盘? 这可能是由应用注册托盘使用了相同的服务名,按照 KDE/freedesktop StatusNotifierItem 规范应用注册服务名为 org.kdeStatusNotifierItem-``-``,在如意玲珑应用中,应用运行时的 pid 为19,可以通过以下命令查看是否有注册过的服务,`dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.NameHasOwner string:org.kde.StatusNotifierItem-19-1`,如果存在 `boolean true` 说明服务被注册过。 diff --git a/docs/pages/guide/debug/ll-builder-faq.md b/docs/pages/guide/debug/ll-builder-faq.md index 7e845c091..bcfb4ae00 100644 --- a/docs/pages/guide/debug/ll-builder-faq.md +++ b/docs/pages/guide/debug/ll-builder-faq.md @@ -8,24 +8,24 @@ SPDX-License-Identifier: LGPL-3.0-or-later 1. `cmake`类型构建,出现`-lxxx`失败,但`ldconfig`与`pkg-config`均能查询到该库信息。 - 链接库路径不在常规路径,新路径为`/runtime/lib`。 + 链接库路径不在常规路径,新路径为`/runtime/lib`。 - 添加环境变量 `LIBRARY_PATH=`,目前构建环境已默认包含该环境变量。 + 添加环境变量 `LIBRARY_PATH=`,目前构建环境已默认包含该环境变量。 2. 构建时`link`静态库失败,要求重新使用`fPIC`构建。 - 构建静态库时使用`-fPIC`参数。 + 构建静态库时使用`-fPIC`参数。 3. 构建时启动`box`失败,如下图: - ![ll-box启动失败](images/ll-box-start-failed.png) + ![ll-box启动失败](images/ll-box-start-failed.png) - 内核不支持`unprivilege namespace`,开启`unprivilege namespace`解决。 + 内核不支持`unprivilege namespace`,开启`unprivilege namespace`解决。 - ```bash - sudo sysctl -w kernel.unprivileged_userns_clone=1 - ``` + ```bash + sudo sysctl -w kernel.unprivileged_userns_clone=1 + ``` 4. `qtbase`构建成功,但无法构建`qt`应用,提示`module,mkspec` 相关错误。 - 低版本`fuse-overlay mount`存在问题,导致`qtbase commit`时文件内容被污染 ,无法正常使用。使用`fuse-overlayfs >= 1.7`版本。 + 低版本`fuse-overlay mount`存在问题,导致`qtbase commit`时文件内容被污染 ,无法正常使用。使用`fuse-overlayfs >= 1.7`版本。 diff --git a/docs/pages/guide/debug/ll-pica-faq.md b/docs/pages/guide/debug/ll-pica-faq.md index 340ddc7cb..c526f86b9 100644 --- a/docs/pages/guide/debug/ll-pica-faq.md +++ b/docs/pages/guide/debug/ll-pica-faq.md @@ -3,15 +3,17 @@ 1. ll-pica 生成的 linglong.yaml 文件的默认配置在哪里? ll-pica 配置文件在 `~/.pica/config.json`。 + 2. ll-pica 无法转换,wine、安卓、输入法、安全类软件吗? 如意玲珑应用目前不支持这类应用,ll-pica 也无法转换。 + 3. 为什么需要使用音频的软件没有声音? 提示 not found libpulsecommon-12.2.so 可以在linglong.yaml 文件build 字段的里面,添加一行 `mv $PREFIX/lib/$TRIPLET/pulseaudio/* $PREFIX/lib/$TRIPLET`。 + 4. 为什么生成出来的 linglong.yaml 文件中 command 字段是空的? ll-pica 是通过读取,deb 包中的 desktop 文件里来获取 Exec 字段,如果 command 为空,请检查 deb 包中的 desktop 文件路径是否在以下路径。 - - /opt/apps/$appid/entries/applications - /usr/share/applications diff --git a/docs/pages/guide/lessons/basic-notes.md b/docs/pages/guide/lessons/basic-notes.md index f72be69bd..796837e1f 100755 --- a/docs/pages/guide/lessons/basic-notes.md +++ b/docs/pages/guide/lessons/basic-notes.md @@ -1,16 +1,19 @@ # 玲珑应用构建工程基础知识 + 在正式开始构建一个玲珑应用工程前, 我们需要对关于玲珑应用构建的基础知识有一定的认知, 以此协助我们更好地决策我们在启动构建工程前决定要准备哪些材料、进行哪一类型的操作 ## 玲珑应用构建基本步骤 + 在正式开始构建一个玲珑应用工程前, 我们需要了解一个玲珑应用从资源(源代码、二进制文件等)输入到应用安装包导出所经过的基本步骤, 来确定我们需要准备哪些必要文件 1. 获取构建目标源文件(开源项目源代码、应用二进制文件等) 2. 根据源文件判断玲珑应用构建类型, 选择合适的构建方案 3. 准备符合要求的玲珑构建环境 -4. 按照构建类型及源代码内容定制构建配置文件 `linglong.yaml` +4. 按照构建类型及源代码内容定制构建配置文件 `linglong.yaml` 5. 准备应用所使用的通用类资源, 图标以及其他非二进制资源 ## 玲珑应用构建工程所需材料 + 结合上述的知识, 我们可以了解到一个玲珑应用在构建的全过程中, 主要涉及到以下的文件: 1. 玲珑应用构建工程配置文件 `linglong.yaml` @@ -18,6 +21,7 @@ 3. 非二进制文件等通用资源 ## 玲珑应用遵循的主流规范 + 每一款Linux桌面软件包管理方案为了能够保障完整的功能和良好的体验, 均需要遵守软件包管理方案提出的各类规范要求以最大限度发挥软件包管理方案的功能并保障应用生态体验. 如意玲珑也并不总是特立独行, 需要满足一定的规范来保障如意玲珑生态得以持续稳步发展. @@ -25,7 +29,7 @@ 1. Freedesktop XDG规范 2. 玲珑应用目录结构规范 -3. 玲珑应用构建工程配置文件 `linglong.yaml` 规范 +3. 玲珑应用构建工程配置文件 `linglong.yaml` 规范 ### Freedesktop XDG规范 @@ -42,8 +46,8 @@ 3. 在构建工程中, 构建工程目录将会被映射到玲珑容器中, 挂载为 `/project` 4. 玲珑应用容器中运行库、头文件所在目录将根据运行环境类型而异 -foundation类: 在玲珑容器中映射为普通系统路径 `/usr/bin` `/usr/include` 等, 作为基础运行系统环境存在 -runtime类: 在玲珑容器中映射为runtime容器路径 `/runtime/usr/bin` `/runtime/usr/include` 等, 作为基础运行系统环境存在 + foundation类: 在玲珑容器中映射为普通系统路径 `/usr/bin` `/usr/include` 等, 作为基础运行系统环境存在 + runtime类: 在玲珑容器中映射为runtime容器路径 `/runtime/usr/bin` `/runtime/usr/include` 等, 作为基础运行系统环境存在 \*默认情况下, 玲珑容器内部的环境变量已自动处理好路径识别问题, 如: @@ -53,15 +57,18 @@ PATH=szbt@szbt-linyaps23:/project$ echo $PATH ``` 通用表达为: + ``` PATH=szbt@szbt-linyaps23:/project$ echo $PATH /bin:/usr/bin:/runtime/bin:$PREFIX/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin ``` ## 玲珑应用构建工程通用资源的规范 + 在玲珑应用构建工程中, 不同的资源文件均需要遵循相关规范以确保构建、体验能够满足要求 ### icons 图标目录规范 + 依据玲珑遵循的 `Freedesktop XDG规范` 及 `玲珑应用目录结构规范`, 图标根据不同尺寸放置在对应的目录中 主流的非矢量图标尺寸有: `16x16` `24x24` `32x32` `48x48` `128x128` `256x256` `512x512` @@ -79,21 +86,25 @@ $PREFIX/share/icons/hicolor/256x256/apps $PREFIX/share/icons/hicolor/512x512/apps $PREFIX/share/icons/hicolor/scalable/apps ``` + \* `scalable` 目录用于放置 `矢量图标` 文件, 一般为 `.svg` 格式 假设你的玲珑应用同时提供尺寸为 `128x128` 的非矢量图标文件 `linyaps-app-demo.png` 和 `128x128` 的矢量图标文件 `linyaps-app-demo.svg`, 在玲珑容器中应当表现为以下状态 + ``` $PREFIX/share/icons/hicolor/128x128/apps/linyaps-app-demo.png $PREFIX/share/icons/hicolor/scalable/apps/linyaps-app-demo.svg ``` + \* 为了避免图标冲突被覆盖, 图标文件名请使用应用 `唯一英文名称` 或 `玲珑应用id` ### desktop 文件规范 + 玲珑应用兼容大部分符合 `Freedesktop XDG规范` 的 `desktop启动文件`, 其中有以下字段需要额外注意: -| 字段 | 值要求 | -|-------|---------| -| Exec | 该值用于设置点击此desktop文件时执行的指令, 需要与 `linglong.yaml` 中的 `command` 值保持一致 | +| 字段 | 值要求 | +| ---- | ------------------------------------------------------------------------------------------------------------- | +| Exec | 该值用于设置点击此desktop文件时执行的指令, 需要与 `linglong.yaml` 中的 `command` 值保持一致 | | Icon | 该值用于设置该desktop文件显示的应用图标, 需要与 `icons 图标目录规范` 中的图标文件名一致, 此值不需要文件名后缀 | 因此, 一个符合玲珑应用规范的desktop文件可以参考: @@ -116,22 +127,23 @@ Terminal=false ``` ## 玲珑应用构建工程 `linglong.yaml` 规范 -正如其他传统包管理套件一样, 手动创建一个玲珑应用构建工程需要设置构建规则文件 `linglong.yaml`, 在构建规则中, 则根据用途划分为 `全局字段` 及 `定制化字段`. -\* 案例中 `linglong.yaml` 正文内所有空格符号、占位符均为有效字符, 请勿删除或变更格式 + +正如其他传统包管理套件一样, 手动创建一个玲珑应用构建工程需要设置构建规则文件 `linglong.yaml`, 在构建规则中, 则根据用途划分为 `全局字段` 及 `定制化字段`. \* 案例中 `linglong.yaml` 正文内所有空格符号、占位符均为有效字符, 请勿删除或变更格式 ### 全局字段规范 + 在 `linglong.yaml` 中, 对于不受构建类型影响的字段我们称为 `全局字段`, 主要有以下参考的规范: 1. 一个可以正常开始构建工程的 `linglong.yaml` 应包含以下的关键部分: -| 模块 | 解释 | -|-------|-------| -| version | 构建工程版本号 | -| package | 玲珑应用基本信息 | -| base | 玲珑应用容器基础环境及版本设置, 基础环境中包含了部分基础运行库 | -| runtime | 玲珑应用运行库 `runtime` 及版本设置, 当 `base` 中的基础运行库满足程序运行要求时, 此模块可删除 | -| command | 玲珑应用容器启动时执行的命令, 与 `desktop` 文件的 `Exec` 字段内容一致 | -| sources | 玲珑应用构建工程源文件类型 | -| build | 玲珑应用构建工程将要执行的构建规则 | + | 模块 | 解释 | + |-------|-------| + | version | 构建工程版本号 | + | package | 玲珑应用基本信息 | + | base | 玲珑应用容器基础环境及版本设置, 基础环境中包含了部分基础运行库 | + | runtime | 玲珑应用运行库 `runtime` 及版本设置, 当 `base` 中的基础运行库满足程序运行要求时, 此模块可删除 | + | command | 玲珑应用容器启动时执行的命令, 与 `desktop` 文件的 `Exec` 字段内容一致 | + | sources | 玲珑应用构建工程源文件类型 | + | build | 玲珑应用构建工程将要执行的构建规则 | `package` 模块中存在数个子模块: | 子模块 | 解释 | @@ -142,32 +154,35 @@ Terminal=false | kind | 玲珑应用类型, 默认为 `app` | | description | 玲珑应用描述 | -2. 玲珑应用遵循 `$PREFIX` 路径规则,该变量自动生成,应用所有相关文件需存放于此目录下. 构建规则中若有需要涉及安装文件的操作, 均需要安装到 `$PREFIX` 路径下 -\* `$PREFIX` 变量名即为填写的实际内容, **请勿使用 `绝对路径` 或任何具有绝对值作用的内容代替 ** +2. 玲珑应用遵循 `$PREFIX` 路径规则,该变量自动生成,应用所有相关文件需存放于此目录下. 构建规则中若有需要涉及安装文件的操作, 均需要安装到 `$PREFIX` 路径下 \* `$PREFIX` 变量名即为填写的实际内容, **请勿使用 `绝对路径` 或任何具有绝对值作用的内容代替 ** 3. 玲珑应用目前遵循 `四位数字` 的版本号命名规则,不符合规则无法启动构建工程 4. `base`、`runtime` 版本支持自动匹配最新版本 `尾号`,版本号可以仅填写版本号的`前三位数字`.如: -当base `org.deepin.foundation`同时提供 `23.0.0.28` `23.0.0.29`, 若 `linglong.yaml` 中仅填写 + 当base `org.deepin.foundation`同时提供 `23.0.0.28` `23.0.0.29`, 若 `linglong.yaml` 中仅填写 + ``` base: org.deepin.foundation/23.0.0 ``` + 那么在启动玲珑应用构建工程时, 将会默认采用最高版本号的 `23.0.0.29` 5 玲珑应用构建工程配置文件目前不直接兼容其他包构建工具的配置文件,需要根据构建工程配置文件案例来进行适配修改: https://linglong.dev/guide/ll-builder/manifests.html - ### 定制化字段 -根据玲珑应用构建工程源文件类型, 又可将玲珑应用构建工程划分为 `本地文件文件构建` `git 源码仓库拉取构建`, 不同类型则需要填写不同的 `linglong.yaml` + +根据玲珑应用构建工程源文件类型, 又可将玲珑应用构建工程划分为 `本地文件文件构建` `git 源码仓库拉取构建`, 不同类型则需要填写不同的 `linglong.yaml` 玲珑应用构建工程源文件类型 `sources` 主要支持这几种类型: `git` `local` `file` `archive` 完整说明参考: [构建配置文件简介](https://linyaps.org.cn/guide/ll-builder/manifests.html) #### git拉取源码编译模式 -当玲珑应用构建工程需要通过git拉取开源项目仓库资源到本地进行构建时, 此时 `sources` 应当设置为 `git` 类型, 并根据要求填写 `linglong.yaml` + +当玲珑应用构建工程需要通过git拉取开源项目仓库资源到本地进行构建时, 此时 `sources` 应当设置为 `git` 类型, 并根据要求填写 `linglong.yaml` 此时需要根据规范编写 `sources` 与 `build` 模块 1. `sources` 示例: + ```yaml sources: - kind: git @@ -181,15 +196,17 @@ sources: commit: 4b4003d0fdc09a257a0841ad965b22533ed87a0d ``` -| 名称 | 描述 | -|------|-------| -| kind | 源文件类型 | -| url | 需要通过git拉取的源代码仓库地址, 该仓库需要支持git功能. 当网络状态不佳时, 可采用镜像地址代替 | -| version | 指定源代码仓库的版本号, 即 `tag标签`, 或拉取主线 `master` | -| commit | 根据该仓库 `commit` 变动历史拉取源码, 此处填入commit对应的值, 将会应用该仓库截止本commit的所有变更. *此字段优先级高于 `version`, 请勿填入 `version` 合并时间之后的任何 `commit`| +| 名称 | 描述 | +| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| kind | 源文件类型 | +| url | 需要通过git拉取的源代码仓库地址, 该仓库需要支持git功能. 当网络状态不佳时, 可采用镜像地址代替 | +| version | 指定源代码仓库的版本号, 即 `tag标签`, 或拉取主线 `master` | +| commit | 根据该仓库 `commit` 变动历史拉取源码, 此处填入commit对应的值, 将会应用该仓库截止本commit的所有变更. \*此字段优先级高于 `version`, 请勿填入 `version` 合并时间之后的任何 `commit` | + \* 支持同时添加多个git仓库作为 `sources` 拉取 2. `build` 示例: + ```yaml build: | mkdir -p ${PREFIX}/bin/ ${PREFIX}/share/ @@ -197,15 +214,18 @@ build: | cd /project/linglong/sources/qBittorrent.git git apply -v /project/patches/linyaps-qBittorrent-4.6.7-szbt2.patch ``` + 此模块为构建规则正文, 路径遵守 `玲珑应用目录结构规范` 在 `sources` 拉取到本地后, 仓库文件将会存放在 `/project/linglong/sources` 目录中, 此时不同仓库目录以 `xxx.git` 命名 支持运用 `git patch` 功能对源代码进行便捷维护 #### 本地资源操作模式 -当玲珑应用构建工程需要对构建目录中的文件操作时, 此时 `kind` 应当设置为 `local` 类型, 并根据要求填写 `linglong.yaml` + +当玲珑应用构建工程需要对构建目录中的文件操作时, 此时 `kind` 应当设置为 `local` 类型, 并根据要求填写 `linglong.yaml` 此时需要根据规范编写 `sources` 与 `build` 模块 1. `sources` 示例: + ```yaml sources: source: @@ -213,14 +233,15 @@ source: name: "qBittorrent" ``` -| 名称 | 描述 | -|------|-------| -| kind | 源文件类型 | +| 名称 | 描述 | +| ---- | ------------------------------ | +| kind | 源文件类型 | | name | 源文件名称标识, 不具备实际用途 | \* 当 `kind` 应当设置为 `local` 类型时, 构建工程将不会对任何源文件进行操作 2. `build` 示例: + ```yaml build: | ##Build main @@ -231,12 +252,13 @@ build: | make -j$(nproc) make install ``` + 此模块为构建规则正文, 路径遵守 `玲珑应用目录结构规范` -此时 `build` 规则支持多种写法以模拟人为操作 -\* 需要确保此构建规则所有步骤均可以正常被执行, 否则将会中断当次构建任务 +此时 `build` 规则支持多种写法以模拟人为操作 \* 需要确保此构建规则所有步骤均可以正常被执行, 否则将会中断当次构建任务 #### 容器内部手动操作模式 + 若计划直接进入玲珑容器手动操作而不是通过构建规则文件 `linglong.yaml`,那么应该参考 `本地资源操作模式` 填写 `linglong.yaml` 1. `sources` 部分写法与 `本地资源操作模式` 一致 -2. 由于使用手动操作, 因此不需要完整且可以正常被执行的 `build` 规则, 此时 `linglong.yaml` 用于生成符合描述的玲珑容器而不是执行所有任务, 具体操作可查阅后续课程关于容器内部构建文件的案例 \ No newline at end of file +2. 由于使用手动操作, 因此不需要完整且可以正常被执行的 `build` 规则, 此时 `linglong.yaml` 用于生成符合描述的玲珑容器而不是执行所有任务, 具体操作可查阅后续课程关于容器内部构建文件的案例 diff --git a/docs/pages/guide/lessons/build-git-patch.md b/docs/pages/guide/lessons/build-git-patch.md index 73820eb4e..634bcd213 100644 --- a/docs/pages/guide/lessons/build-git-patch.md +++ b/docs/pages/guide/lessons/build-git-patch.md @@ -1,4 +1,5 @@ # 将基于Qt5的开源应用--qBittorrent 适配为支持自动化的玲珑应用构建工程 + 书接上文, 我们继续探讨如何将 `linglong.yaml` 适配为支持自动构建的版本 由于上一环节我们已经确定了可以正常完成编译构建任务所使用的构建规则, 因此我们本节主要讨论如何利用 `git` 功能完成下列自动操作 @@ -6,14 +7,17 @@ 2. 自动应用自定义patch内容 ## 改造 `linglong.yaml` + 在上一节中我们已经获得了可以成功编译本地源代码的 `linglong.yaml`, 由于是同一款应用项目, 我们可以直接在其基础上进行改造 对于 `linglong.yaml` 而言, 核心部分之二主要是 `sources` 和 `build` 模块, 这次我们分开这两部分进行详解 ### `sources` 模块 + 根据 [玲珑应用构建工程 `linglong.yaml` 规范], 当构建工程的源文件为git仓库时(即通过git clone拉取源代码仓库), `sources` 的源文件类型 `kind` 应设为 `git` 并填写仓库的相关信息 根据 [玲珑应用构建工程 `linglong.yaml` 规范] 的 `git拉取源码编译模式` 规范, 我们需要掌握源代码仓库的以下信息: + 1. url, 即git clone 所使用的地址, 如普通git clone一样可以使用镜像地址 2. version, 即需要抓取仓库的某一个具体版本号, 一般为 `Tags` 标签 3. 需要应用的仓库commit编号, 此处填入commit对应的值, 将会应用该仓库截止本commit的所有变更. 此字段优先级高于 `version`, 请勿填入 `version` 合并时间之后的任何 `commit` @@ -40,10 +44,12 @@ sources: 由图可见, 填入的commit值均匹配了对应Tag生成时的commit ### `build` 模块 + 在完成源文件信息设置后, 我们开始修改构建规则 考虑到上一课时已经取得了执行性较强的构建规则, 因此我们仅需根据 [玲珑应用构建工程 `linglong.yaml` 规范] `git拉取源码编译模式` 中的相关规范修改源码路径即可 在完成修改后, 我们将会得到如下的构建规则: + ```yaml build: | mkdir -p ${PREFIX}/bin/ ${PREFIX}/share/ @@ -68,6 +74,7 @@ build: | ``` ### 自定义patch应用 + 在本次案例中, 我们同时引入了新场景: 当拉取开源项目某个具体版本号的仓库资源后, 需要在源码上进行修改以达到修复漏洞、bug的补丁效果 为此, 我们需要学习一个新知识: `git patch` 相关内容, git程序内置patch管理系统, 需要便捷地利用此功能对源码进行修订, 一般有以下步骤: @@ -96,17 +103,18 @@ origin https://ghp.ci/https://github.com/qbittorrent/qBittorrent.git (push) 可见, 执行指令后可以返回远程仓库的信息, 此目录满足要求 -3. 随后, 根据上述安全漏洞提交时文件变更对源码进行手动修改 -\* 此处需要维护者根据经验判断具体需要合入哪些提交 +3. 随后, 根据上述安全漏洞提交时文件变更对源码进行手动修改 \* 此处需要维护者根据经验判断具体需要合入哪些提交 4. 修改完成后, 返回源码根目录, 执行 `git diff` 可以查看存在的差异比对: 5. 确认无误后, 将此差异保存到本地中, 形成patch文件 + ```bash ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ git diff > ./ ``` 6. 在得到patch文件后, 我们将应用patch的内容添加到已有的 `build` 构建规则中: + ```yaml build: | mkdir -p ${PREFIX}/bin/ ${PREFIX}/share/ @@ -133,6 +141,7 @@ build: | ##Extract common res cp -rf /project/template_app/* ${PREFIX}/share/ ``` + 7. 此刻我们可以返回构建目录, 开始构建测试了, 执行: ```bash @@ -140,23 +149,29 @@ ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ ll-builder build ``` 此次构建很快就成功结束了, 我们执行以下指令来将容器导出为玲珑应用安装包 `binary.layer` : + ```bash ziggy@linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-local$ ll-builder export --layer ``` ## 本地构建结果测试 + 在得到玲珑应用安装包后, 我在不同支持玲珑环境的主流发行版上尝试体验, 来确认通过玲珑容器构建的二进制程序是否存在通用性 ### deepin 23 + #![deepin 23](image/4-test-1.png) ### openKylin 2.0 + #![openKylin 2.0](image/4-test-2.png) ### Ubuntu 2404 + #![Ubuntu 2404](image/4-test-3.png) ### OpenEuler 2403 + #![OpenEuler 2403](image/4-test-4.png) 至此, 足以证明 `基于Qt5的开源应用--qBittorrent` 在添加定制补丁以及修改构建规则后可以实现一站拉取项目源码并编译成可执行的二进制文件, 并在其他发行版上也可以使用 ! diff --git a/docs/pages/guide/lessons/build-in-env.md b/docs/pages/guide/lessons/build-in-env.md index 301f7f37f..5e0ab9cac 100644 --- a/docs/pages/guide/lessons/build-in-env.md +++ b/docs/pages/guide/lessons/build-in-env.md @@ -1,13 +1,16 @@ # 在玲珑容器中编译基于Qt5的开源应用--qBittorrent + 在学习上一章节 `玲珑应用构建工程基础知识` 后, 我们即将步入实操课堂, 利用所学知识去正式构建一款玲珑应用. 今天, 我们将演示进入玲珑容器并将一款开源图形应用 `qBittorrent` 的源代码编译为二进制文件并测试运行 ## 前期准备 + 根据 `玲珑应用构建工程基础知识` 中对于 `玲珑应用构建工程通用资源的规范` 要求, 我们应当为一款图形化应用同时提供保障桌面用户体验的 `icons` 图标文件及 `desktop` 启动文件 但本节实操课堂仅在玲珑容器中进行编译、测试操作, 因此暂时不需要准备通用资源 本次分享基于 `deepin 23` 发行版, 因此在进行以下任意步骤前均需要准备一个可以构建玲珑应用的 `deepin 23` 系统环境: + 1. 确保环境中已经安装 `ll-builder` 构建套件, 不同发行版安装方式参考: [安装玲珑](https://linyaps.org.cn/guide/start/install.html) 2. 由于在构建过程中我们需要联网获取玲珑容器的运行库以及可能需要的第三方库, 因此我们需要保障全操作过程能够得到顺畅的网络连接 @@ -16,10 +19,7 @@ 4. 结合上一节 [玲珑应用构建工程 `linglong.yaml` 规范] 并按照以下模板简单编写一版玲珑构建工程配置文件 `linglong.yaml`, 以此来生成一个符合要求的容器 -主要有以下需要关注的点: -\* 由于本次操作是直接进入容器进行操作, 因此 `build` 部分的构建规则可不详细写 -\* 由于本次涉及编译操作, 为了能够极大程度包含所需的运行库, 我们加入 `runtime` 段, 具体编写规范参考 [玲珑应用构建工程基础知识] - +主要有以下需要关注的点: \* 由于本次操作是直接进入容器进行操作, 因此 `build` 部分的构建规则可不详细写 \* 由于本次涉及编译操作, 为了能够极大程度包含所需的运行库, 我们加入 `runtime` 段, 具体编写规范参考 [玲珑应用构建工程基础知识] ```yaml # SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. @@ -51,6 +51,7 @@ build: | ``` ### 项目编译演示 + \*这里需要回顾一个知识点: 根据 [玲珑应用目录结构规范], 与构建工程配置文件 `linglong.yaml` 同级的构建目录将被映射为 `/project` 目录 万事俱备, 我们就可以开始编译了 @@ -63,35 +64,38 @@ szbt@szbt-linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-git$ ll-builder bui ``` 路径发生类似以下变化时, 即意味着我们已经进入玲珑容器中了 + ``` szbt@szbt-linyaps23:/project$ ``` 3. 通过 `普通操作` 窗口解压 `qBittorrent-4.6.7` 源码到构建目录中, 我这里单独解压到一个子目录中 + ``` szbt@szbt-linyaps23:/media/szbt/Data/ll-build/QT/qBittorrent-git$ tar -xvf qBittorrent-4.6.7-git-origin-src.tar.zst -C src/ ``` 4. 源码解压后, 根据 [玲珑应用构建基本步骤], 我们在编译任意源代码前应该正确选择使用何种编译系统/工具. 我们通过观察 `qBittorrent-4.6.7` 源码目录, 可以看到其存在 `CMakeLists.txt` 文件, 这是 `CMake` 构建项目. -![1](image/2-1.png) + ![1](image/2-1.png) 5. 由于 [qBittorrent INSTALL](https://github.com/qbittorrent/qBittorrent/blob/release-4.6.7/INSTALL) 中简要描述了本项目主要使用的运行库, 因此我们可以对照此文档来判断哪些运行库存在与玲珑提供的 `base`、 `runtime` 中或哪些运行库并未被提供的. 对于暂未被正式提供的运行库, 在编译主程序前我们可能需要先预编译必要的第三方库. 由于文档所述需要的运行库较少, 此次我们可以先直接进行一次测试编译来确认运行库缺失情况 6. 事不宜迟, 我们通过 `玲珑容器操作` 窗口进入源码目录, 为了尽量避免对源目录的干扰, 我这里新建一个 `build` 目录用于编译. 进入 `build` 目录后我们输入CMake相关配置参数来配置构建工程. -根据[玲珑应用目录结构规范], 我们将 `DCMAKE_INSTALL_PREFIX` 赋予 `$PREFIX` 的值, 最终我在本地执行了以下操作: + 根据[玲珑应用目录结构规范], 我们将 `DCMAKE_INSTALL_PREFIX` 赋予 `$PREFIX` 的值, 最终我在本地执行了以下操作: + ``` cmake -DCMAKE_BUILD_TYPE=Release\ -DCMAKE_INSTALL_PREFIX=$PREFIX .. ``` -7. 可以从图中看到, 这里出现了一个错误导致无法完成配置. 我们看到 `pkg-config` 出现错误: `libtorrent-rasterbar>=1.2.19` 库不能满足条件: +7. 可以从图中看到, 这里出现了一个错误导致无法完成配置. 我们看到 `pkg-config` 出现错误: `libtorrent-rasterbar>=1.2.19` 库不能满足条件: ![error-1](image/2-error-1.png) ``` --- Found PkgConfig: /bin/pkg-config (found version "1.8.1") +-- Found PkgConfig: /bin/pkg-config (found version "1.8.1") -- Checking for module 'libtorrent-rasterbar>=1.2.19' ``` @@ -103,7 +107,6 @@ szbt@szbt-linyaps23:/project/src/qBittorrent-release-4.6.7-szbt2/build$ pkg-conf 结合此报错, 基本可以判断为该库缺失, 因此我们需要在编译主程序前编译并安装此第三方库 - 8. 我们返回`普通操作` 窗口将: `libtorrent-rasterbar>=1.2.19` 库对应的源码下载到当前构建目录中, 进入`玲珑容器操作` 窗口重新编译 9. 源码解压后, 根据 [玲珑应用构建基本步骤], 我们在编译任意源代码前应该正确选择使用何种编译系统/工具. 我们通过观察 `libtorrent-rasterbar-2.0.9` 源码目录, 可以看到其存在 `CMakeLists.txt` 文件, 这是 `CMake` 构建项目. @@ -111,7 +114,8 @@ szbt@szbt-linyaps23:/project/src/qBittorrent-release-4.6.7-szbt2/build$ pkg-conf ![2](image/2-2.png) 10. 我们通过 `玲珑容器操作` 窗口进入源码目录, 为了尽量避免对源目录的干扰, 我这里新建一个 `build` 目录用于编译. 进入 `build` 目录后我们输入CMake相关配置参数来配置构建工程. -根据[玲珑应用目录结构规范], 我们将 `DCMAKE_INSTALL_PREFIX` 赋予 `$PREFIX` 的值, 最终我在本地执行了以下操作: + 根据[玲珑应用目录结构规范], 我们将 `DCMAKE_INSTALL_PREFIX` 赋予 `$PREFIX` 的值, 最终我在本地执行了以下操作: + ``` cmake -DCMAKE_BUILD_TYPE=Release\ -DCMAKE_INSTALL_PREFIX=$PREFIX .. @@ -124,8 +128,8 @@ szbt@szbt-linyaps23:/project/src/qBittorrent-release-4.6.7-szbt2/build$ pkg-conf 11. 我们返回 `玲珑容器操作` 窗口进入 `qBittorrent-4.6.7` 源码目录,重新执行配置、编译、安装操作, 均不存在报错了. ### 编译结果测试 - 在流程结束后, 我们在 `$PREFIX` 目录中找到该项目的二进制执行文件 `/opt/apps/org.qbittorrent.qBittorrent/files/bin/qbittorrent` 并在容器中运行测试 -\* 该操作需要在图形化桌面的终端操作, 否则有可能无法调起程序的图形界面 + +在流程结束后, 我们在 `$PREFIX` 目录中找到该项目的二进制执行文件 `/opt/apps/org.qbittorrent.qBittorrent/files/bin/qbittorrent` 并在容器中运行测试 \* 该操作需要在图形化桌面的终端操作, 否则有可能无法调起程序的图形界面 看起来因为并不是直接通过容器启动, 发生了运行库无法找到的问题, 因为报错的库也在$PREFIX中, 因此我们直接通过变量 `LD_LIBRARY_PATH` 来指定动态运行库寻找路径 diff --git a/docs/pages/guide/lessons/build-offline-src.md b/docs/pages/guide/lessons/build-offline-src.md index a6fc5b22e..13beb591c 100644 --- a/docs/pages/guide/lessons/build-offline-src.md +++ b/docs/pages/guide/lessons/build-offline-src.md @@ -82,7 +82,6 @@ Icon=qbittorrent 由于在上节课程中我们已经准备了一版简单但不具备完整构建功能的 `linglong.yaml`, 因此我们可以在其基础上进行定制, 现在是初始状态: ```yaml - version: "4.6.7.2" package: @@ -144,15 +143,13 @@ build: | cp -rf /project/template_app/* ${PREFIX}/share/ ``` -在将此块构建规则补全后, 我们可以开始尝试通过自动化构建来将本地源码编译为二进制程序并导出玲珑应用安装包 `binary.layer` 了 -\* 由于此版配置文件不提供解压、删除功能, 因此每次重新构建前均需要将这些目录清空并重新解压 +在将此块构建规则补全后, 我们可以开始尝试通过自动化构建来将本地源码编译为二进制程序并导出玲珑应用安装包 `binary.layer` 了 \* 由于此版配置文件不提供解压、删除功能, 因此每次重新构建前均需要将这些目录清空并重新解压 ### 本地一站构建测试 在补全 `build` 模块后, 此时的 `linglong.yaml` 状态: ```yaml - version: "2" package: diff --git a/docs/pages/guide/lessons/test-with-toolchains.md b/docs/pages/guide/lessons/test-with-toolchains.md index 5d7544c5a..4db096346 100644 --- a/docs/pages/guide/lessons/test-with-toolchains.md +++ b/docs/pages/guide/lessons/test-with-toolchains.md @@ -1,9 +1,11 @@ # 玲珑应用兼容性测试进阶--玲珑应用自动化测试套件 + 大家可以发现, 在我们前面的玲珑应用编译之后, 都是通过手动安装软件包、启动应用来检验兼容性的 但是这里会衍生出一个问题: 随着需要测试的应用不断增加, 人工测试的方式是否显得相对低效率? 为此, 我向各位介绍如意玲珑社区中目前开放给各生态贡献者使用、学习的 `玲珑应用自动化测试套件 -- Next Linyaps Testing Toolchains` ## 项目介绍 + `Next Linyaps Testing Toolchains` 是一套shell脚本组成的玲珑应用测试工具链,旨在为玲珑应用测试带来更多便捷的方案 本项目是[linglong-automan](https://gitee.com/ziggy615/linglong-automan)的正统精神传承,并承诺永久开源 @@ -13,29 +15,32 @@ 2. 指定整理完成的玲珑文件存放目录后,开启流水化安装进程 -3. 指定资源存放目录和应用信息表格后,根据 `安装情况`、 `desktop文件存在状态` 、`窗口生成状态` 来模拟通过desktop文件启动应用,并对测试结果进行截图 -\* 当前代码部分功能依赖 `deepin 23` 系统组件,在其他发行版使用时需要重新适配 +3. 指定资源存放目录和应用信息表格后,根据 `安装情况`、 `desktop文件存在状态` 、`窗口生成状态` 来模拟通过desktop文件启动应用,并对测试结果进行截图 \* 当前代码部分功能依赖 `deepin 23` 系统组件,在其他发行版使用时需要重新适配 4. 对已安装的玲珑应用进行图标文件扫描, 判断当前应用icons目录及文件是否符合 `Freedesktop XDG` 规范并收集图标 5. 对已安装的玲珑应用进行批量卸载 ## 代码结构解析 + 进入套件仓库, 可以看到该套件根据功能/作用划分为了数个关键独立脚本, 大体为: 1. `linyaps-auto-optimize.sh`, 玲珑应用安装包 `binary.layer` 整理工具. 将某目录下所有 `binary.layer` 文件整理为符合测试套件的结构并产出两个表格用于记录玲珑应用id、版本号如: + ``` org.qbittorrent.qBittorrent/package/org.qbittorrent.qBittorrent_4.6.7.22_x86_64_binary.layer com.poki.apple-knight-golf.linyaps/package/com.poki.apple-knight-golf.linyaps_28.3.3.2_x86_64_binary.layer ``` ll-pkg-name.csv + ``` org.qbittorrent.qBittorrent com.poki.apple-knight-golf.linyaps ``` ll-pkg-version.csv + ``` 4.6.7.22 28.3.3.2 @@ -50,19 +55,25 @@ ll-pkg-version.csv 5. `linyaps-auto-uninstall-release.sh`, 玲珑应用批量卸载工具 ## Next Linyaps Testing Toolchains运用实操 + 在介绍完总体功能、代码逻辑后, 我们基于 `deepin 23` 演示如何通过 `玲珑应用自动化测试套件` 完成对前面课时产出的玲珑应用安装包 `binary.layer` 进行批量测试 ### 环境预备 + 在开始使用测试套件前,你需要确保当前环境满足以下条件 + 1. 本次实操中所使用的自助兼容性测试套件部分功能需要使用 `Linux x11` 窗口管理工具,因此在使用前需要安装以下软件包: + ``` wmctrl x11-utils ``` + 2. 测试套件通过x11窗口管理工具来判断应用窗口启动状态,因此需要确保你的系统是 `x11` 环境而不是 `Wayland` 环境 3. `wmctrl` 与 `xwininfo` 组件可以正常生效,可以通过`xwininfo`查询窗口信息 4. 由于 `deepin 23` 下提供了兼容性测试结果截图功能, 因此需要安装相关的软件包: + ``` deepin-screen-recorder imagemagick-6.q16 ``` @@ -74,10 +85,11 @@ deepin-screen-recorder imagemagick-6.q16 1. 在上节实操课时中, 我们得到了 `qBittorrent--4.6.7` 的玲珑安装包 `org.qbittorrent.qBittorrent_4.6.7.22_x86_64_binary.layer`, 为了方便演示套件的批量支持能力, 我这里单独另找一个安装包 2. 现在我们有两款玲珑应用的安装包, 首先执行 `linyaps-auto-optimize.sh` 脚本来整理目录 -此脚本主要使用两个参数, 用于指向当前存放玲珑应用安装包 `binary.layer` 的目录 `$ll_origin_pool` 及 需要整理的终点目录 `$ll_stored_pool` + 此脚本主要使用两个参数, 用于指向当前存放玲珑应用安装包 `binary.layer` 的目录 `$ll_origin_pool` 及 需要整理的终点目录 `$ll_stored_pool` 3. 我在本地目录创建了两个独立目录 `ll-bins` `ll-pool` 用于指向 `$ll_origin_pool` 及 `$ll_stored_pool` - `ll-bins` 现在的目录结构: + `ll-bins` 现在的目录结构: + ``` ├── ll-bins │ ├── org.qbittorrent.qBittorrent_4.6.7.22_x86_64_binary.layer @@ -85,6 +97,7 @@ deepin-screen-recorder imagemagick-6.q16 ``` 4. 执行目录整理操作 + ```bash ziggy@linyaps23:/media/szbt/Data/linyaps-testing-toolchains$ ./linyaps-auto-optimize.sh ./ll-bins ./ll-pool ``` @@ -105,13 +118,15 @@ ll-pool/ 5. 目录整理后生成了 `ll-pkg-name.csv` `ll-pkg-version.csv` 两个用于记录应用信息的表格, 我们将两列内容合并为一个新表格 `ll-pkg-info.csv` : ll-pkg-info.csv + ``` org.qbittorrent.qBittorrent,4.6.7.22 com.poki.apple-knight-golf.linyaps,28.3.3.2 ``` 6. 根据此文件, 我们可以开始批量安装玲珑应用了 -此脚本主要使用一个参数, 用于指向当前整理完成的终点目录 `$ll_stored_pool`: + 此脚本主要使用一个参数, 用于指向当前整理完成的终点目录 `$ll_stored_pool`: + ```bash ziggy@linyaps23:/media/szbt/Data/linyaps-testing-toolchains$ linyaps-auto-install-release.sh ./ll-pool ``` @@ -119,11 +134,12 @@ ziggy@linyaps23:/media/szbt/Data/linyaps-testing-toolchains$ linyaps-auto-instal 7. 安装完玲珑应用后以及完成所有前置工作后, 我们可以开展测试流程了. 这里我们新建一个 `res` 目录, 用于存放图标、截图等测试结果资源 8. 在图形化界面打开终端, 执行截图脚本, 由于我们是 `deepin 23 x11` 环境并安装了必要的程序, 因此运行 `linyaps-auto-screenshot-deepin23.sh` -此脚本主要使用两个参数, 用于指向用于放置测试结果资源的目录 `$ll_res_pool` 以及 记录应用信息的表格 `$ll_pkgname_list`, 这里指的是我们上一环节得到的新表格 `ll-pkg-info.csv` : + 此脚本主要使用两个参数, 用于指向用于放置测试结果资源的目录 `$ll_res_pool` 以及 记录应用信息的表格 `$ll_pkgname_list`, 这里指的是我们上一环节得到的新表格 `ll-pkg-info.csv` : ```bash ziggy@linyaps23:/media/szbt/Data/linyaps-testing-toolchains$ ./linyaps-auto-screenshot-deepin23.sh ./res ./ll-pkg-info.csv ``` + \* 谨记, 此脚本必须在图形化终端下执行, 否则无法正常拉起进程 9. 在脚本启动后, 将该终端设置为最小化窗口保留在背景运行, 测试套件将会判断应用安装情况、desktop文件存在情况来 `启动` 和 `关闭` 应用窗口 @@ -139,9 +155,9 @@ ziggy@linyaps23:/media/szbt/Data/linyaps-testing-toolchains$ ./linyaps-auto-scre 11. 应用成功运行后, 将会依次完成截图、图标检测&获取操作 12. 在测试完成后, 可以在`res` 目录看到不同状态的表格及测试结果的材料, 由于这里的两款应用均通过了兼容性测试, 因此会在 `all-good.csv` 中记录 -否则会出现两种异常情况: -a. 超时未生成窗口的应用则会被写入`failed.csv`文件中,以判断为应用无法启动 -b. 玲珑应用目录内不包含图标文件,则会被写入`icons-missing.csv`文件中,不满足如意玲珑社区中对于图形化应用的规范 + 否则会出现两种异常情况: + a. 超时未生成窗口的应用则会被写入`failed.csv`文件中,以判断为应用无法启动 + b. 玲珑应用目录内不包含图标文件,则会被写入`icons-missing.csv`文件中,不满足如意玲珑社区中对于图形化应用的规范 ``` res/ @@ -165,4 +181,4 @@ res/ ![test-5](image/5-test-5.png) -至此, 我们成功通过玲珑应用自动化测试套件, 完成了针对历史课时中产出的玲珑应用的兼容性测试 \ No newline at end of file +至此, 我们成功通过玲珑应用自动化测试套件, 完成了针对历史课时中产出的玲珑应用的兼容性测试 diff --git a/docs/pages/guide/ll-builder/export.md b/docs/pages/guide/ll-builder/export.md index 7ca0d0e3b..6aec2466d 100644 --- a/docs/pages/guide/ll-builder/export.md +++ b/docs/pages/guide/ll-builder/export.md @@ -22,13 +22,13 @@ ll-builder export --help ## 主要选项 -* `-f, --file FILE`: 指定 `linglong.yaml` 配置文件的路径 (默认: `./linglong.yaml`),`linglong.yaml` 文件所在的目录为项目的工作目录。 -* `-o, --output FILE`: 指定输出文件的路径。对于 UAB,这通常是 `.uab` 文件的完整路径或文件名。对于 layer 这是输出文件名的前缀。 -* `-z, --compressor X`: 指定压缩算法。支持 `lz4` (UAB 默认), `lzma` (layer 默认), `zstd`。 -* `--icon FILE`: 为导出的 UAB 文件指定图标 (仅 UAB 模式,与 `--layer` 互斥)。 -* `--loader FILE`: 为导出的 UAB 文件指定自定义加载器 (仅 UAB 模式,与 `--layer` 互斥)。 -* `--layer`: **(已弃用)** 导出为 layer 文件格式,而不是 UAB (与 `--icon`, `--loader` 互斥)。 -* `--no-develop`: 在导出 layer 文件时,不包含 `develop` 模块。 +- `-f, --file FILE`: 指定 `linglong.yaml` 配置文件的路径 (默认: `./linglong.yaml`),`linglong.yaml` 文件所在的目录为项目的工作目录。 +- `-o, --output FILE`: 指定输出文件的路径。对于 UAB,这通常是 `.uab` 文件的完整路径或文件名。对于 layer 这是输出文件名的前缀。 +- `-z, --compressor X`: 指定压缩算法。支持 `lz4` (UAB 默认), `lzma` (layer 默认), `zstd`。 +- `--icon FILE`: 为导出的 UAB 文件指定图标 (仅 UAB 模式,与 `--layer` 互斥)。 +- `--loader FILE`: 为导出的 UAB 文件指定自定义加载器 (仅 UAB 模式,与 `--layer` 互斥)。 +- `--layer`: **(已弃用)** 导出为 layer 文件格式,而不是 UAB (与 `--icon`, `--loader` 互斥)。 +- `--no-develop`: 在导出 layer 文件时,不包含 `develop` 模块。 ## 导出 UAB 文件 (推荐) @@ -66,8 +66,8 @@ ll-builder export --layer -o my-app 导出 layer 文件会生成以下文件: -* `*_binary.layer`: 包含应用运行所需的基本文件。 -* `*_develop.layer`: (可选)包含用于开发和调试的文件。如果使用了 `--no-develop` 选项,则不会生成此文件。 +- `*_binary.layer`: 包含应用运行所需的基本文件。 +- `*_develop.layer`: (可选)包含用于开发和调试的文件。如果使用了 `--no-develop` 选项,则不会生成此文件。 ## 进阶说明 diff --git a/docs/pages/guide/ll-builder/linyaps_package_spec.md b/docs/pages/guide/ll-builder/linyaps_package_spec.md index 6944c6d58..9f3895ec8 100644 --- a/docs/pages/guide/ll-builder/linyaps_package_spec.md +++ b/docs/pages/guide/ll-builder/linyaps_package_spec.md @@ -5,7 +5,7 @@ 这些关键词与原文中的英语词汇的对应关系如下表所示: | 中文 | 英语 | -|------------|-------------| +| ---------- | ----------- | | **必须** | MUST | | **禁止** | MUST NOT | | **必要的** | REQUIRED | @@ -183,7 +183,6 @@ PKG_CONFIG ?= pkg-config - desktop文件对应图标 参见: - - 如果安装的图标为固定大小的版本,那么**推荐**使用png格式 至少**需要**安装一个48x48大小的png才能保证桌面环境中图标相关的基础功能正常 @@ -322,11 +321,8 @@ desktop文件的文件名中**不推荐**带有`-`,去掉.desktop后缀后, - **不推荐**填写[`Icon`字段][key-icon]时使用绝对路径 [key-tryexec]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-tryexec - [key-startupwmclass]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-startupwmclass - [key-exec]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-exec - [key-icon]: https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-icon #### DBus服务 @@ -417,11 +413,11 @@ Terminal=false 玲珑的环境最多有三部分组成,以在`x86_64`架构下编译`org.deepin.demo`为例,其头文件以及库文件默认搜索路径包含以下部分: -| **组成** | **包名** | **头文件** | **库文件** | -| ----------------------------------------------- | ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------ | -| base | org.deepin.base | /usr/include | /usr/lib
/usr/lib/x86_64-linux-gnu | -| runtime (可选) | org.deepin.runtime.dtk | /runtime/include | /runtime/lib
/runtime/lib/x86_64-linux-gnu | -| app | org.deepin.demo | /opt/apps/org.deepin.demo/files/include | /opt/apps/org.deepin.demo/files/lib
/opt/apps/org.deepin.demo/files/lib/x86_64-linux-gnu | +| **组成** | **包名** | **头文件** | **库文件** | +| -------------- | ---------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------- | +| base | org.deepin.base | /usr/include | /usr/lib
/usr/lib/x86_64-linux-gnu | +| runtime (可选) | org.deepin.runtime.dtk | /runtime/include | /runtime/lib
/runtime/lib/x86_64-linux-gnu | +| app | org.deepin.demo | /opt/apps/org.deepin.demo/files/include | /opt/apps/org.deepin.demo/files/lib
/opt/apps/org.deepin.demo/files/lib/x86_64-linux-gnu | 优先级按从上往下的顺序排列。如果一份头文件同时在`org.deepin.base`和`org.deepin.demo`中存在,使用时会优先匹配到`org.deepin.base`中的文件。库文件同理。 @@ -498,7 +494,7 @@ target_link_libraries(demo PRIVATE PackageName::Component) 通过源码引入依赖是一个**推荐的**做法,它能极大的保证构建流程的稳定以及可维护性。缺点是这可能会花费开发者不少时间编写yaml文件,因为依赖也许也会有自身的依赖。 -*如果开发者发现依赖复杂且重复被其他应用使用,那么应当考虑将依赖整合做成一个runtime类型的包。* +_如果开发者发现依赖复杂且重复被其他应用使用,那么应当考虑将依赖整合做成一个runtime类型的包。_ 当依赖是在玲珑环境下编译产生时,其配置文件通常是“可靠的”。编译安装后开发者可以直接在项目中使用。 @@ -585,14 +581,14 @@ deb的编译产物,安装前缀是`/usr`,`install_dep`脚本会自动处理其 玲珑应用**必须**选择一个base作为基础运行环境。可使用的base: -| **基础库** | **包名/版本** | -| ----------------------------------------------- | ------------------------------------------------ | +| **基础库** | **包名/版本** | +| ----------- | ------------------------ | | glibc(2.38) | org.deepin.base/23.1.0.0 | 如果需要额外使用基础环境以外的框架,**应当**使用合适的runtime。可使用的runtime: -| **框架** | **包名/版本** | -| ----------------------------------------------- | ------------------------------------------------ | +| **框架** | **包名/版本** | +| ------------------- | ------------------------------- | | QT(5.15) + DTK(5.6) | org.deepin.runtime.dtk/23.1.0.0 | 在使用base或runtime时,版本号**推荐**填写前三位,如 '23.1.0',便于后续接收更新。全量填写4位版本表示**禁止**base或runtime更新。 @@ -700,14 +696,10 @@ info.json是玲珑定义的应用描述文件。该文件由构建工具自动 ```json { "id": "org.deepin.demo", - "arch": [ - "x86_64" - ], + "arch": ["x86_64"], "base": "main:org.deepin.foundation/23.0.0/x86_64", "channel": "main", - "command": [ - "/opt/apps/org.deepin.demo/files/bin/demo" - ], + "command": ["/opt/apps/org.deepin.demo/files/bin/demo"], "description": "simple Qt demo.\n", "kind": "app", "module": "runtime", @@ -857,12 +849,12 @@ ExecStart = ll-cli run org.deepin.demo -- demo WantedBy=user-session.target ``` -与dbus service不同的是,安装到```$PREFIX/lib/systemd/user```下的文件会被自动拷贝到```$PREFIX/share/systemd/user```。 +与dbus service不同的是,安装到`$PREFIX/lib/systemd/user`下的文件会被自动拷贝到`$PREFIX/share/systemd/user`。 **路径对应关系:** -| **打包路径** | **安装路径** | -| ------------------------------------------------------------- | -------------------------------------------------------------- | +| **打包路径** | **安装路径** | +| ------------------------------------------------ | --------------------------------------------------- | | $PREFIX/lib/systemd/user/org.deepin.demo.service | $XDG_DATA_DIRS/systemd/user/org.deepin.demo.service | ##### icons 目录 diff --git a/docs/pages/guide/ll-builder/manifests.md b/docs/pages/guide/ll-builder/manifests.md index 911d023ba..ad8180059 100644 --- a/docs/pages/guide/ll-builder/manifests.md +++ b/docs/pages/guide/ll-builder/manifests.md @@ -27,11 +27,11 @@ SPDX-License-Identifier: LGPL-3.0-or-later `linglong.yaml` 文件结构遵循特定的规范。首先,需要在文件顶层声明配置文件的版本: ```yaml -version: '1' +version: "1" ``` -| 名称 | 描述 | 必填 | -| ------- | ------------------------ | ---- | +| 名称 | 描述 | 必填 | +| ------- | ------------------------------ | ---- | | version | 构建配置文件的版本,当前为 '1' | 是 | 接下来是主要的配置块。其中 `package`, `base`, `build` 是必须定义的。 @@ -49,18 +49,18 @@ package: description: | calculator for deepin os. architecture: amd64 # 可选 - channel: stable # 可选 + channel: stable # 可选 ``` -| 名称 | 描述 | 必填 | -| -------------- | -------------------------------------------------------- | ---- | -| id | 构建产物的唯一名称 (例如:`org.deepin.calculator`) | 是 | -| name | 构建产物的名称 (例如:`deepin-calculator`) | 是 | -| version | 构建产物的版本,建议四位数字 (例如:`5.7.21.0`) | 是 | -| kind | 构建产物的类型:`app` (应用)、`runtime` (运行时) | 是 | -| description | 构建产物的详细描述 | 是 | -| architecture | 构建产物的目标架构 (例如:`amd64`, `arm64`) | 否 | -| channel | 构建产物的通道 (例如:`stable`, `beta`) | 否 | +| 名称 | 描述 | 必填 | +| ------------ | -------------------------------------------------- | ---- | +| id | 构建产物的唯一名称 (例如:`org.deepin.calculator`) | 是 | +| name | 构建产物的名称 (例如:`deepin-calculator`) | 是 | +| version | 构建产物的版本,建议四位数字 (例如:`5.7.21.0`) | 是 | +| kind | 构建产物的类型:`app` (应用)、`runtime` (运行时) | 是 | +| description | 构建产物的详细描述 | 是 | +| architecture | 构建产物的目标架构 (例如:`amd64`, `arm64`) | 否 | +| channel | 构建产物的通道 (例如:`stable`, `beta`) | 否 | ### 启动命令 (`command`) @@ -72,8 +72,8 @@ command: # - --some-argument # 可以添加更多参数 ``` -| 名称 | 描述 | 必填 | -| ------- | -------------------------------------------------------------------- | ---- | +| 名称 | 描述 | 必填 | +| ------- | --------------------------------------------------------------------- | ---- | | command | 定义启动应用的可执行文件路径及其参数列表。对于 `kind: app` 通常需要。 | 否 | ### 基础环境 (`base`) @@ -84,9 +84,9 @@ command: base: org.deepin.base/23.1.0 ``` -| 名称 | 描述 | 必填 | -| ------- | ----------------------------------------- | ---- | -| base | base 的标识符,格式为 `id/version`。版本号支持三位模糊匹配。 | 是 | +| 名称 | 描述 | 必填 | +| ---- | ------------------------------------------------------------ | ---- | +| base | base 的标识符,格式为 `id/version`。版本号支持三位模糊匹配。 | 是 | ### 运行时(runtime) @@ -116,13 +116,13 @@ sources: name: deepin-calculator.git # 可选,指定下载后的目录名 ``` -| 名称 | 描述 | 必填 (单个source内) | -| ------- | -------------------------------------------------------------------- | ------------------- | -| kind | `git`,表示使用 git 工具下载。 | 是 | -| url | 源码仓库地址 | 是 | -| version | 源码仓库的分支或标签 | 否 (默认为主分支) | -| commit | 源码某次提交的 hash 值,用于精确检出 | 否 | -| name | 可选,指定源码下载后在 `linglong/sources` 目录下的子目录名。 | 否 | +| 名称 | 描述 | 必填 (单个source内) | +| ------- | ------------------------------------------------------------ | ------------------- | +| kind | `git`,表示使用 git 工具下载。 | 是 | +| url | 源码仓库地址 | 是 | +| version | 源码仓库的分支或标签 | 否 (默认为主分支) | +| commit | 源码某次提交的 hash 值,用于精确检出 | 否 | +| name | 可选,指定源码下载后在 `linglong/sources` 目录下的子目录名。 | 否 | #### file 类型 @@ -134,12 +134,12 @@ sources: name: my-data.dat # 可选,指定下载后的文件名 ``` -| 名称 | 描述 | 必填 (单个source内) | -| ------ | -------------------------------------------------------------------- | ------------------- | -| kind | `file`,表示直接下载文件。 | 是 | -| url | 文件下载地址 | 是 | -| digest | 可选,文件的 sha256 哈希值,用于校验。 | 否 | -| name | 可选,指定下载后在 `linglong/sources` 目录下的文件名。 | 否 | +| 名称 | 描述 | 必填 (单个source内) | +| ------ | ------------------------------------------------------ | ------------------- | +| kind | `file`,表示直接下载文件。 | 是 | +| url | 文件下载地址 | 是 | +| digest | 可选,文件的 sha256 哈希值,用于校验。 | 否 | +| name | 可选,指定下载后在 `linglong/sources` 目录下的文件名。 | 否 | #### archive 类型 @@ -151,12 +151,12 @@ sources: name: deepin-calculator-6.5.4 # 可选,指定解压后的目录名 ``` -| 名称 | 描述 | 必填 (单个source内) | -| ------ | -------------------------------------------------------------------- | ------------------- | -| kind | `archive`,下载压缩包并自动解压。支持常见的压缩格式。 | 是 | -| url | 压缩包下载地址 | 是 | -| digest | 可选,压缩包文件的 sha256 哈希值,用于校验。 | 否 | -| name | 可选,指定解压后在 `linglong/sources` 目录下的目录名。 | 否 | +| 名称 | 描述 | 必填 (单个source内) | +| ------ | ------------------------------------------------------ | ------------------- | +| kind | `archive`,下载压缩包并自动解压。支持常见的压缩格式。 | 是 | +| url | 压缩包下载地址 | 是 | +| digest | 可选,压缩包文件的 sha256 哈希值,用于校验。 | 否 | +| name | 可选,指定解压后在 `linglong/sources` 目录下的目录名。 | 否 | #### dsc 类型 @@ -168,12 +168,12 @@ sources: name: deepin-calculator-dsc # 可选,指定下载和解压后的目录名 ``` -| 名称 | 描述 | 必填 (单个source内) | -| ------ | -------------------------------------------------------------------- | ------------------- | -| kind | `dsc`,处理 Debian 源码包描述文件及其关联文件。 | 是 | -| url | `.dsc` 文件下载地址 | 是 | -| digest | 可选,`.dsc` 文件的 sha256 哈希值,用于校验。 | 否 | -| name | 可选,指定下载和解压后在 `linglong/sources` 目录下的目录名。 | 否 | +| 名称 | 描述 | 必填 (单个source内) | +| ------ | ------------------------------------------------------------ | ------------------- | +| kind | `dsc`,处理 Debian 源码包描述文件及其关联文件。 | 是 | +| url | `.dsc` 文件下载地址 | 是 | +| digest | 可选,`.dsc` 文件的 sha256 哈希值,用于校验。 | 否 | +| name | 可选,指定下载和解压后在 `linglong/sources` 目录下的目录名。 | 否 | ### 导出裁剪规则 (`exclude`/`include`) @@ -188,9 +188,9 @@ include: - /usr/share/locale/zh_CN.UTF-8 # 配合exclude实现仅导出一个文件夹下的某些文件 ``` -| 名称 | 描述 | -| ------- | ----------------------------------------------------------------- | -| exclude | 容器内的绝对路径,可以为文件或文件夹,用于排除。 | +| 名称 | 描述 | +| ------- | ------------------------------------------------------------------- | +| exclude | 容器内的绝对路径,可以为文件或文件夹,用于排除。 | | include | 容器内的绝对路径,需要强制包含进 UAB 包的文件(即使父目录被排除)。 | ### 构建规则 (`build`) @@ -206,9 +206,9 @@ build: | make install ``` -| 名称 | 描述 | 必填 | -| ----- | -------------------------------------------------------------------- | ---- | -| build | 构建阶段执行的 shell 脚本。脚本在容器构建环境内执行。 | 是 | +| 名称 | 描述 | 必填 | +| ----- | ----------------------------------------------------- | ---- | +| build | 构建阶段执行的 shell 脚本。脚本在容器构建环境内执行。 | 是 | ### 构建扩展 (`buildext`) @@ -226,12 +226,12 @@ buildext: - libglib2.0-0 ``` -| 名称 | 描述 | 必填 | -| ----------- | ------------------------------------------------------------------ | ---- | -| buildext | 构建扩展配置的容器块。 | 否 | -| apt | 使用 apt 包管理器的扩展配置。 | 否 | +| 名称 | 描述 | 必填 | +| ------------- | ------------------------------------------------------------------ | ---- | +| buildext | 构建扩展配置的容器块。 | 否 | +| apt | 使用 apt 包管理器的扩展配置。 | 否 | | build_depends | 一个字符串列表,列出了构建时需要的包,这些包不会进入最终产物。 | 否 | -| depends | 一个字符串列表,列出了运行时需要的包,这些包会被包含在最终产物中。 | 否 | +| depends | 一个字符串列表,列出了运行时需要的包,这些包会被包含在最终产物中。 | 否 | ### 模块 (`modules`) @@ -253,11 +253,11 @@ modules: - share/my-app/optional-data/ ``` -| 名称 | 描述 | 必填 | -| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| modules | 定义应用模块拆分的规则列表。 | 否 | -| name | 模块的名称。每个模块都需要一个唯一的名称。 | 是 (在每个模块项内) | -| files | 一个字符串列表,列出了属于该模块的文件或目录。路径是相对于 `${PREFIX}` 的路径。 | 是 (在每个模块项内) | +| 名称 | 描述 | 必填 | +| ------- | ------------------------------------------------------------------------------- | ------------------- | +| modules | 定义应用模块拆分的规则列表。 | 否 | +| name | 模块的名称。每个模块都需要一个唯一的名称。 | 是 (在每个模块项内) | +| files | 一个字符串列表,列出了属于该模块的文件或目录。路径是相对于 `${PREFIX}` 的路径。 | 是 (在每个模块项内) | **注意:** 所有安装到 `${PREFIX}` 下的文件都会被分配到一个模块中。未定义 `modules` 时,构建系统会自动生成默认的 `binary` 和 `develop` 模块。 @@ -265,10 +265,10 @@ modules: 描述构建过程走可以使用的变量。 -| 名称 | 描述 | -| ------- | ------------------------------------------------------------------------------------------------------ | +| 名称 | 描述 | +| ------- | ------------------------------------------------------------------------------------ | | PREFIX | build 字段下使用的环境变量;提供构建时的安装路径,如 /opt/apps/org.deepin.calculator | -| TRIPLET | build 字段下使用的环境变量;提供包含架构信息的三元组,如 x86_64-linux-gnu | +| TRIPLET | build 字段下使用的环境变量;提供包含架构信息的三元组,如 x86_64-linux-gnu | ## 完整示例 @@ -277,7 +277,7 @@ modules: #### 计算器 ```yaml -version: '1' +version: "1" package: id: org.deepin.calculator @@ -361,4 +361,3 @@ ll-builder build --skip-fetch-source ``` 在根文件系统基础上添加 Qt 等基础环境。 - diff --git a/docs/pages/guide/ll-cli/exec.md b/docs/pages/guide/ll-cli/exec.md index 4ba702e09..320d5116d 100644 --- a/docs/pages/guide/ll-cli/exec.md +++ b/docs/pages/guide/ll-cli/exec.md @@ -40,7 +40,6 @@ Options: 1. 使用 `ll-cli ps` 获取正在运行的容器ID: - ```bash App ContainerID Pid main:org.dde.calendar/5.14.5.0/x86_64 c3b5ce363172 539537 diff --git a/docs/pages/guide/ll-pica/convert.md b/docs/pages/guide/ll-pica/convert.md index 4d7e30db3..6d34ebaa1 100644 --- a/docs/pages/guide/ll-pica/convert.md +++ b/docs/pages/guide/ll-pica/convert.md @@ -31,7 +31,7 @@ Global Flags: -V, --verbose verbose output ``` -在执行 `ll-pica init -w w --pi com.baidu.baidunetdisk --pn com.baidu.baidunetdisk -t repo` 命令后,我们仅需要执行 `ll-pica convert -w w -b --exportFile` 命令来转换出玲珑应用,这里会使用 `apt download` 命令去下载包名为 `com.baidu.baidunetdisk` 的 deb 包。 +在执行 `ll-pica init -w w --pi com.baidu.baidunetdisk --pn com.baidu.baidunetdisk -t repo` 命令后,我们仅需要执行 `ll-pica convert -w w -b --exportFile` 命令来转换出玲珑应用,这里会使用 `apt download` 命令去下载包名为 `com.baidu.baidunetdisk` 的 deb 包。 :::tip 这里使用 apt download 命令下载 deb 包,可能由于 deb 包过大而下载或者无法获取链接导致,失败推荐使用下面的命令。 diff --git a/docs/pages/guide/ll-pica/manifests.md b/docs/pages/guide/ll-pica/manifests.md index aafd77480..58ea3044a 100644 --- a/docs/pages/guide/ll-pica/manifests.md +++ b/docs/pages/guide/ll-pica/manifests.md @@ -33,7 +33,7 @@ runtime: | -------------- | ----------------------------------------------- | | runtime | 运行时(runtime) | | version | 运行时(runtime)版本,三位数可以模糊匹配第四位 | -| base_version | base 的版本号, 三位数可以模糊匹配第四位 | +| base_version | base 的版本号, 三位数可以模糊匹配第四位 | | source | 获取 deb 包依赖时使用的源 | | distro_version | 发行版的代号 | | arch | 获取 deb 包需要的架构 | diff --git a/docs/pages/guide/start/install.md b/docs/pages/guide/start/install.md index 9b2ecc049..b0057a10c 100644 --- a/docs/pages/guide/start/install.md +++ b/docs/pages/guide/start/install.md @@ -16,17 +16,17 @@ SPDX-License-Identifier: LGPL-3.0-or-later ### release 仓库 - 基于最新tag自动构建 +基于最新tag自动构建 - 1. 仓库地址 - 2. 构建地址 +1. 仓库地址 +2. 构建地址 ### latest 仓库 - 基于最新提交自动构建 +基于最新提交自动构建 - 1. 仓库地址 - 2. 构建地址 +1. 仓库地址 +2. 构建地址 :::tip diff --git a/docs/pages/guide/start/whatis.md b/docs/pages/guide/start/whatis.md index ce41f5b41..ee44d7a5a 100644 --- a/docs/pages/guide/start/whatis.md +++ b/docs/pages/guide/start/whatis.md @@ -25,30 +25,30 @@ SPDX-License-Identifier: LGPL-3.0-or-later ## 对比 -| 特性 | 如意玲珑 | Flatpak | Snap | AppImage | -| ------------------------- | ------------------------------- | ------------- | ---------------- | --------------------------------------- | -| 打包桌面应用 | ✔ | ✔ | ✔ | ✔ | -| 打包终端应用 | ✔ | ✔ | ✔ | ✔ | -| 处理服务器应用 | ✔ | ✘ | ✔ | ✘ | -| 打包系统服务(root 权限) | ✘ | ✘ | ✔ | ✘ | -| 主题功能正常 | ✔ | ✔ | ✔ | ✔ | -| 提供库托管服务 | ✔ | ✘ | ✘ | ✘ | -| 库/依赖来源 | 包自身携带 | | | | -| 宿主系统 | 包自身携带 | | | | -| SDK | 包自身携带 | | | | -| Snap Base | | | | | -| 商业支持 | ✔ | ✘ | ✔ | ✘ | -| 应用商店数量 | 预计 3000+ | 1400+ | 6600+ | 1300+ | -| 开发工具支持 | | GNOME Builder | electron-builder | | +| 特性 | 如意玲珑 | Flatpak | Snap | AppImage | +| ------------------------- | ------------------------------- | ------------- | ---------------- | -------------------------------------- | +| 打包桌面应用 | ✔ | ✔ | ✔ | ✔ | +| 打包终端应用 | ✔ | ✔ | ✔ | ✔ | +| 处理服务器应用 | ✔ | ✘ | ✔ | ✘ | +| 打包系统服务(root 权限) | ✘ | ✘ | ✔ | ✘ | +| 主题功能正常 | ✔ | ✔ | ✔ | ✔ | +| 提供库托管服务 | ✔ | ✘ | ✘ | ✘ | +| 库/依赖来源 | 包自身携带 | | | | +| 宿主系统 | 包自身携带 | | | | +| SDK | 包自身携带 | | | | +| Snap Base | | | | | +| 商业支持 | ✔ | ✘ | ✔ | ✘ | +| 应用商店数量 | 预计 3000+ | 1400+ | 6600+ | 1300+ | +| 开发工具支持 | | GNOME Builder | electron-builder | | | 容器支持 | ✔ | ✔ | ✔ | ◐ (官方不提供,技术上可行) | -| rootless 容器 | ✔ | ✘ | ✘ | ✘ | -| 不安装运行 | ✔ (提供 Bundle 模式) | ✘ | ✘ | ✔ | -| 不解压运行 | ✔ (提供 Bundle 模式) | ✘ | ✔ | ✔ | -| 自分发/绿色格式分发 | ◐ (技术可行,但是系统做限制) | ✘ | ✘ | ✔ | -| 支持 Wine 应用运行 | ◐   (适配中) | ◐ (理论可行 | ◐ (理论可行) | ◐ (使用 LD 修改 open 调用,兼容性差) | -| 离线环境支持 | ✔ | ✔ | ✔ | ✔ | +| rootless 容器 | ✔ | ✘ | ✘ | ✘ | +| 不安装运行 | ✔ (提供 Bundle 模式) | ✘ | ✘ | ✔ | +| 不解压运行 | ✔ (提供 Bundle 模式) | ✘ | ✔ | ✔ | +| 自分发/绿色格式分发 | ◐ (技术可行,但是系统做限制) | ✘ | ✘ | ✔ | +| 支持 Wine 应用运行 | ◐   (适配中) | ◐ (理论可行 | ◐ (理论可行) | ◐ (使用 LD 修改 open 调用,兼容性差) | +| 离线环境支持 | ✔ | ✔ | ✔ | ✔ | | 权限管理 | ✔ | ✔ | ✔ | ✘ | -| 中心仓库 | mirror-repo-linglong.deepin.com | FlatHub | Snap Store | AppImageHub | -| 多版本共存 | ✔ | ✔ | ✔ | ✔ | -| 点对点分发 | ✔ | ✔ | ✔ | ✔ | -| 应用升级 | 仓库升级 | 仓库升级 | 仓库升级 | 官方工具升级 | +| 中心仓库 | mirror-repo-linglong.deepin.com | FlatHub | Snap Store | AppImageHub | +| 多版本共存 | ✔ | ✔ | ✔ | ✔ | +| 点对点分发 | ✔ | ✔ | ✔ | ✔ | +| 应用升级 | 仓库升级 | 仓库升级 | 仓库升级 | 官方工具升级 | diff --git a/docs/ref.md b/docs/ref.md index de29702b3..d45c70b73 100644 --- a/docs/ref.md +++ b/docs/ref.md @@ -30,8 +30,8 @@ org.deepin.calculator 为 ID,1.2.2 为版本,x86_64 为架构。 | 标识 | 取值范围 | | ------- | ------------------------------------------------------------------------------------------ | -| repo | 小写字母 + 下划线 | -| channel | 小写字母 + 下划线 | +| repo | 小写字母 + 下划线 | +| channel | 小写字母 + 下划线 | | id | 英文倒置域名 | | version | 4 位数字,使用`.`分隔。不足 4 位的补 0,超过 4 位的将后续的数字字符串拼接到第 4 位数字中。 | | arch | 架构描述字符串,目前支持 x86_64/arm/loongarch | diff --git a/docs/rootfs.md b/docs/rootfs.md index 7638e927d..7b5374572 100644 --- a/docs/rootfs.md +++ b/docs/rootfs.md @@ -77,6 +77,6 @@ The example of annotations is: } ``` -The ll-box support two method to build rootfs, use native ro bind mount or with overlayfs. +The ll-box support two method to build rootfs, use native ro bind mount or with overlayfs. `container_root_path` is the work directory of ll-box. diff --git a/docs/test/unit-testing.md b/docs/test/unit-testing.md index b0846dfa3..c323d1ab3 100644 --- a/docs/test/unit-testing.md +++ b/docs/test/unit-testing.md @@ -6,6 +6,6 @@ Seem some test is hard to run in ci envionment, we disable it by default. Here are some envionment variables to control if test run, all of them are empty by default. -|name| vaule| -|-|-| -|LINGLONG_TEST_ALL|If set, will run all unit testing. | \ No newline at end of file +| name | vaule | +| ----------------- | ---------------------------------- | +| LINGLONG_TEST_ALL | If set, will run all unit testing. | diff --git a/docs/uab-build.md b/docs/uab-build.md index 9e64ddbb3..0e7042236 100644 --- a/docs/uab-build.md +++ b/docs/uab-build.md @@ -13,7 +13,7 @@ loader和extra-files.txt loader的编写参考: -``` bash +```bash #!/bin/env sh APPID=org.deepin.demo ./ll-box $APPID $PWD /opt/apps/$APPID/files/bin/demo diff --git a/libs/linglong/src/linglong/package/layer_packager.cpp b/libs/linglong/src/linglong/package/layer_packager.cpp index 041f3f244..530ee99a5 100644 --- a/libs/linglong/src/linglong/package/layer_packager.cpp +++ b/libs/linglong/src/linglong/package/layer_packager.cpp @@ -13,8 +13,8 @@ #include #include -#include #include +#include #include @@ -133,17 +133,16 @@ utils::error::Result LayerPackager::unpack(LayerFile &file) std::ifstream f(fdPath.toStdString()); if (!f.is_open()) { // 如果不可读,通过文件描述符复制到工作目录 - fdPath = this->workDir.absoluteFilePath(QUuid::createUuid().toString(QUuid::Id128)+".erofs"); + fdPath = + this->workDir.absoluteFilePath(QUuid::createUuid().toString(QUuid::Id128) + ".erofs"); // 如果保存失败,返回错误 if (!file.saveTo(fdPath)) { return LINGLONG_ERR("Failed to save layer file to work directory"); } } - auto ret = - utils::command::Exec("erofsfuse", - { QString("--offset=%1").arg(*offset), - fdPath, - unpackDir.absolutePath() }); + auto ret = utils::command::Exec( + "erofsfuse", + { QString("--offset=%1").arg(*offset), fdPath, unpackDir.absolutePath() }); if (!ret) { return LINGLONG_ERR(ret); } diff --git a/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp b/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp index 3ebecdbcc..e9ac3abe4 100644 --- a/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp +++ b/libs/linglong/tests/ll-tests/src/linglong/repo/config_test.cpp @@ -18,7 +18,7 @@ TEST(Repo, GetRepoMinPriority) { RepoConfigV2 cfg; - cfg.repos = { { std::nullopt,false, "repo1", 100, "http://example.com/repo1" }}; + cfg.repos = { { std::nullopt, false, "repo1", 100, "http://example.com/repo1" } }; EXPECT_EQ(getRepoMinPriority(cfg), 100); cfg.repos = { { std::nullopt, false, "repo1", 200, "http://example.com/repo1" }, @@ -54,7 +54,7 @@ TEST(Repo, GetRepoMaxPriority) { std::nullopt, false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 300); - cfg.repos = { { "alias1",false, "repo1", 200, "http://example.com/repo1" }, + cfg.repos = { { "alias1", false, "repo1", 200, "http://example.com/repo1" }, { "alias2", false, "repo2", 0, "http://example.com/repo2" }, { "alias3", false, "repo3", 300, "http://example.com/repo3" } }; EXPECT_EQ(getRepoMaxPriority(cfg), 300); diff --git a/libs/ocppi/include/ocppi/runtime/Signal.hpp b/libs/ocppi/include/ocppi/runtime/Signal.hpp index ef3a3564e..20c47c1bf 100644 --- a/libs/ocppi/include/ocppi/runtime/Signal.hpp +++ b/libs/ocppi/include/ocppi/runtime/Signal.hpp @@ -2,7 +2,8 @@ #include -namespace ocppi::runtime { +namespace ocppi::runtime +{ using Signal = std::string; } diff --git a/linglong.yaml b/linglong.yaml index bcf9a4cb4..cd644dce5 100644 --- a/linglong.yaml +++ b/linglong.yaml @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: LGPL-3.0-or-later -version: "1" +version: '1' package: id: cn.org.linyaps.builder.utils name: ll-builder-utils @@ -53,4 +53,23 @@ build: | install /usr/local/bin/mkfs.erofs $PREFIX/bin/ buildext: apt: - build_depends: [patch, meson, libtool, pkg-config, uuid-dev, libdeflate-dev, libzstd-dev, nlohmann-json3-dev, libyaml-cpp-dev, liblz4-dev, liblzma-dev, libselinux1-dev, libpcre2-dev, libelf-dev, libcap-dev, libcli11-dev, libgtest-dev] + build_depends: + [ + patch, + meson, + libtool, + pkg-config, + uuid-dev, + libdeflate-dev, + libzstd-dev, + nlohmann-json3-dev, + libyaml-cpp-dev, + liblz4-dev, + liblzma-dev, + libselinux1-dev, + libpcre2-dev, + libelf-dev, + libcap-dev, + libcli11-dev, + libgtest-dev, + ] diff --git a/misc/lib/linglong/container/README.md b/misc/lib/linglong/container/README.md index 843a0089c..0fd4f3dc9 100644 --- a/misc/lib/linglong/container/README.md +++ b/misc/lib/linglong/container/README.md @@ -47,15 +47,14 @@ can be found at [/api/schema/v1.yaml]. [/api/schema/v1.yaml]: ../../../../api/schema/v1.yaml - ## Application-specific patches Patches in application ID-named directories are application-specific and apply after global patches ## Examples -- Global patch: `99-dump-conf` -- App patch: `com.example.app/99-test.json` +- Global patch: `99-dump-conf` +- App patch: `com.example.app/99-test.json` com.example.app/99-test.json: @@ -70,9 +69,7 @@ com.example.app/99-test.json: "destination": "/opt/host-apps/", "type": "bind", "source": "/opt/apps", - "options": [ - "rbind" - ] + "options": ["rbind"] } } ] @@ -84,7 +81,7 @@ this patch will applied after 99-dump-conf. 99-dump-conf can write following content to print the container's configuration: -``` bash +```bash #!/bin/sh content=$(cat -) diff --git a/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp b/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp index dc121a4a9..2a5fcef90 100644 --- a/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp +++ b/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp @@ -26,35 +26,33 @@ ** ****************************************************************************/ +#include #include #include #include +#include #include #include #include #include +#include #include #include #include -#include - -#include -#include #include #include -#define PROGRAMNAME "qdbusxml2cpp" -#define PROGRAMVERSION "0.8" +#define PROGRAMNAME "qdbusxml2cpp" +#define PROGRAMVERSION "0.8" #define PROGRAMCOPYRIGHT "Copyright (C) 2020 The Qt Company Ltd." -#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" +#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" // https://github.com/AD-Vega/qarv/issues/22#issuecomment-1012011346 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) -namespace Qt -{ - static auto endl = ::endl; +namespace Qt { +static auto endl = ::endl; } #endif @@ -70,23 +68,21 @@ static QString commandLine; static QStringList includes; static QStringList wantedInterfaces; -static const char includeList[] = - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n"; - -static const char forwardDeclarations[] = - "QT_BEGIN_NAMESPACE\n" - "class QByteArray;\n" - "template class QList;\n" - "template class QMap;\n" - "class QString;\n" - "class QStringList;\n" - "class QVariant;\n" - "QT_END_NAMESPACE\n"; +static const char includeList[] = "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n"; + +static const char forwardDeclarations[] = "QT_BEGIN_NAMESPACE\n" + "class QByteArray;\n" + "template class QList;\n" + "template class QMap;\n" + "class QString;\n" + "class QStringList;\n" + "class QVariant;\n" + "QT_END_NAMESPACE\n"; static QDBusIntrospection::Interfaces readInput() { @@ -101,13 +97,12 @@ static QDBusIntrospection::Interfaces readInput() // check if the input is already XML data = data.trimmed(); - if (data.startsWith("= 0) - annotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); + annotationName += + QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); QString qttype = annotations.value(annotationName); if (!qttype.isEmpty()) return std::move(qttype).toLatin1(); QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); if (paramId >= 0) - oldAnnotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); + oldAnnotationName += + QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); qttype = annotations.value(oldAnnotationName); if (qttype.isEmpty()) { if (!isSignal || qstrcmp(direction, "Out") == 0) { - fprintf(stderr, "%s: Got unknown type `%s' processing '%s'\n", - PROGRAMNAME, qPrintable(signature), qPrintable(inputFile)); - fprintf(stderr, "You should add \"/> to the XML description\n", + fprintf(stderr, + "%s: Got unknown type `%s' processing '%s'\n", + PROGRAMNAME, + qPrintable(signature), + qPrintable(inputFile)); + fprintf(stderr, + "You should add \"/> to the XML " + "description\n", qPrintable(annotationName)); } @@ -246,9 +252,12 @@ static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection: exit(1); } - fprintf(stderr, "%s: Warning: deprecated annotation '%s' found while processing '%s'; " - "suggest updating to '%s'\n", - PROGRAMNAME, qPrintable(oldAnnotationName), qPrintable(inputFile), + fprintf(stderr, + "%s: Warning: deprecated annotation '%s' found while processing '%s'; " + "suggest updating to '%s'\n", + PROGRAMNAME, + qPrintable(oldAnnotationName), + qPrintable(inputFile), qPrintable(annotationName)); return std::move(qttype).toLatin1(); } @@ -274,12 +283,12 @@ static QString constRefArg(const QByteArray &arg) if (!arg.startsWith('Q')) return QLatin1String(arg + ' '); else - return QString( QLatin1String("const %1 &") ).arg( QLatin1String(arg) ); + return QString(QLatin1String("const %1 &")).arg(QLatin1String(arg)); } -static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = - QDBusIntrospection::Arguments()) +static QStringList +makeArgNames(const QDBusIntrospection::Arguments &inputArgs, + const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) { QStringList retval; const int numInputArgs = inputArgs.count(); @@ -289,7 +298,7 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, const QDBusIntrospection::Argument &arg = inputArgs.at(i); QString name = arg.name; if (name.isEmpty()) - name = QString( QLatin1String("in%1") ).arg(i); + name = QString(QLatin1String("in%1")).arg(i); else name.replace(QLatin1Char('-'), QLatin1Char('_')); while (retval.contains(name)) @@ -300,7 +309,7 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, const QDBusIntrospection::Argument &arg = outputArgs.at(i); QString name = arg.name; if (name.isEmpty()) - name = QString( QLatin1String("out%1") ).arg(i); + name = QString(QLatin1String("out%1")).arg(i); else name.replace(QLatin1Char('-'), QLatin1Char('_')); while (retval.contains(name)) @@ -310,10 +319,12 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, return retval; } -static void writeArgList(QTextStream &ts, const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) +static void +writeArgList(QTextStream &ts, + const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &inputArgs, + const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) { // input args: bool first = true; @@ -337,21 +348,22 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames, if (!first) ts << ", "; - ts << nonConstRefArg(qtTypeName(arg.type, annotations, i, "Out")) - << argNames.at(argPos++); + ts << nonConstRefArg(qtTypeName(arg.type, annotations, i, "Out")) << argNames.at(argPos++); first = false; } } -static void writeSignalArgList(QTextStream &ts, const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &outputArgs) +static void writeSignalArgList(QTextStream &ts, + const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &outputArgs) { bool first = true; int argPos = 0; for (int i = 0; i < outputArgs.count(); ++i) { const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString type = constRefArg(qtTypeName(arg.type, annotations, i, "Out", true /* isSignal */)); + QString type = + constRefArg(qtTypeName(arg.type, annotations, i, "Out", true /* isSignal */)); if (!first) ts << ", "; @@ -362,36 +374,42 @@ static void writeSignalArgList(QTextStream &ts, const QStringList &argNames, static QString propertyGetter(const QDBusIntrospection::Property &property) { - QString getter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyGetter")); + QString getter = + property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyGetter")); if (!getter.isEmpty()) return getter; getter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertyGetter")); if (!getter.isEmpty()) { - fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found" + fprintf(stderr, + "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found" " while processing '%s';" " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n", - PROGRAMNAME, qPrintable(inputFile)); + PROGRAMNAME, + qPrintable(inputFile)); return getter; } - getter = property.name; + getter = property.name; getter[0] = getter[0].toLower(); return getter; } static QString propertySetter(const QDBusIntrospection::Property &property) { - QString setter = property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertySetter")); + QString setter = + property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertySetter")); if (!setter.isEmpty()) return setter; setter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertySetter")); if (!setter.isEmpty()) { - fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found" + fprintf(stderr, + "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found" " while processing '%s';" " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n", - PROGRAMNAME, qPrintable(inputFile)); + PROGRAMNAME, + qPrintable(inputFile)); return setter; } @@ -415,12 +433,14 @@ static QString stringify(const QString &data) int i; for (i = 0; i < data.length(); ++i) { retval += QLatin1Char('\"'); - for ( ; i < data.length() && data[i] != QLatin1Char('\n') && data[i] != QLatin1Char('\r'); ++i) + for (; i < data.length() && data[i] != QLatin1Char('\n') && data[i] != QLatin1Char('\r'); + ++i) if (data[i] == QLatin1Char('\"')) retval += QLatin1String("\\\""); else retval += data[i]; - if (i+1 < data.length() && data[i] == QLatin1Char('\r') && data[i+1] == QLatin1Char('\n')) + if (i + 1 < data.length() && data[i] == QLatin1Char('\r') + && data[i + 1] == QLatin1Char('\n')) i++; retval += QLatin1String("\\n\"\n"); } @@ -441,8 +461,11 @@ static bool openFile(const QString &fileName, QFile &file) } if (!isOk) - fprintf(stderr, "%s: Unable to open '%s': %s\n", - PROGRAMNAME, qPrintable(fileName), qPrintable(file.errorString())); + fprintf(stderr, + "%s: Unable to open '%s': %s\n", + PROGRAMNAME, + qPrintable(fileName), + qPrintable(file.errorString())); return isOk; } @@ -463,13 +486,11 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf writeHeader(cs, false); // include guards: - hs << "#pragma once" << Qt::endl - << Qt::endl; + hs << "#pragma once" << Qt::endl << Qt::endl; // include our stuff: hs << "#include " << Qt::endl - << includeList - << "#include " << Qt::endl; + << includeList << "#include " << Qt::endl; for (const QString &include : qAsConst(includes)) { hs << "#include \"" << include << "\"" << Qt::endl; @@ -509,12 +530,20 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // constructors/destructors: hs << "public:" << Qt::endl - << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl + << " " << className + << "(const QString &service, const QString &path, const QDBusConnection &connection, " + "QObject *parent = nullptr);" + << Qt::endl << Qt::endl << " ~" << className << "();" << Qt::endl << Qt::endl; - cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl + cs << className << "::" << className + << "(const QString &service, const QString &path, const QDBusConnection &connection, " + "QObject *parent)" + << Qt::endl + << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, " + "parent)" + << Qt::endl << "{" << Qt::endl << "}" << Qt::endl << Qt::endl @@ -546,13 +575,14 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // getter: if (property.access != QDBusIntrospection::Property::Write) { hs << " inline " << type << " " << getter << "() const" << Qt::endl - << " { return qvariant_cast< " << type << " >(property(\"" - << property.name << "\")); }" << Qt::endl; + << " { return qvariant_cast< " << type << " >(property(\"" << property.name + << "\")); }" << Qt::endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl + hs << " inline void " << setter << "(" << constRefArg(type) << "value)" + << Qt::endl << " { setProperty(\"" << property.name << "\", QVariant::fromValue(value)); }" << Qt::endl; } @@ -563,18 +593,23 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // methods: hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { - bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true"); + bool isDeprecated = + method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) + == QLatin1String("true"); bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); + method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", - PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), + fprintf(stderr, + "%s: warning while processing '%s': method %s in interface %s is marked " + "'no-reply' but has output arguments.\n", + PROGRAMNAME, + qPrintable(inputFile), + qPrintable(method.name), qPrintable(interface->name)); continue; } - hs << " inline virtual " - << (isDeprecated ? "Q_DECL_DEPRECATED " : ""); + hs << " inline virtual " << (isDeprecated ? "Q_DECL_DEPRECATED " : ""); if (isNoReply) { hs << "Q_NOREPLY void "; @@ -582,7 +617,8 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf hs << "QDBusPendingReply<"; for (int i = 0; i < method.outputArgs.count(); ++i) hs << (i > 0 ? ", " : "") - << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")); + << templateArg( + qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")); hs << "> "; } @@ -604,20 +640,20 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf if (isNoReply) hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; else - hs << " return asyncCallWithArgumentList(QStringLiteral(\"" - << method.name << "\"), argumentList);" << Qt::endl; + hs << " return asyncCallWithArgumentList(QStringLiteral(\"" << method.name + << "\"), argumentList);" << Qt::endl; // close the function: hs << " }" << Qt::endl; if (method.outputArgs.count() > 1) { // generate the old-form QDBusReply methods with multiple incoming parameters - hs << " inline " - << (isDeprecated ? "Q_DECL_DEPRECATED " : "") - << "QDBusReply<" - << templateArg(qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out")) << "> "; + hs << " inline " << (isDeprecated ? "Q_DECL_DEPRECATED " : "") << "QDBusReply<" + << templateArg( + qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out")) + << "> "; hs << method.name << "("; QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); @@ -636,16 +672,18 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; argPos++; - hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == " + hs << " if (reply.type() == QDBusMessage::ReplyMessage && " + "reply.arguments().count() == " << method.outputArgs.count() << ") {" << Qt::endl; // yes, starting from 1 for (int i = 1; i < method.outputArgs.count(); ++i) hs << " " << argNames.at(argPos++) << " = qdbus_cast<" - << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) + << templateArg( + qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) << ">(reply.arguments().at(" << i << "));" << Qt::endl; hs << " }" << Qt::endl << " return reply;" << Qt::endl @@ -658,8 +696,8 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == - QLatin1String("true")) + if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) + == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; @@ -671,15 +709,13 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } // close the class: - hs << "};" << Qt::endl - << Qt::endl; + hs << "};" << Qt::endl << Qt::endl; } if (!skipNamespaces) { QStringList last; QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin(); - do - { + do { QStringList current; QString name; if (it != interfaces.constEnd()) { @@ -698,13 +734,14 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // open current.arguments().count() - i namespaces for (int j = i; j < current.count(); ++j) - hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl; + hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" + << Qt::endl; // add this class: if (!name.isEmpty()) { hs << QString(current.count() * 2, QLatin1Char(' ')) - << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) - << " " << name << ";" << Qt::endl; + << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) << " " + << name << ";" << Qt::endl; } if (it == interfaces.constEnd()) @@ -716,8 +753,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl - << "#include \"" << mocName << "\"" << Qt::endl; + cs << Qt::endl << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); @@ -763,8 +799,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } else { includeGuard = QLatin1String("QDBUSXML2CPP_ADAPTOR"); } - includeGuard = QString(QLatin1String("%1")) - .arg(includeGuard); + includeGuard = QString(QLatin1String("%1")).arg(includeGuard); hs << "#ifndef " << includeGuard << Qt::endl << "#define " << includeGuard << Qt::endl << Qt::endl; @@ -786,9 +821,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte if (!headerName.isEmpty() && headerName != QLatin1String("-")) cs << "#include \"" << headerName << "\"" << Qt::endl; - cs << "#include " << Qt::endl - << includeList - << Qt::endl; + cs << "#include " << Qt::endl << includeList << Qt::endl; hs << forwardDeclarations; } else { hs << includeList; @@ -818,8 +851,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte << " Q_OBJECT" << Qt::endl << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl - << stringify(interface->introspection) - << " \"\")" << Qt::endl + << stringify(interface->introspection) << " \"\")" << Qt::endl << "public:" << Qt::endl << " " << className << "(" << parent << " *parent);" << Qt::endl << " virtual ~" << className << "();" << Qt::endl @@ -861,11 +893,11 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // getter: if (property.access != QDBusIntrospection::Property::Write) { hs << " " << type << " " << getter << "() const;" << Qt::endl; - cs << type << " " - << className << "::" << getter << "() const" << Qt::endl + cs << type << " " << className << "::" << getter << "() const" << Qt::endl << "{" << Qt::endl << " // get the value of property " << property.name << Qt::endl - << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl + << " return qvariant_cast< " << type << " >(parent()->property(\"" + << property.name << "\"));" << Qt::endl << "}" << Qt::endl << Qt::endl; } @@ -873,15 +905,15 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // setter if (property.access != QDBusIntrospection::Property::Read) { hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl + cs << "void " << className << "::" << setter << "(" << constRefType << "value)" + << Qt::endl << "{" << Qt::endl << " // set the value of property " << property.name << Qt::endl - << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; + << " parent()->setProperty(\"" << property.name + << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; - cs << "));" << Qt::endl - << "}" << Qt::endl - << Qt::endl; + cs << "));" << Qt::endl << "}" << Qt::endl << Qt::endl; } hs << Qt::endl; @@ -890,16 +922,21 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); + method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", - PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), qPrintable(interface->name)); + fprintf(stderr, + "%s: warning while processing '%s': method %s in interface %s is marked " + "'no-reply' but has output arguments.\n", + PROGRAMNAME, + qPrintable(inputFile), + qPrintable(method.name), + qPrintable(interface->name)); continue; } hs << " "; - if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == - QLatin1String("true")) + if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) + == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; QByteArray returnType; @@ -910,7 +947,8 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "void "; cs << "void "; } else { - returnType = qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out"); + returnType = + qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out"); hs << returnType << " "; cs << returnType << " "; } @@ -926,7 +964,8 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << ");" << Qt::endl; // finished for header cs << ")" << Qt::endl << "{" << Qt::endl - << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl; + << " // handle method call " << interface->name << "." << methodName(method) + << Qt::endl; // make the call bool usingInvokeMethod = false; @@ -945,19 +984,13 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte if (!method.outputArgs.isEmpty()) cs << ", Q_RETURN_ARG(" - << qtTypeName(method.outputArgs.at(0).type, method.annotations, - 0, "Out") - << ", " - << argNames.at(method.inputArgs.count()) - << ")"; + << qtTypeName(method.outputArgs.at(0).type, method.annotations, 0, "Out") + << ", " << argNames.at(method.inputArgs.count()) << ")"; for (int i = 0; i < method.inputArgs.count(); ++i) cs << ", Q_ARG(" - << qtTypeName(method.inputArgs.at(i).type, method.annotations, - i, "In") - << ", " - << argNames.at(i) - << ")"; + << qtTypeName(method.inputArgs.at(i).type, method.annotations, i, "In") + << ", " << argNames.at(i) << ")"; cs << ");" << Qt::endl; @@ -984,7 +1017,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte cs << (first ? "" : ", ") << argNames.at(argPos++); first = false; } - ++argPos; // skip retval, if any + ++argPos; // skip retval, if any for (int i = 1; i < method.outputArgs.count(); ++i) { cs << (first ? "" : ", ") << argNames.at(argPos++); first = false; @@ -992,15 +1025,14 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte cs << ");" << Qt::endl; } - cs << "}" << Qt::endl - << Qt::endl; + cs << "}" << Qt::endl << Qt::endl; } hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == - QLatin1String("true")) + if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) + == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; @@ -1012,8 +1044,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } // close the class: - hs << "};" << Qt::endl - << Qt::endl; + hs << "};" << Qt::endl << Qt::endl; } // close the include guard @@ -1021,8 +1052,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl - << "#include \"" << mocName << "\"" << Qt::endl; + cs << Qt::endl << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); @@ -1050,50 +1080,65 @@ int main(int argc, char **argv) QCommandLineParser parser; parser.setApplicationDescription(QLatin1String( - "Produces the C++ code to implement the interfaces defined in the input file.\n\n" - "If the file name given to the options -a and -p does not end in .cpp or .h, the\n" - "program will automatically append the suffixes and produce both files.\n" - "You can also use a colon (:) to separate the header name from the source file\n" - "name, as in '-a filename_p.h:filename.cpp'.\n\n" - "If you pass a dash (-) as the argument to either -p or -a, the output is written\n" - "to the standard output.")); + "Produces the C++ code to implement the interfaces defined in the input file.\n\n" + "If the file name given to the options -a and -p does not end in .cpp or .h, the\n" + "program will automatically append the suffixes and produce both files.\n" + "You can also use a colon (:) to separate the header name from the source file\n" + "name, as in '-a filename_p.h:filename.cpp'.\n\n" + "If you pass a dash (-) as the argument to either -p or -a, the output is written\n" + "to the standard output.")); parser.addHelpOption(); parser.addVersionOption(); - parser.addPositionalArgument(QStringLiteral("xml-or-xml-file"), QStringLiteral("XML file to use.")); - parser.addPositionalArgument(QStringLiteral("interfaces"), QStringLiteral("List of interfaces to use."), - QStringLiteral("[interfaces ...]")); - - QCommandLineOption adapterCodeOption(QStringList() << QStringLiteral("a") << QStringLiteral("adaptor"), - QStringLiteral("Write the adaptor code to "), QStringLiteral("filename")); + parser.addPositionalArgument(QStringLiteral("xml-or-xml-file"), + QStringLiteral("XML file to use.")); + parser.addPositionalArgument(QStringLiteral("interfaces"), + QStringLiteral("List of interfaces to use."), + QStringLiteral("[interfaces ...]")); + + QCommandLineOption adapterCodeOption(QStringList() + << QStringLiteral("a") << QStringLiteral("adaptor"), + QStringLiteral("Write the adaptor code to "), + QStringLiteral("filename")); parser.addOption(adapterCodeOption); - QCommandLineOption classNameOption(QStringList() << QStringLiteral("c") << QStringLiteral("classname"), - QStringLiteral("Use as the class name for the generated classes"), QStringLiteral("classname")); + QCommandLineOption classNameOption( + QStringList() << QStringLiteral("c") << QStringLiteral("classname"), + QStringLiteral("Use as the class name for the generated classes"), + QStringLiteral("classname")); parser.addOption(classNameOption); - QCommandLineOption addIncludeOption(QStringList() << QStringLiteral("i") << QStringLiteral("include"), - QStringLiteral("Add #include to the output"), QStringLiteral("filename")); + QCommandLineOption addIncludeOption(QStringList() + << QStringLiteral("i") << QStringLiteral("include"), + QStringLiteral("Add #include to the output"), + QStringLiteral("filename")); parser.addOption(addIncludeOption); - QCommandLineOption adapterParentOption(QStringLiteral("l"), - QStringLiteral("When generating an adaptor, use as the parent class"), QStringLiteral("classname")); + QCommandLineOption adapterParentOption( + QStringLiteral("l"), + QStringLiteral("When generating an adaptor, use as the parent class"), + QStringLiteral("classname")); parser.addOption(adapterParentOption); - QCommandLineOption mocIncludeOption(QStringList() << QStringLiteral("m") << QStringLiteral("moc"), - QStringLiteral("Generate #include \"filename.moc\" statements in the .cpp files")); + QCommandLineOption mocIncludeOption( + QStringList() << QStringLiteral("m") << QStringLiteral("moc"), + QStringLiteral("Generate #include \"filename.moc\" statements in the .cpp files")); parser.addOption(mocIncludeOption); - QCommandLineOption noNamespaceOption(QStringList() << QStringLiteral("N") << QStringLiteral("no-namespaces"), - QStringLiteral("Don't use namespaces")); + QCommandLineOption noNamespaceOption(QStringList() << QStringLiteral("N") + << QStringLiteral("no-namespaces"), + QStringLiteral("Don't use namespaces")); parser.addOption(noNamespaceOption); - QCommandLineOption proxyCodeOption(QStringList() << QStringLiteral("p") << QStringLiteral("proxy"), - QStringLiteral("Write the proxy code to "), QStringLiteral("filename")); + QCommandLineOption proxyCodeOption(QStringList() + << QStringLiteral("p") << QStringLiteral("proxy"), + QStringLiteral("Write the proxy code to "), + QStringLiteral("filename")); parser.addOption(proxyCodeOption); - QCommandLineOption verboseOption(QStringList() << QStringLiteral("V") << QStringLiteral("verbose"), - QStringLiteral("Be verbose.")); + QCommandLineOption verboseOption(QStringList() + << QStringLiteral("V") << QStringLiteral("verbose"), + QStringLiteral("Be verbose.")); parser.addOption(verboseOption); parser.process(app); @@ -1113,7 +1158,8 @@ int main(int argc, char **argv) QFileInfo inputInfo(inputFile); if (!inputInfo.exists() || !inputInfo.isFile() || !inputInfo.isReadable()) { - qCritical("Error: Input %s is not a file or cannot be accessed\n", qPrintable(inputFile)); + qCritical("Error: Input %s is not a file or cannot be accessed\n", + qPrintable(inputFile)); return 1; } } @@ -1137,4 +1183,3 @@ int main(int argc, char **argv) return 0; } - From b3f342ea204d47d939e44653a827f589b654e93c Mon Sep 17 00:00:00 2001 From: myml Date: Mon, 21 Jul 2025 15:28:10 +0800 Subject: [PATCH 106/366] fix: modify output check logic for UAB export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Changed output check behavior to always run main-check.sh for UAB export statistics 2. Separated skip conditions for non-app packages and output check skipping 3. Improved message clarity with "skipped" vs "ignored" states 4. Maintained existing error handling for failed checks The modification ensures main-check.sh always runs for app packages since its output is needed for UAB export statistics, even when output checks are skipped. The logic is now clearer with distinct handling for non-app packages (skipped) vs skipped output checks (ignored). fix: 修改ldd检查逻辑以支持UAB导出 1. 修改ldd检查行为,为UAB导出功能, 无论是否跳过output skip都执行main-check.sh 2. 分离非应用包和跳过输出检查的不同跳过条件 3. 使用"skipped"和"ignored"提高消息清晰度 4. 保留对检查失败的现有错误处理 此修改确保对于应用包始终运行main-check.sh,因为其输出用于UAB导出统计,即 使跳过输出检查。现在逻辑更清晰,区分了非应用包(跳过)和跳过输出检查(忽略) 的不同处理情况。 --- .../src/linglong/builder/linglong_builder.cpp | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 448226a57..5c94469fc 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -2148,19 +2148,24 @@ utils::error::Result Builder::runtimeCheck() { LINGLONG_TRACE("runtime check"); printMessage("[Runtime Check]"); - // Do some checks after run container - if (!this->buildOptions.skipCheckOutput && this->project.package.kind == "app") { - printMessage("Start runtime check", 2); - auto ret = - this->run(packageModules, { { QString{ LINGLONG_BUILDER_HELPER } + "/main-check.sh" } }); - if (!ret) { - printMessage("Runtime check failed", 2); - return LINGLONG_ERR(ret); - } - } else { - printMessage("Skip runtime check", 2); + // skip runtime check for non-app packages + if (this->project.package.kind != "app") { + printMessage("Runtime check skipped", 2); + return LINGLONG_OK; + } + printMessage("Start runtime check", 2); + // 导出uab时需要使用main-check统计的信息,所以无论是否跳过检查,都需要执行main-check + auto ret = + this->run(packageModules, { { QString{ LINGLONG_BUILDER_HELPER } + "/main-check.sh" } }); + // ignore runtime check if skipCheckOutput is set + if (this->buildOptions.skipCheckOutput) { + printMessage("Runtime check ignored", 2); + return LINGLONG_OK; + } + if (!ret) { + printMessage("Runtime check failed", 2); + return LINGLONG_ERR(ret); } - printMessage("Runtime check done", 2); return LINGLONG_OK; } From 590c1c081f67e5c2cfeadf954907f6f0e747b4ee Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 21 Jul 2025 14:57:59 +0800 Subject: [PATCH 107/366] fix: remove vendor qdbusxml2cpp tools/qdbusxml2cpp may not compile on all Qt versions. Signed-off-by: reddevillg --- CMakeLists.txt | 5 - LICENSES/GPL-3.0-only.txt | 232 ----- LICENSES/LicenseRef-Qt-Commercial.txt | 0 LICENSES/Qt-GPL-exception-1.0.txt | 21 - REUSE.toml | 12 - cmake/Qt6DBusMacro.cmake | 105 -- libs/dbus-api/CMakeLists.txt | 4 +- libs/linglong/CMakeLists.txt | 14 +- tools/qdbusxml2cpp/CMakeLists.txt | 10 - tools/qdbusxml2cpp/README.md | 8 - tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp | 1185 ---------------------- tools/qdbusxml2cpp/qdbusxml2cpp_6.cpp | 1347 ------------------------- 12 files changed, 3 insertions(+), 2940 deletions(-) delete mode 100644 LICENSES/GPL-3.0-only.txt delete mode 100644 LICENSES/LicenseRef-Qt-Commercial.txt delete mode 100644 LICENSES/Qt-GPL-exception-1.0.txt delete mode 100644 cmake/Qt6DBusMacro.cmake delete mode 100644 tools/qdbusxml2cpp/CMakeLists.txt delete mode 100644 tools/qdbusxml2cpp/README.md delete mode 100644 tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp delete mode 100644 tools/qdbusxml2cpp/qdbusxml2cpp_6.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bc4c81f6..773c53982 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,10 +262,6 @@ endif() message(STATUS "compiling with Qt${QT_VERSION_MAJOR}") -if("${QT_VERSION_MAJOR}" STREQUAL "6") - include(Qt6DBusMacro) -endif() - pkg_search_module(glib2 REQUIRED IMPORTED_TARGET glib-2.0) pkg_search_module(ostree1 REQUIRED IMPORTED_TARGET ostree-1) pkg_search_module(systemd REQUIRED IMPORTED_TARGET libsystemd) @@ -277,7 +273,6 @@ set(ytj_ENABLE_INSTALL NO) pfl_init(AUTO) add_subdirectory(external/http) -add_subdirectory(tools/qdbusxml2cpp) pfl_add_libraries( LIBS diff --git a/LICENSES/GPL-3.0-only.txt b/LICENSES/GPL-3.0-only.txt deleted file mode 100644 index f6cdd22a6..000000000 --- a/LICENSES/GPL-3.0-only.txt +++ /dev/null @@ -1,232 +0,0 @@ -GNU GENERAL PUBLIC LICENSE -Version 3, 29 June 2007 - -Copyright © 2007 Free Software Foundation, Inc. - -Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - -Preamble - -The GNU General Public License is a free, copyleft license for software and other kinds of works. - -The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. - -To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. - -Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. - -Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. - -The precise terms and conditions for copying, distribution and modification follow. - -TERMS AND CONDITIONS - -0. Definitions. - -“This License” refers to version 3 of the GNU General Public License. - -“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. - -“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. - -To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. - -A “covered work” means either the unmodified Program or a work based on the Program. - -To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. - -To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. - -An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. - -1. Source Code. -The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. - -A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. - -The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. - -The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same work. - -2. Basic Permissions. -All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. - -3. Protecting Users' Legal Rights From Anti-Circumvention Law. -No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. - -When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. - -4. Conveying Verbatim Copies. -You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. - -5. Conveying Modified Source Versions. -You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. - - c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. - -A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. - -6. Conveying Non-Source Forms. -You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: - - a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. - - d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. - -A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. - -“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. - -If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). - -The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. - -Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. - -7. Additional Terms. -“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or authors of the material; or - - e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. - -All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. - -8. Termination. -You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). - -However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. - -Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. - -Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. - -9. Acceptance Not Required for Having Copies. -You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. - -10. Automatic Licensing of Downstream Recipients. -Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. - -An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. - -11. Patents. -A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. - -A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. - -In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. - -If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. - -A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. - -12. No Surrender of Others' Freedom. -If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. - -13. Use with the GNU Affero General Public License. -Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. - -14. Revised Versions of this License. -The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. - -If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. - -Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. - -15. Disclaimer of Warranty. -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -16. Limitation of Liability. -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -17. Interpretation of Sections 15 and 16. -If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - -If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. - -You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . - -The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSES/LicenseRef-Qt-Commercial.txt b/LICENSES/LicenseRef-Qt-Commercial.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/LICENSES/Qt-GPL-exception-1.0.txt b/LICENSES/Qt-GPL-exception-1.0.txt deleted file mode 100644 index 761d0327a..000000000 --- a/LICENSES/Qt-GPL-exception-1.0.txt +++ /dev/null @@ -1,21 +0,0 @@ -The Qt Company GPL Exception 1.0 - -Exception 1: - -As a special exception you may create a larger work which contains the -output of this application and distribute that work under terms of your -choice, so long as the work is not otherwise derived from or based on -this application and so long as the work does not in itself generate -output that contains the output from this application in its original -or modified form. - -Exception 2: - -As a special exception, you have permission to combine this application -with Plugins licensed under the terms of your choice, to produce an -executable, and to copy and distribute the resulting executable under -the terms of your choice. However, the executable must be accompanied -by a prominent notice offering all users of the executable the entire -source code to this application, excluding the source code of the -independent modules, but including any changes you have made to this -application, under the terms of this license. diff --git a/REUSE.toml b/REUSE.toml index 218de29e2..6a8b60480 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -117,18 +117,6 @@ precedence = "aggregate" SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "CC0-1.0" -[[annotations]] -path = "tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp" -precedence = "aggregate" -SPDX-FileCopyrightText = "2020 The Qt Company Ltd." -SPDX-License-Identifier = "GPL-3.0-only" - -[[annotations]] -path = "tools/qdbusxml2cpp/qdbusxml2cpp_6.h" -precedence = "aggregate" -SPDX-FileCopyrightText = "2021 The Qt Company Ltd." -SPDX-License-Identifier = "GPL-3.0-only" - [[annotations]] path = "libs/ocppi/**" precedence = "aggregate" diff --git a/cmake/Qt6DBusMacro.cmake b/cmake/Qt6DBusMacro.cmake deleted file mode 100644 index 3a7bca2eb..000000000 --- a/cmake/Qt6DBusMacro.cmake +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2005-2011 Kitware, Inc. -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -include(MacroAddFileDependencies) - -function(qt6_add_dbus_interface_override _target _sources _interface _relativename) - get_filename_component(_infile ${_interface} ABSOLUTE) - get_filename_component(_basepath ${_relativename} DIRECTORY) - get_filename_component(_basename ${_relativename} NAME) - set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.h") - set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.cpp") - if(_basepath) - set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/moc_${_basename}.cpp") - else() - set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp") - endif() - - get_source_file_property(_nonamespace ${_interface} NO_NAMESPACE) - if(_nonamespace) - set(_params -N -m) - else() - set(_params -m) - endif() - - get_source_file_property(_classname ${_interface} CLASSNAME) - if(_classname) - set(_params ${_params} -c ${_classname}) - endif() - - get_source_file_property(_include ${_interface} INCLUDE) - if(_include) - set(_params ${_params} -i ${_include}) - endif() - - add_custom_command(OUTPUT "${_impl}" "${_header}" - COMMAND ${_target} ${_params} -p ${_relativename} ${_infile} - DEPENDS ${_infile} ${_target} - VERBATIM - ) - - set_source_files_properties("${_impl}" "${_header}" PROPERTIES - SKIP_AUTOMOC TRUE - SKIP_AUTOUIC TRUE - ) - - qt6_generate_moc("${_header}" "${_moc}") - - list(APPEND ${_sources} "${_impl}" "${_header}") - macro_add_file_dependencies("${_impl}" "${_moc}") - set(${_sources} ${${_sources}} PARENT_SCOPE) -endfunction() - -function(qt6_add_dbus_adaptor_override _target _sources _xml_file _include) # _optionalParentClass _optionalRelativename _optionalClassName) - get_filename_component(_infile ${_xml_file} ABSOLUTE) - - set(_optionalParentClass "${ARGV4}") - if(_optionalParentClass) - set(_parentClassOption "-l") - set(_parentClass "${_optionalParentClass}") - endif() - - set(_optionalRelativename "${ARGV5}") - if(_optionalRelativename) - set(_relativename ${_optionalRelativename}) - else() - string(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2adaptor" _relativename ${_infile}) - string(TOLOWER ${_relativename} _relativename) - endif() - get_filename_component(_basepath ${_relativename} DIRECTORY) - get_filename_component(_basename ${_relativename} NAME) - - set(_optionalClassName "${ARGV6}") - set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.h") - set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_relativename}.cpp") - if(_basepath) - set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basepath}/moc_${_basename}.cpp") - else() - set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp") - endif() - - if(_optionalClassName) - add_custom_command(OUTPUT "${_impl}" "${_header}" - COMMAND ${_target} -m -a ${_relativename} -c ${_optionalClassName} -i ${_include} ${_parentClassOption} ${_parentClass} ${_infile} - DEPENDS ${_infile} ${_target} - VERBATIM - ) - else() - add_custom_command(OUTPUT "${_impl}" "${_header}" - COMMAND ${_target} -m -a ${_relativename} -i ${_include} ${_parentClassOption} ${_parentClass} ${_infile} - DEPENDS ${_infile} ${_target} - VERBATIM - ) - endif() - - qt6_generate_moc("${_header}" "${_moc}") - set_source_files_properties("${_impl}" "${_header}" PROPERTIES - SKIP_AUTOMOC TRUE - SKIP_AUTOUIC TRUE - ) - macro_add_file_dependencies("${_impl}" "${_moc}") - - list(APPEND ${_sources} "${_impl}" "${_header}") - set(${_sources} ${${_sources}} PARENT_SCOPE) -endfunction() diff --git a/libs/dbus-api/CMakeLists.txt b/libs/dbus-api/CMakeLists.txt index 0426b66a0..c055fcfa7 100644 --- a/libs/dbus-api/CMakeLists.txt +++ b/libs/dbus-api/CMakeLists.txt @@ -34,10 +34,8 @@ function(linglong_add_dbus_interface target xml basename) # include endif() endif() - set(INTERFACE_SOURCES) if("${QT_VERSION_MAJOR}" STREQUAL "6") - qt6_add_dbus_interface_override(qdbusxml2cpp INTERFACE_SOURCES ${xml} - ${basename}) + qt6_add_dbus_interface(INTERFACE_SOURCES ${xml} ${basename}) else() set(Qt5DBus_QDBUSXML2CPP_EXECUTABLE qdbusxml2cpp) qt5_add_dbus_interface(INTERFACE_SOURCES ${xml} ${basename}) diff --git a/libs/linglong/CMakeLists.txt b/libs/linglong/CMakeLists.txt index 43a8e8f28..2debeaa1d 100644 --- a/libs/linglong/CMakeLists.txt +++ b/libs/linglong/CMakeLists.txt @@ -115,20 +115,10 @@ function( classname) get_real_target_name(target ${target}) - set(DBUS_ADAPTOR_SOURCE) - if("${QT_VERSION_MAJOR}" STREQUAL "6") - qt6_add_dbus_adaptor_override( - qdbusxml2cpp - DBUS_ADAPTOR_SOURCE - ${xml} - ${includes} - ${parent_class} - ${basename} - ${classname}) + qt6_add_dbus_adaptor(DBUS_ADAPTOR_SOURCE ${xml} ${includes} ${parent_class} + ${basename} ${classname}) else() - set(Qt5DBus_QDBUSXML2CPP_EXECUTABLE qdbusxml2cpp) # this varible only exists - # in qt5 qt5_add_dbus_adaptor(DBUS_ADAPTOR_SOURCE ${xml} ${includes} ${parent_class} ${basename} ${classname}) endif() diff --git a/tools/qdbusxml2cpp/CMakeLists.txt b/tools/qdbusxml2cpp/CMakeLists.txt deleted file mode 100644 index 6dcb65cd1..000000000 --- a/tools/qdbusxml2cpp/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -# -# SPDX-License-Identifier: LGPL-3.0-or-later - -set(SOURCE qdbusxml2cpp_${QT_VERSION_MAJOR}.cpp) -add_executable(qdbusxml2cpp ${SOURCE}) - -target_link_libraries( - qdbusxml2cpp PRIVATE Qt${QT_VERSION_MAJOR}::DBus Qt${QT_VERSION_MAJOR}::Core - Qt${QT_VERSION_MAJOR}::DBusPrivate) diff --git a/tools/qdbusxml2cpp/README.md b/tools/qdbusxml2cpp/README.md deleted file mode 100644 index 52cf692bd..000000000 --- a/tools/qdbusxml2cpp/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# qdbusxml2cpp - -This is a modified version of the offficial qdbusxml2cpp, -which generates DBus methods as virtual function. - -And we can override these virtual functions to generate mock dbus reply message. - -Check examples in tests for further information. diff --git a/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp b/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp deleted file mode 100644 index 2a5fcef90..000000000 --- a/tools/qdbusxml2cpp/qdbusxml2cpp_5.cpp +++ /dev/null @@ -1,1185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PROGRAMNAME "qdbusxml2cpp" -#define PROGRAMVERSION "0.8" -#define PROGRAMCOPYRIGHT "Copyright (C) 2020 The Qt Company Ltd." - -#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" - -// https://github.com/AD-Vega/qarv/issues/22#issuecomment-1012011346 -#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) -namespace Qt { -static auto endl = ::endl; -} -#endif - -static QString globalClassName; -static QString parentClassName; -static QString proxyFile; -static QString adaptorFile; -static QString inputFile; -static bool skipNamespaces; -static bool verbose; -static bool includeMocs; -static QString commandLine; -static QStringList includes; -static QStringList wantedInterfaces; - -static const char includeList[] = "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n"; - -static const char forwardDeclarations[] = "QT_BEGIN_NAMESPACE\n" - "class QByteArray;\n" - "template class QList;\n" - "template class QMap;\n" - "class QString;\n" - "class QStringList;\n" - "class QVariant;\n" - "QT_END_NAMESPACE\n"; - -static QDBusIntrospection::Interfaces readInput() -{ - QFile input(inputFile); - if (inputFile.isEmpty() || inputFile == QLatin1String("-")) { - input.open(stdin, QIODevice::ReadOnly); - } else { - input.open(QIODevice::ReadOnly); - } - - QByteArray data = input.readAll(); - - // check if the input is already XML - data = data.trimmed(); - if (data.startsWith("= 0) - annotationName += - QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); - QString qttype = annotations.value(annotationName); - if (!qttype.isEmpty()) - return std::move(qttype).toLatin1(); - - QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); - if (paramId >= 0) - oldAnnotationName += - QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); - qttype = annotations.value(oldAnnotationName); - - if (qttype.isEmpty()) { - if (!isSignal || qstrcmp(direction, "Out") == 0) { - fprintf(stderr, - "%s: Got unknown type `%s' processing '%s'\n", - PROGRAMNAME, - qPrintable(signature), - qPrintable(inputFile)); - fprintf(stderr, - "You should add \"/> to the XML " - "description\n", - qPrintable(annotationName)); - } - - if (isSignal) - return qtTypeName(signature, annotations, paramId, "In", isSignal); - - exit(1); - } - - fprintf(stderr, - "%s: Warning: deprecated annotation '%s' found while processing '%s'; " - "suggest updating to '%s'\n", - PROGRAMNAME, - qPrintable(oldAnnotationName), - qPrintable(inputFile), - qPrintable(annotationName)); - return std::move(qttype).toLatin1(); - } - - return QVariant::typeToName(QVariant::Type(type)); -} - -static QString nonConstRefArg(const QByteArray &arg) -{ - return QLatin1String(arg + " &"); -} - -static QString templateArg(const QByteArray &arg) -{ - if (!arg.endsWith('>')) - return QLatin1String(arg); - - return QLatin1String(arg + ' '); -} - -static QString constRefArg(const QByteArray &arg) -{ - if (!arg.startsWith('Q')) - return QLatin1String(arg + ' '); - else - return QString(QLatin1String("const %1 &")).arg(QLatin1String(arg)); -} - -static QStringList -makeArgNames(const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) -{ - QStringList retval; - const int numInputArgs = inputArgs.count(); - const int numOutputArgs = outputArgs.count(); - retval.reserve(numInputArgs + numOutputArgs); - for (int i = 0; i < numInputArgs; ++i) { - const QDBusIntrospection::Argument &arg = inputArgs.at(i); - QString name = arg.name; - if (name.isEmpty()) - name = QString(QLatin1String("in%1")).arg(i); - else - name.replace(QLatin1Char('-'), QLatin1Char('_')); - while (retval.contains(name)) - name += QLatin1String("_"); - retval << name; - } - for (int i = 0; i < numOutputArgs; ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString name = arg.name; - if (name.isEmpty()) - name = QString(QLatin1String("out%1")).arg(i); - else - name.replace(QLatin1Char('-'), QLatin1Char('_')); - while (retval.contains(name)) - name += QLatin1String("_"); - retval << name; - } - return retval; -} - -static void -writeArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) -{ - // input args: - bool first = true; - int argPos = 0; - for (int i = 0; i < inputArgs.count(); ++i) { - const QDBusIntrospection::Argument &arg = inputArgs.at(i); - QString type = constRefArg(qtTypeName(arg.type, annotations, i, "In")); - - if (!first) - ts << ", "; - ts << type << argNames.at(argPos++); - first = false; - } - - argPos++; - - // output args - // yes, starting from 1 - for (int i = 1; i < outputArgs.count(); ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - - if (!first) - ts << ", "; - ts << nonConstRefArg(qtTypeName(arg.type, annotations, i, "Out")) << argNames.at(argPos++); - first = false; - } -} - -static void writeSignalArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &outputArgs) -{ - bool first = true; - int argPos = 0; - for (int i = 0; i < outputArgs.count(); ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString type = - constRefArg(qtTypeName(arg.type, annotations, i, "Out", true /* isSignal */)); - - if (!first) - ts << ", "; - ts << type << argNames.at(argPos++); - first = false; - } -} - -static QString propertyGetter(const QDBusIntrospection::Property &property) -{ - QString getter = - property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertyGetter")); - if (!getter.isEmpty()) - return getter; - - getter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertyGetter")); - if (!getter.isEmpty()) { - fprintf(stderr, - "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found" - " while processing '%s';" - " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n", - PROGRAMNAME, - qPrintable(inputFile)); - return getter; - } - - getter = property.name; - getter[0] = getter[0].toLower(); - return getter; -} - -static QString propertySetter(const QDBusIntrospection::Property &property) -{ - QString setter = - property.annotations.value(QLatin1String("org.qtproject.QtDBus.PropertySetter")); - if (!setter.isEmpty()) - return setter; - - setter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertySetter")); - if (!setter.isEmpty()) { - fprintf(stderr, - "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found" - " while processing '%s';" - " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n", - PROGRAMNAME, - qPrintable(inputFile)); - return setter; - } - - setter = QLatin1String("set") + property.name; - setter[3] = setter[3].toUpper(); - return setter; -} - -static QString methodName(const QDBusIntrospection::Method &method) -{ - QString name = method.annotations.value(QStringLiteral("org.qtproject.QtDBus.MethodName")); - if (!name.isEmpty()) - return name; - - return method.name; -} - -static QString stringify(const QString &data) -{ - QString retval; - int i; - for (i = 0; i < data.length(); ++i) { - retval += QLatin1Char('\"'); - for (; i < data.length() && data[i] != QLatin1Char('\n') && data[i] != QLatin1Char('\r'); - ++i) - if (data[i] == QLatin1Char('\"')) - retval += QLatin1String("\\\""); - else - retval += data[i]; - if (i + 1 < data.length() && data[i] == QLatin1Char('\r') - && data[i + 1] == QLatin1Char('\n')) - i++; - retval += QLatin1String("\\n\"\n"); - } - return retval; -} - -static bool openFile(const QString &fileName, QFile &file) -{ - if (fileName.isEmpty()) - return false; - - bool isOk = false; - if (fileName == QLatin1String("-")) { - isOk = file.open(stdout, QIODevice::WriteOnly | QIODevice::Text); - } else { - file.setFileName(fileName); - isOk = file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text); - } - - if (!isOk) - fprintf(stderr, - "%s: Unable to open '%s': %s\n", - PROGRAMNAME, - qPrintable(fileName), - qPrintable(file.errorString())); - return isOk; -} - -static void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces) -{ - // open the file - QString headerName = header(filename); - QByteArray headerData; - QTextStream hs(&headerData); - - QString cppName = cpp(filename); - QByteArray cppData; - QTextStream cs(&cppData); - - // write the header: - writeHeader(hs, true); - if (cppName != headerName) - writeHeader(cs, false); - - // include guards: - hs << "#pragma once" << Qt::endl << Qt::endl; - - // include our stuff: - hs << "#include " << Qt::endl - << includeList << "#include " << Qt::endl; - - for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << Qt::endl; - if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << Qt::endl; - } - - hs << Qt::endl; - - if (cppName != headerName) { - if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl; - } - - for (const QDBusIntrospection::Interface *interface : interfaces) { - QString className = classNameForInterface(interface->name, Proxy); - - // comment: - hs << "/*" << Qt::endl - << " * Proxy class for interface " << interface->name << Qt::endl - << " */" << Qt::endl; - cs << "/*" << Qt::endl - << " * Implementation of interface class " << className << Qt::endl - << " */" << Qt::endl - << Qt::endl; - - // class header: - hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl - << "{" << Qt::endl - << " Q_OBJECT" << Qt::endl; - - // the interface name - hs << "public:" << Qt::endl - << " static inline const char *staticInterfaceName()" << Qt::endl - << " { return \"" << interface->name << "\"; }" << Qt::endl - << Qt::endl; - - // constructors/destructors: - hs << "public:" << Qt::endl - << " " << className - << "(const QString &service, const QString &path, const QDBusConnection &connection, " - "QObject *parent = nullptr);" - << Qt::endl - << Qt::endl - << " ~" << className << "();" << Qt::endl - << Qt::endl; - cs << className << "::" << className - << "(const QString &service, const QString &path, const QDBusConnection &connection, " - "QObject *parent)" - << Qt::endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, " - "parent)" - << Qt::endl - << "{" << Qt::endl - << "}" << Qt::endl - << Qt::endl - << className << "::~" << className << "()" << Qt::endl - << "{" << Qt::endl - << "}" << Qt::endl - << Qt::endl; - - // properties: - for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.type, property.annotations); - QString getter = propertyGetter(property); - QString setter = propertySetter(property); - - hs << " Q_PROPERTY(" << type << " " << property.name; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) - // it's readble - hs << " READ " << getter; - - // setter - if (property.access != QDBusIntrospection::Property::Read) - // it's writeable - hs << " WRITE " << setter; - - hs << ")" << Qt::endl; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << Qt::endl - << " { return qvariant_cast< " << type << " >(property(\"" << property.name - << "\")); }" << Qt::endl; - } - - // setter: - if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" - << Qt::endl - << " { setProperty(\"" << property.name - << "\", QVariant::fromValue(value)); }" << Qt::endl; - } - - hs << Qt::endl; - } - - // methods: - hs << "public Q_SLOTS: // METHODS" << Qt::endl; - for (const QDBusIntrospection::Method &method : interface->methods) { - bool isDeprecated = - method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) - == QLatin1String("true"); - bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); - if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, - "%s: warning while processing '%s': method %s in interface %s is marked " - "'no-reply' but has output arguments.\n", - PROGRAMNAME, - qPrintable(inputFile), - qPrintable(method.name), - qPrintable(interface->name)); - continue; - } - - hs << " inline virtual " << (isDeprecated ? "Q_DECL_DEPRECATED " : ""); - - if (isNoReply) { - hs << "Q_NOREPLY void "; - } else { - hs << "QDBusPendingReply<"; - for (int i = 0; i < method.outputArgs.count(); ++i) - hs << (i > 0 ? ", " : "") - << templateArg( - qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")); - hs << "> "; - } - - hs << methodName(method) << "("; - - QStringList argNames = makeArgNames(method.inputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs); - - hs << ")" << Qt::endl - << " {" << Qt::endl - << " QList argumentList;" << Qt::endl; - - if (!method.inputArgs.isEmpty()) { - hs << " argumentList"; - for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << Qt::endl; - } - - if (isNoReply) - hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; - else - hs << " return asyncCallWithArgumentList(QStringLiteral(\"" << method.name - << "\"), argumentList);" << Qt::endl; - - // close the function: - hs << " }" << Qt::endl; - - if (method.outputArgs.count() > 1) { - // generate the old-form QDBusReply methods with multiple incoming parameters - hs << " inline " << (isDeprecated ? "Q_DECL_DEPRECATED " : "") << "QDBusReply<" - << templateArg( - qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out")) - << "> "; - hs << method.name << "("; - - QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - - hs << ")" << Qt::endl - << " {" << Qt::endl - << " QList argumentList;" << Qt::endl; - - int argPos = 0; - if (!method.inputArgs.isEmpty()) { - hs << " argumentList"; - for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) - hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << Qt::endl; - } - - hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; - - argPos++; - hs << " if (reply.type() == QDBusMessage::ReplyMessage && " - "reply.arguments().count() == " - << method.outputArgs.count() << ") {" << Qt::endl; - - // yes, starting from 1 - for (int i = 1; i < method.outputArgs.count(); ++i) - hs << " " << argNames.at(argPos++) << " = qdbus_cast<" - << templateArg( - qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) - << ">(reply.arguments().at(" << i << "));" << Qt::endl; - hs << " }" << Qt::endl - << " return reply;" << Qt::endl - << " }" << Qt::endl; - } - - hs << Qt::endl; - } - - hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; - for (const QDBusIntrospection::Signal &signal : interface->signals_) { - hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) - == QLatin1String("true")) - hs << "Q_DECL_DEPRECATED "; - - hs << "void " << signal.name << "("; - - QStringList argNames = makeArgNames(signal.outputArgs); - writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - - hs << ");" << Qt::endl; // finished for header - } - - // close the class: - hs << "};" << Qt::endl << Qt::endl; - } - - if (!skipNamespaces) { - QStringList last; - QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin(); - do { - QStringList current; - QString name; - if (it != interfaces.constEnd()) { - current = it->constData()->name.split(QLatin1Char('.')); - name = current.takeLast(); - } - - int i = 0; - while (i < current.count() && i < last.count() && current.at(i) == last.at(i)) - ++i; - - // i parts matched - // close last.arguments().count() - i namespaces: - for (int j = i; j < last.count(); ++j) - hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl; - - // open current.arguments().count() - i namespaces - for (int j = i; j < current.count(); ++j) - hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" - << Qt::endl; - - // add this class: - if (!name.isEmpty()) { - hs << QString(current.count() * 2, QLatin1Char(' ')) - << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) << " " - << name << ";" << Qt::endl; - } - - if (it == interfaces.constEnd()) - break; - ++it; - last = current; - } while (true); - } - - QString mocName = moc(filename); - if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl << "#include \"" << mocName << "\"" << Qt::endl; - - cs.flush(); - hs.flush(); - - QFile file; - const bool headerOpen = openFile(headerName, file); - if (headerOpen) - file.write(headerData); - - if (headerName == cppName) { - if (headerOpen) - file.write(cppData); - } else { - QFile cppFile; - if (openFile(cppName, cppFile)) - cppFile.write(cppData); - } -} - -static void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces) -{ - // open the file - QString headerName = header(filename); - QByteArray headerData; - QTextStream hs(&headerData); - - QString cppName = cpp(filename); - QByteArray cppData; - QTextStream cs(&cppData); - - // write the headers - writeHeader(hs, false); - if (cppName != headerName) - writeHeader(cs, true); - - // include guards: - QString includeGuard; - if (!headerName.isEmpty() && headerName != QLatin1String("-")) { - includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_')); - int pos = includeGuard.lastIndexOf(QLatin1Char('/')); - if (pos != -1) - includeGuard = includeGuard.mid(pos + 1); - } else { - includeGuard = QLatin1String("QDBUSXML2CPP_ADAPTOR"); - } - includeGuard = QString(QLatin1String("%1")).arg(includeGuard); - hs << "#ifndef " << includeGuard << Qt::endl - << "#define " << includeGuard << Qt::endl - << Qt::endl; - - // include our stuff: - hs << "#include " << Qt::endl; - if (cppName == headerName) - hs << "#include " << Qt::endl - << "#include " << Qt::endl; - hs << "#include " << Qt::endl; - - for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << Qt::endl; - if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << Qt::endl; - } - - if (cppName != headerName) { - if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << Qt::endl; - - cs << "#include " << Qt::endl << includeList << Qt::endl; - hs << forwardDeclarations; - } else { - hs << includeList; - } - - hs << Qt::endl; - - QString parent = parentClassName; - if (parentClassName.isEmpty()) - parent = QLatin1String("QObject"); - - for (const QDBusIntrospection::Interface *interface : interfaces) { - QString className = classNameForInterface(interface->name, Adaptor); - - // comment: - hs << "/*" << Qt::endl - << " * Adaptor class for interface " << interface->name << Qt::endl - << " */" << Qt::endl; - cs << "/*" << Qt::endl - << " * Implementation of adaptor class " << className << Qt::endl - << " */" << Qt::endl - << Qt::endl; - - // class header: - hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl - << "{" << Qt::endl - << " Q_OBJECT" << Qt::endl - << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl - << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl - << stringify(interface->introspection) << " \"\")" << Qt::endl - << "public:" << Qt::endl - << " " << className << "(" << parent << " *parent);" << Qt::endl - << " virtual ~" << className << "();" << Qt::endl - << Qt::endl; - - if (!parentClassName.isEmpty()) - hs << " inline " << parent << " *parent() const" << Qt::endl - << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl - << Qt::endl; - - // constructor/destructor - cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl - << " : QDBusAbstractAdaptor(parent)" << Qt::endl - << "{" << Qt::endl - << " // constructor" << Qt::endl - << " setAutoRelaySignals(true);" << Qt::endl - << "}" << Qt::endl - << Qt::endl - << className << "::~" << className << "()" << Qt::endl - << "{" << Qt::endl - << " // destructor" << Qt::endl - << "}" << Qt::endl - << Qt::endl; - - hs << "public: // PROPERTIES" << Qt::endl; - for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.type, property.annotations); - QString constRefType = constRefArg(type); - QString getter = propertyGetter(property); - QString setter = propertySetter(property); - - hs << " Q_PROPERTY(" << type << " " << property.name; - if (property.access != QDBusIntrospection::Property::Write) - hs << " READ " << getter; - if (property.access != QDBusIntrospection::Property::Read) - hs << " WRITE " << setter; - hs << ")" << Qt::endl; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;" << Qt::endl; - cs << type << " " << className << "::" << getter << "() const" << Qt::endl - << "{" << Qt::endl - << " // get the value of property " << property.name << Qt::endl - << " return qvariant_cast< " << type << " >(parent()->property(\"" - << property.name << "\"));" << Qt::endl - << "}" << Qt::endl - << Qt::endl; - } - - // setter - if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" - << Qt::endl - << "{" << Qt::endl - << " // set the value of property " << property.name << Qt::endl - << " parent()->setProperty(\"" << property.name - << "\", QVariant::fromValue(value"; - if (constRefType.contains(QLatin1String("QDBusVariant"))) - cs << ".variant()"; - cs << "));" << Qt::endl << "}" << Qt::endl << Qt::endl; - } - - hs << Qt::endl; - } - - hs << "public Q_SLOTS: // METHODS" << Qt::endl; - for (const QDBusIntrospection::Method &method : interface->methods) { - bool isNoReply = - method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); - if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, - "%s: warning while processing '%s': method %s in interface %s is marked " - "'no-reply' but has output arguments.\n", - PROGRAMNAME, - qPrintable(inputFile), - qPrintable(method.name), - qPrintable(interface->name)); - continue; - } - - hs << " "; - if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) - == QLatin1String("true")) - hs << "Q_DECL_DEPRECATED "; - - QByteArray returnType; - if (isNoReply) { - hs << "Q_NOREPLY void "; - cs << "void "; - } else if (method.outputArgs.isEmpty()) { - hs << "void "; - cs << "void "; - } else { - returnType = - qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out"); - hs << returnType << " "; - cs << returnType << " "; - } - - QString name = methodName(method); - hs << name << "("; - cs << className << "::" << name << "("; - - QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - - hs << ");" << Qt::endl; // finished for header - cs << ")" << Qt::endl - << "{" << Qt::endl - << " // handle method call " << interface->name << "." << methodName(method) - << Qt::endl; - - // make the call - bool usingInvokeMethod = false; - if (parentClassName.isEmpty() && method.inputArgs.count() <= 10 - && method.outputArgs.count() <= 1) - usingInvokeMethod = true; - - if (usingInvokeMethod) { - // we are using QMetaObject::invokeMethod - if (!returnType.isEmpty()) - cs << " " << returnType << " " << argNames.at(method.inputArgs.count()) - << ";" << Qt::endl; - - static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; - cs << invoke << name << "\""; - - if (!method.outputArgs.isEmpty()) - cs << ", Q_RETURN_ARG(" - << qtTypeName(method.outputArgs.at(0).type, method.annotations, 0, "Out") - << ", " << argNames.at(method.inputArgs.count()) << ")"; - - for (int i = 0; i < method.inputArgs.count(); ++i) - cs << ", Q_ARG(" - << qtTypeName(method.inputArgs.at(i).type, method.annotations, i, "In") - << ", " << argNames.at(i) << ")"; - - cs << ");" << Qt::endl; - - if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl; - } else { - if (parentClassName.isEmpty()) - cs << " //"; - else - cs << " "; - - if (!method.outputArgs.isEmpty()) - cs << "return "; - - if (parentClassName.isEmpty()) - cs << "static_cast(parent())->"; - else - cs << "parent()->"; - cs << name << "("; - - int argPos = 0; - bool first = true; - for (int i = 0; i < method.inputArgs.count(); ++i) { - cs << (first ? "" : ", ") << argNames.at(argPos++); - first = false; - } - ++argPos; // skip retval, if any - for (int i = 1; i < method.outputArgs.count(); ++i) { - cs << (first ? "" : ", ") << argNames.at(argPos++); - first = false; - } - - cs << ");" << Qt::endl; - } - cs << "}" << Qt::endl << Qt::endl; - } - - hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; - for (const QDBusIntrospection::Signal &signal : interface->signals_) { - hs << " "; - if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) - == QLatin1String("true")) - hs << "Q_DECL_DEPRECATED "; - - hs << "void " << signal.name << "("; - - QStringList argNames = makeArgNames(signal.outputArgs); - writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - - hs << ");" << Qt::endl; // finished for header - } - - // close the class: - hs << "};" << Qt::endl << Qt::endl; - } - - // close the include guard - hs << "#endif" << Qt::endl; - - QString mocName = moc(filename); - if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl << "#include \"" << mocName << "\"" << Qt::endl; - - cs.flush(); - hs.flush(); - - QFile file; - const bool headerOpen = openFile(headerName, file); - if (headerOpen) - file.write(headerData); - - if (headerName == cppName) { - if (headerOpen) - file.write(cppData); - } else { - QFile cppFile; - if (openFile(cppName, cppFile)) - cppFile.write(cppData); - } -} - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME)); - QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION)); - - QCommandLineParser parser; - parser.setApplicationDescription(QLatin1String( - "Produces the C++ code to implement the interfaces defined in the input file.\n\n" - "If the file name given to the options -a and -p does not end in .cpp or .h, the\n" - "program will automatically append the suffixes and produce both files.\n" - "You can also use a colon (:) to separate the header name from the source file\n" - "name, as in '-a filename_p.h:filename.cpp'.\n\n" - "If you pass a dash (-) as the argument to either -p or -a, the output is written\n" - "to the standard output.")); - - parser.addHelpOption(); - parser.addVersionOption(); - parser.addPositionalArgument(QStringLiteral("xml-or-xml-file"), - QStringLiteral("XML file to use.")); - parser.addPositionalArgument(QStringLiteral("interfaces"), - QStringLiteral("List of interfaces to use."), - QStringLiteral("[interfaces ...]")); - - QCommandLineOption adapterCodeOption(QStringList() - << QStringLiteral("a") << QStringLiteral("adaptor"), - QStringLiteral("Write the adaptor code to "), - QStringLiteral("filename")); - parser.addOption(adapterCodeOption); - - QCommandLineOption classNameOption( - QStringList() << QStringLiteral("c") << QStringLiteral("classname"), - QStringLiteral("Use as the class name for the generated classes"), - QStringLiteral("classname")); - parser.addOption(classNameOption); - - QCommandLineOption addIncludeOption(QStringList() - << QStringLiteral("i") << QStringLiteral("include"), - QStringLiteral("Add #include to the output"), - QStringLiteral("filename")); - parser.addOption(addIncludeOption); - - QCommandLineOption adapterParentOption( - QStringLiteral("l"), - QStringLiteral("When generating an adaptor, use as the parent class"), - QStringLiteral("classname")); - parser.addOption(adapterParentOption); - - QCommandLineOption mocIncludeOption( - QStringList() << QStringLiteral("m") << QStringLiteral("moc"), - QStringLiteral("Generate #include \"filename.moc\" statements in the .cpp files")); - parser.addOption(mocIncludeOption); - - QCommandLineOption noNamespaceOption(QStringList() << QStringLiteral("N") - << QStringLiteral("no-namespaces"), - QStringLiteral("Don't use namespaces")); - parser.addOption(noNamespaceOption); - - QCommandLineOption proxyCodeOption(QStringList() - << QStringLiteral("p") << QStringLiteral("proxy"), - QStringLiteral("Write the proxy code to "), - QStringLiteral("filename")); - parser.addOption(proxyCodeOption); - - QCommandLineOption verboseOption(QStringList() - << QStringLiteral("V") << QStringLiteral("verbose"), - QStringLiteral("Be verbose.")); - parser.addOption(verboseOption); - - parser.process(app); - - adaptorFile = parser.value(adapterCodeOption); - globalClassName = parser.value(classNameOption); - includes = parser.values(addIncludeOption); - parentClassName = parser.value(adapterParentOption); - includeMocs = parser.isSet(mocIncludeOption); - skipNamespaces = parser.isSet(noNamespaceOption); - proxyFile = parser.value(proxyCodeOption); - verbose = parser.isSet(verboseOption); - - wantedInterfaces = parser.positionalArguments(); - if (!wantedInterfaces.isEmpty()) { - inputFile = wantedInterfaces.takeFirst(); - - QFileInfo inputInfo(inputFile); - if (!inputInfo.exists() || !inputInfo.isFile() || !inputInfo.isReadable()) { - qCritical("Error: Input %s is not a file or cannot be accessed\n", - qPrintable(inputFile)); - return 1; - } - } - - if (verbose) - QLoggingCategory::setFilterRules(QStringLiteral("dbus.parser.debug=true")); - - QDBusIntrospection::Interfaces interfaces = readInput(); - cleanInterfaces(interfaces); - - QStringList args = app.arguments(); - args.removeFirst(); - commandLine = QLatin1String(PROGRAMNAME " "); - commandLine += args.join(QLatin1Char(' ')); - - if (!proxyFile.isEmpty() || adaptorFile.isEmpty()) - writeProxy(proxyFile, interfaces); - - if (!adaptorFile.isEmpty()) - writeAdaptor(adaptorFile, interfaces); - - return 0; -} diff --git a/tools/qdbusxml2cpp/qdbusxml2cpp_6.cpp b/tools/qdbusxml2cpp/qdbusxml2cpp_6.cpp deleted file mode 100644 index 475d4fc53..000000000 --- a/tools/qdbusxml2cpp/qdbusxml2cpp_6.cpp +++ /dev/null @@ -1,1347 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -// ATTENTION: This file has been modified - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PROGRAMNAME "qdbusxml2cpp" -#define PROGRAMVERSION "0.8" -#define PROGRAMCOPYRIGHT QT_COPYRIGHT - -#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" - -using namespace Qt::StringLiterals; - -class QDBusXmlToCpp final -{ -public: - int run(const QCoreApplication &app); - -private: - class DiagnosticsReporter final : public QDBusIntrospection::DiagnosticsReporter - { - public: - void setFileName(const QString &fileName) { m_fileName = fileName; } - - bool hadErrors() const { return m_hadErrors; } - - void warning(const QDBusIntrospection::SourceLocation &location, - const char *msg, - ...) override; - void error(const QDBusIntrospection::SourceLocation &location, - const char *msg, - ...) override; - void note(const QDBusIntrospection::SourceLocation &location, const char *msg, ...) - Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); - - private: - QString m_fileName; - bool m_hadErrors = false; - - void report(const QDBusIntrospection::SourceLocation &location, - const char *msg, - va_list ap, - const char *severity); - }; - - enum ClassType { Proxy, Adaptor }; - - void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces); - void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces); - - QDBusIntrospection::Interfaces readInput(); - void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces); - QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost); - QString classNameForInterface(const QString &interface, ClassType classType); - QByteArray qtTypeName(const QDBusIntrospection::SourceLocation &location, - const QString &signature, - const QDBusIntrospection::Annotations &annotations, - qsizetype paramId = -1, - const char *direction = "Out"); - void - writeArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()); - void writeSignalArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &outputArgs); - QString propertyGetter(const QDBusIntrospection::Property &property); - QString propertySetter(const QDBusIntrospection::Property &property); - - QString globalClassName; - QString parentClassName; - QString inputFile; - bool skipNamespaces = false; - bool includeMocs = false; - QString commandLine; - QStringList includes; - QStringList globalIncludes; - QStringList wantedInterfaces; - - DiagnosticsReporter reporter; -}; - -static const char includeList[] = "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n"; - -static const char forwardDeclarations[] = "#include \n"; - -void QDBusXmlToCpp::DiagnosticsReporter::warning(const QDBusIntrospection::SourceLocation &location, - const char *msg, - ...) -{ - va_list ap; - va_start(ap, msg); - report(location, msg, ap, "warning"); - va_end(ap); -} - -void QDBusXmlToCpp::DiagnosticsReporter::error(const QDBusIntrospection::SourceLocation &location, - const char *msg, - ...) -{ - va_list ap; - va_start(ap, msg); - report(location, msg, ap, "error"); - va_end(ap); - m_hadErrors = true; -} - -void QDBusXmlToCpp::DiagnosticsReporter::note(const QDBusIntrospection::SourceLocation &location, - const char *msg, - ...) -{ - va_list ap; - va_start(ap, msg); - report(location, msg, ap, "note"); - va_end(ap); - m_hadErrors = true; -} - -void QDBusXmlToCpp::DiagnosticsReporter::report(const QDBusIntrospection::SourceLocation &location, - const char *msg, - va_list ap, - const char *severity) -{ - fprintf(stderr, - "%s:%lld:%lld: %s: ", - qPrintable(m_fileName), - (long long int)location.lineNumber, - (long long int)location.columnNumber + 1, - severity); - vfprintf(stderr, msg, ap); -} - -QDBusIntrospection::Interfaces QDBusXmlToCpp::readInput() -{ - QFile input(inputFile); - if (inputFile.isEmpty() || inputFile == "-"_L1) { - reporter.setFileName(""_L1); - if (!input.open(stdin, QIODevice::ReadOnly)) { - fprintf(stderr, - PROGRAMNAME ": could not open standard input: %s\n", - qPrintable(input.errorString())); - exit(1); - } - } else { - reporter.setFileName(inputFile); - if (!input.open(QIODevice::ReadOnly)) { - fprintf(stderr, - PROGRAMNAME ": could not open input file '%s': %s\n", - qPrintable(inputFile), - qPrintable(input.errorString())); - exit(1); - } - } - - QByteArray data = input.readAll(); - auto interfaces = QDBusIntrospection::parseInterfaces(QString::fromUtf8(data), &reporter); - if (reporter.hadErrors()) - exit(1); - - return interfaces; -} - -void QDBusXmlToCpp::cleanInterfaces(QDBusIntrospection::Interfaces &interfaces) -{ - if (!wantedInterfaces.isEmpty()) { - QDBusIntrospection::Interfaces::Iterator it = interfaces.begin(); - while (it != interfaces.end()) - if (!wantedInterfaces.contains(it.key())) - it = interfaces.erase(it); - else - ++it; - } -} - -static bool isSupportedSuffix(QStringView suffix) -{ - const QLatin1StringView candidates[] = { "h"_L1, "cpp"_L1, "cc"_L1 }; - - for (auto candidate : candidates) - if (suffix == candidate) - return true; - - return false; -} - -// produce a header name from the file name -static QString header(const QString &name) -{ - QStringList parts = name.split(u':'); - QString retval = parts.front(); - - if (retval.isEmpty() || retval == "-"_L1) - return retval; - - QFileInfo header{ retval }; - if (!isSupportedSuffix(header.suffix())) - retval.append(".h"_L1); - - return retval; -} - -// produce a cpp name from the file name -static QString cpp(const QString &name) -{ - QStringList parts = name.split(u':'); - QString retval = parts.back(); - - if (retval.isEmpty() || retval == "-"_L1) - return retval; - - QFileInfo source{ retval }; - if (!isSupportedSuffix(source.suffix())) - retval.append(".cpp"_L1); - - return retval; -} - -// produce a moc name from the file name -static QString moc(const QString &name) -{ - QString retval; - const QStringList fileNames = name.split(u':'); - - if (fileNames.size() == 1) { - QFileInfo fi{ fileNames.front() }; - if (isSupportedSuffix(fi.suffix())) { - // Generates a file that contains the header and the implementation: include - // "filename.moc" - retval += fi.completeBaseName(); - retval += ".moc"_L1; - } else { - // Separate source and header files are generated: include "moc_filename.cpp" - retval += "moc_"_L1; - retval += fi.fileName(); - retval += ".cpp"_L1; - } - } else { - QString headerName = fileNames.front(); - QString sourceName = fileNames.back(); - - if (sourceName.isEmpty() || sourceName == "-"_L1) { - // If only a header is generated, don't include anything - } else if (headerName.isEmpty() || headerName == "-"_L1) { - // If only source file is generated: include "moc_sourcename.cpp" - QFileInfo source{ sourceName }; - - retval += "moc_"_L1; - retval += source.completeBaseName(); - retval += ".cpp"_L1; - - fprintf(stderr, - "warning: no header name is provided, assuming it to be \"%s\"\n", - qPrintable(source.completeBaseName() + ".h"_L1)); - } else { - // Both source and header generated: include "moc_headername.cpp" - QFileInfo header{ headerName }; - - retval += "moc_"_L1; - retval += header.completeBaseName(); - retval += ".cpp"_L1; - } - } - - return retval; -} - -QTextStream &QDBusXmlToCpp::writeHeader(QTextStream &ts, bool changesWillBeLost) -{ - ts << "/*\n" - " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION "\n" - " * Source file was " - << QFileInfo(inputFile).fileName() - << "\n" - " *\n" - " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT "\n" - " *\n" - " * This is an auto-generated file.\n"; - - if (changesWillBeLost) - ts << " * Do not edit! All changes made to it will be lost.\n"; - else - ts << " * This file may have been hand-edited. Look for HAND-EDIT comments\n" - " * before re-generating it.\n"; - - ts << " */\n\n"; - - return ts; -} - -QString QDBusXmlToCpp::classNameForInterface(const QString &interface, - QDBusXmlToCpp::ClassType classType) -{ - if (!globalClassName.isEmpty()) - return globalClassName; - - const auto parts = QStringView{ interface }.split(u'.'); - - QString retval; - if (classType == Proxy) { - for (const auto &part : parts) { - retval += part[0].toUpper(); - retval += part.mid(1); - } - } else { - retval += parts.last()[0].toUpper() + parts.last().mid(1).toString(); - } - - if (classType == Proxy) - retval += "Interface"_L1; - else - retval += "Adaptor"_L1; - - return retval; -} - -QByteArray QDBusXmlToCpp::qtTypeName(const QDBusIntrospection::SourceLocation &location, - const QString &signature, - const QDBusIntrospection::Annotations &annotations, - qsizetype paramId, - const char *direction) -{ - int type = QDBusMetaType::signatureToMetaType(signature.toLatin1()).id(); - if (type == QMetaType::UnknownType) { - QString annotationName = u"org.qtproject.QtDBus.QtTypeName"_s; - if (paramId >= 0) - annotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); - auto annotation = annotations.value(annotationName); - QString qttype = annotation.value; - if (!qttype.isEmpty()) - return std::move(qttype).toLatin1(); - - QString oldAnnotationName = u"com.trolltech.QtDBus.QtTypeName"_s; - if (paramId >= 0) - oldAnnotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); - annotation = annotations.value(oldAnnotationName); - qttype = annotation.value; - - if (qttype.isEmpty()) { - reporter.error(location, "unknown type `%s'\n", qPrintable(signature)); - reporter.note(location, - "you should add \"/>\n", - qPrintable(annotationName)); - - exit(1); - } - - reporter.warning(annotation.location, - "deprecated annotation '%s' found\n", - qPrintable(oldAnnotationName)); - reporter.note(annotation.location, - "suggest updating to '%s'\n", - qPrintable(annotationName)); - return std::move(qttype).toLatin1(); - } - - return QMetaType(type).name(); -} - -static QString nonConstRefArg(const QByteArray &arg) -{ - return QLatin1StringView(arg) + " &"_L1; -} - -static QString templateArg(const QByteArray &arg) -{ - if (!arg.endsWith('>')) - return QLatin1StringView(arg); - - return QLatin1StringView(arg) + " "_L1; -} - -static QString constRefArg(const QByteArray &arg) -{ - if (!arg.startsWith('Q')) - return QLatin1StringView(arg) + " "_L1; - else - return "const %1 &"_L1.arg(QLatin1StringView(arg)); -} - -static QStringList -makeArgNames(const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) -{ - QStringList retval; - const qsizetype numInputArgs = inputArgs.size(); - const qsizetype numOutputArgs = outputArgs.size(); - retval.reserve(numInputArgs + numOutputArgs); - for (qsizetype i = 0; i < numInputArgs; ++i) { - const QDBusIntrospection::Argument &arg = inputArgs.at(i); - QString name = arg.name; - if (name.isEmpty()) - name = u"in%1"_s.arg(i); - else - name.replace(u'-', u'_'); - while (retval.contains(name)) - name += "_"_L1; - retval << name; - } - for (qsizetype i = 0; i < numOutputArgs; ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString name = arg.name; - if (name.isEmpty()) - name = u"out%1"_s.arg(i); - else - name.replace(u'-', u'_'); - while (retval.contains(name)) - name += "_"_L1; - retval << name; - } - return retval; -} - -void QDBusXmlToCpp::writeArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs) -{ - // input args: - bool first = true; - qsizetype argPos = 0; - for (qsizetype i = 0; i < inputArgs.size(); ++i) { - const QDBusIntrospection::Argument &arg = inputArgs.at(i); - QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "In")); - - if (!first) - ts << ", "; - ts << type << argNames.at(argPos++); - first = false; - } - - argPos++; - - // output args - // yes, starting from 1 - for (qsizetype i = 1; i < outputArgs.size(); ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - - if (!first) - ts << ", "; - ts << nonConstRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out")) - << argNames.at(argPos++); - first = false; - } -} - -void QDBusXmlToCpp::writeSignalArgList(QTextStream &ts, - const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &outputArgs) -{ - bool first = true; - qsizetype argPos = 0; - for (qsizetype i = 0; i < outputArgs.size(); ++i) { - const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out")); - - if (!first) - ts << ", "; - ts << type << argNames.at(argPos++); - first = false; - } -} - -QString QDBusXmlToCpp::propertyGetter(const QDBusIntrospection::Property &property) -{ - auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1); - if (!annotation.value.isEmpty()) - return annotation.value; - - annotation = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1); - if (!annotation.value.isEmpty()) { - reporter.warning(annotation.location, - "deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found\n"); - reporter.note(annotation.location, - "suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n"); - return annotation.value; - } - - QString getter = property.name; - getter[0] = getter[0].toLower(); - return getter; -} - -QString QDBusXmlToCpp::propertySetter(const QDBusIntrospection::Property &property) -{ - auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1); - if (!annotation.value.isEmpty()) - return annotation.value; - - annotation = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1); - if (!annotation.value.isEmpty()) { - reporter.warning(annotation.location, - "deprecated annotation 'com.trolltech.QtDBus.propertySetter' found\n"); - reporter.note(annotation.location, - "suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n"); - return annotation.value; - } - - QString setter = "set"_L1 + property.name; - setter[3] = setter[3].toUpper(); - return setter; -} - -static QString methodName(const QDBusIntrospection::Method &method) -{ - QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s).value; - if (!name.isEmpty()) - return name; - - return method.name; -} - -static QString stringify(const QString &data) -{ - QString retval; - qsizetype i; - for (i = 0; i < data.size(); ++i) { - retval += u'\"'; - for (; i < data.size() && data[i] != u'\n' && data[i] != u'\r'; ++i) - if (data[i] == u'\"') - retval += "\\\""_L1; - else - retval += data[i]; - if (i + 1 < data.size() && data[i] == u'\r' && data[i + 1] == u'\n') - i++; - retval += "\\n\"\n"_L1; - } - return retval; -} - -static bool openFile(const QString &fileName, QFile &file) -{ - if (fileName.isEmpty()) - return false; - - bool isOk = false; - if (fileName == "-"_L1) { - isOk = file.open(stdout, QIODevice::WriteOnly | QIODevice::Text); - } else { - file.setFileName(fileName); - isOk = file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text); - } - - if (!isOk) - fprintf(stderr, - "%s: Unable to open '%s': %s\n", - PROGRAMNAME, - qPrintable(fileName), - qPrintable(file.errorString())); - return isOk; -} - -void QDBusXmlToCpp::writeProxy(const QString &filename, - const QDBusIntrospection::Interfaces &interfaces) -{ - // open the file - QString headerName = header(filename); - QByteArray headerData; - QTextStream hs(&headerData); - - QString cppName = cpp(filename); - QByteArray cppData; - QTextStream cs(&cppData); - - // write the header: - writeHeader(hs, true); - if (cppName != headerName) - writeHeader(cs, false); - - // include guards: - hs << "#pragma once" << "\n\n"; - - // include our stuff: - hs << "#include \n" << includeList; -#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) - hs << "#include \n"; -#else - hs << "#include \n" - "#include \n"; -#endif - - for (const QString &include : std::as_const(includes)) { - hs << "#include \"" << include << "\"\n"; - if (headerName.isEmpty()) - cs << "#include \"" << include << "\"\n"; - } - - for (const QString &include : std::as_const(globalIncludes)) { - hs << "#include <" << include << ">\n"; - if (headerName.isEmpty()) - cs << "#include <" << include << ">\n"; - } - - hs << "\n"; - - if (cppName != headerName) { - if (!headerName.isEmpty() && headerName != "-"_L1) - cs << "#include \"" << headerName << "\"\n\n"; - } - - for (const QDBusIntrospection::Interface *interface : interfaces) { - QString className = classNameForInterface(interface->name, Proxy); - - // comment: - hs << "/*\n" - " * Proxy class for interface " - << interface->name - << "\n" - " */\n"; - cs << "/*\n" - " * Implementation of interface class " - << className - << "\n" - " */\n\n"; - - // class header: - hs << "class " << className - << ": public QDBusAbstractInterface\n" - "{\n" - " Q_OBJECT\n"; - - // the interface name - hs << "public:\n" - " static inline const char *staticInterfaceName()\n" - " { return \"" - << interface->name << "\"; }\n\n"; - - // constructors/destructors: - hs << " " << className - << "(const QString &service, const QString &path, const QDBusConnection &connection, " - "QObject *parent = nullptr);\n\n" - " ~" - << className << "() override = default;\n\n"; - cs << className << "::" << className - << "(const QString &service, const QString &path, const QDBusConnection &connection, " - "QObject *parent)\n" - " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, " - "parent)\n" - "{\n" - "}\n\n"; - - // properties: - for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.location, property.type, property.annotations); - QString getter = propertyGetter(property); - QString setter = propertySetter(property); - - hs << " Q_PROPERTY(" << type << " " << property.name; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) - // it's readable - hs << " READ " << getter; - - // setter - if (property.access != QDBusIntrospection::Property::Read) - // it's writeable - hs << " WRITE " << setter; - - hs << ")\n"; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) { - hs << " [[nodiscard]] virtual inline " << type << " " << getter - << "() const\n" - " { return qvariant_cast< " - << type << " >(property(\"" << property.name << "\")); }\n"; - } - - // setter: - if (property.access != QDBusIntrospection::Property::Read) { - hs << " virtual inline void " << setter << "(" << constRefArg(type) - << "value)\n" - " { setProperty(\"" - << property.name << "\", QVariant::fromValue(value)); }\n"; - } - - hs << "\n"; - } - - // methods: - hs << "public Q_SLOTS: // METHODS\n"; - for (const QDBusIntrospection::Method &method : interface->methods) { - bool isDeprecated = - method.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1; - bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; - if (isNoReply && !method.outputArgs.isEmpty()) { - reporter.warning(method.location, - "method %s in interface %s is marked 'no-reply' but has output " - "arguments.\n", - qPrintable(method.name), - qPrintable(interface->name)); - continue; - } - - if (isDeprecated) - hs << " [[deprecated]] "; - else - hs << " "; - - if (isNoReply) { - hs << "Q_NOREPLY virtual inline void "; - } else { - hs << "virtual inline QDBusPendingReply<"; - for (qsizetype i = 0; i < method.outputArgs.size(); ++i) - hs << (i > 0 ? ", " : "") - << templateArg(qtTypeName(method.outputArgs.at(i).location, - method.outputArgs.at(i).type, - method.annotations, - i, - "Out")); - hs << "> "; - } - - hs << methodName(method) << "("; - - QStringList argNames = makeArgNames(method.inputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs); - - hs << ")\n" - " {\n" - " QList argumentList;\n"; - - if (!method.inputArgs.isEmpty()) { - hs << " argumentList"; - for (qsizetype argPos = 0; argPos < method.inputArgs.size(); ++argPos) - hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";\n"; - } - - if (isNoReply) - hs << " callWithArgumentList(QDBus::NoBlock, " - "QStringLiteral(\"" - << method.name << "\"), argumentList);\n"; - else - hs << " return asyncCallWithArgumentList(QStringLiteral(\"" << method.name - << "\"), argumentList);\n"; - - // close the function: - hs << " }\n"; - - if (method.outputArgs.size() > 1) { - // generate the old-form QDBusReply methods with multiple incoming parameters - hs << (isDeprecated ? " Q_DECL_DEPRECATED " : " ") << "inline QDBusReply<" - << templateArg(qtTypeName(method.outputArgs.first().location, - method.outputArgs.first().type, - method.annotations, - 0, - "Out")) - << "> "; - hs << method.name << "("; - - QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - - hs << ")\n" - " {\n" - " QList argumentList;\n"; - - qsizetype argPos = 0; - if (!method.inputArgs.isEmpty()) { - hs << " argumentList"; - for (argPos = 0; argPos < method.inputArgs.size(); ++argPos) - hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";\n"; - } - - hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - "QStringLiteral(\"" - << method.name << "\"), argumentList);\n"; - - argPos++; - hs << " if (reply.type() == QDBusMessage::ReplyMessage && " - "reply.arguments().size() == " - << method.outputArgs.size() << ") {\n"; - - // yes, starting from 1 - for (qsizetype i = 1; i < method.outputArgs.size(); ++i) - hs << " " << argNames.at(argPos++) << " = qdbus_cast<" - << templateArg(qtTypeName(method.outputArgs.at(i).location, - method.outputArgs.at(i).type, - method.annotations, - i, - "Out")) - << ">(reply.arguments().at(" << i << "));\n"; - hs << " }\n" - " return reply;\n" - " }\n"; - } - - hs << "\n"; - } - - hs << "Q_SIGNALS: // SIGNALS\n"; - for (const QDBusIntrospection::Signal &signal : interface->signals_) { - hs << " "; - if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1) - hs << "Q_DECL_DEPRECATED "; - - hs << "void " << signal.name << "("; - - QStringList argNames = makeArgNames(signal.outputArgs); - writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - - hs << ");\n"; // finished for header - } - - // close the class: - hs << "};\n\n"; - } - - if (!skipNamespaces) { - QStringList last; - QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin(); - do { - QStringList current; - QString name; - if (it != interfaces.constEnd()) { - current = it->constData()->name.split(u'.'); - name = current.takeLast(); - } - - qsizetype i = 0; - while (i < current.size() && i < last.size() && current.at(i) == last.at(i)) - ++i; - - // i parts matched - // close last.arguments().size() - i namespaces: - for (qsizetype j = i; j < last.size(); ++j) - hs << QString((last.size() - j - 1 + i) * 2, u' ') << "}\n"; - - // open current.arguments().size() - i namespaces - for (qsizetype j = i; j < current.size(); ++j) - hs << QString(j * 2, u' ') << "namespace " << current.at(j) << " {\n"; - - // add this class: - if (!name.isEmpty()) { - hs << QString(current.size() * 2, u' ') << "using " << name - << " = ::" << classNameForInterface(it->constData()->name, Proxy) << ";\n"; - } - - if (it == interfaces.constEnd()) - break; - ++it; - last = current; - } while (true); - } - - QString mocName = moc(filename); - if (includeMocs && !mocName.isEmpty()) - cs << "\n" - "#include \"" - << mocName << "\"\n"; - - cs.flush(); - hs.flush(); - - QFile file; - const bool headerOpen = openFile(headerName, file); - if (headerOpen) - file.write(headerData); - - if (headerName == cppName) { - if (headerOpen) - file.write(cppData); - } else { - QFile cppFile; - if (openFile(cppName, cppFile)) - cppFile.write(cppData); - } -} - -void QDBusXmlToCpp::writeAdaptor(const QString &filename, - const QDBusIntrospection::Interfaces &interfaces) -{ - // open the file - QString headerName = header(filename); - QByteArray headerData; - QTextStream hs(&headerData); - - QString cppName = cpp(filename); - QByteArray cppData; - QTextStream cs(&cppData); - - // write the headers - writeHeader(hs, false); - if (cppName != headerName) - writeHeader(cs, true); - - // include guards: - QString includeGuard; - if (!headerName.isEmpty() && headerName != "-"_L1) { - includeGuard = headerName.toUpper().replace(u'.', u'_'); - qsizetype pos = includeGuard.lastIndexOf(u'/'); - if (pos != -1) - includeGuard = includeGuard.mid(pos + 1); - } else { - includeGuard = u"QDBUSXML2CPP_ADAPTOR"_s; - } - - hs << "#ifndef " << includeGuard - << "\n" - "#define " - << includeGuard << "\n\n"; - - // include our stuff: - hs << "#include \n"; - if (cppName == headerName) - hs << "#include \n" - "#include \n"; -#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) - hs << "#include \n"; -#else - hs << "#include \n" - "#include \n"; -#endif - - for (const QString &include : std::as_const(includes)) { - hs << "#include \"" << include << "\"\n"; - if (headerName.isEmpty()) - cs << "#include \"" << include << "\"\n"; - } - - for (const QString &include : std::as_const(globalIncludes)) { - hs << "#include <" << include << ">\n"; - if (headerName.isEmpty()) - cs << "#include <" << include << ">\n"; - } - - if (cppName != headerName) { - if (!headerName.isEmpty() && headerName != "-"_L1) - cs << "#include \"" << headerName << "\"\n"; - - cs << "#include \n" << includeList << "\n"; - hs << forwardDeclarations; - } else { - hs << includeList; - } - - hs << "\n"; - - QString parent = parentClassName; - if (parentClassName.isEmpty()) - parent = u"QObject"_s; - - for (const QDBusIntrospection::Interface *interface : interfaces) { - QString className = classNameForInterface(interface->name, Adaptor); - - // comment: - hs << "/*\n" - " * Adaptor class for interface " - << interface->name - << "\n" - " */\n"; - cs << "/*\n" - " * Implementation of adaptor class " - << className - << "\n" - " */\n\n"; - - // class header: - hs << "class " << className - << ": public QDBusAbstractAdaptor\n" - "{\n" - " Q_OBJECT\n" - " Q_CLASSINFO(\"D-Bus Interface\", \"" - << interface->name - << "\")\n" - " Q_CLASSINFO(\"D-Bus Introspection\", \"\"\n" - << stringify(interface->introspection) - << " \"\")\n" - "public:\n" - " " - << className << "(" << parent - << " *parent);\n" - " ~" - << className << "() override;\n\n"; - - if (!parentClassName.isEmpty()) - hs << " inline " << parent - << " *parent() const\n" - " { return static_cast<" - << parent << " *>(QObject::parent()); }\n\n"; - - // constructor/destructor - cs << className << "::" << className << "(" << parent - << " *parent)\n" - " : QDBusAbstractAdaptor(parent)\n" - "{\n" - " // constructor\n" - " setAutoRelaySignals(true);\n" - "}\n\n" - << className << "::~" << className - << "()\n" - "{\n" - " // destructor\n" - "}\n\n"; - - hs << "public: // PROPERTIES\n"; - for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.location, property.type, property.annotations); - QString constRefType = constRefArg(type); - QString getter = propertyGetter(property); - QString setter = propertySetter(property); - - hs << " Q_PROPERTY(" << type << " " << property.name; - if (property.access != QDBusIntrospection::Property::Write) - hs << " READ " << getter; - if (property.access != QDBusIntrospection::Property::Read) - hs << " WRITE " << setter; - hs << ")\n"; - - // getter: - if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;\n"; - cs << type << " " << className << "::" << getter - << "() const\n" - "{\n" - " // get the value of property " - << property.name - << "\n" - " return qvariant_cast< " - << type << " >(parent()->property(\"" << property.name - << "\"));\n" - "}\n\n"; - } - - // setter - if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);\n"; - cs << "void " << className << "::" << setter << "(" << constRefType - << "value)\n" - "{\n" - " // set the value of property " - << property.name - << "\n" - " parent()->setProperty(\"" - << property.name << "\", QVariant::fromValue(value"; - if (constRefType.contains("QDBusVariant"_L1)) - cs << ".variant()"; - cs << "));\n" - "}\n\n"; - } - - hs << "\n"; - } - - hs << "public Q_SLOTS: // METHODS\n"; - for (const QDBusIntrospection::Method &method : interface->methods) { - bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; - if (isNoReply && !method.outputArgs.isEmpty()) { - reporter.warning(method.location, - "method %s in interface %s is marked 'no-reply' but has output " - "arguments.\n", - qPrintable(method.name), - qPrintable(interface->name)); - continue; - } - - hs << " "; - QByteArray returnType; - if (isNoReply) { - hs << "Q_NOREPLY void "; - cs << "void "; - } else if (method.outputArgs.isEmpty()) { - hs << "void "; - cs << "void "; - } else { - returnType = qtTypeName(method.outputArgs.first().location, - method.outputArgs.first().type, - method.annotations, - 0, - "Out"); - hs << returnType << " "; - cs << returnType << " "; - } - - QString name = methodName(method); - hs << name << "("; - cs << className << "::" << name << "("; - - QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); - writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - - hs << ");\n"; // finished for header - cs << ")\n" - "{\n" - " // handle method call " - << interface->name << "." << methodName(method) << "\n"; - - // make the call - bool usingInvokeMethod = false; - if (parentClassName.isEmpty() && method.inputArgs.size() <= 10 - && method.outputArgs.size() <= 1) - usingInvokeMethod = true; - - if (usingInvokeMethod) { - // we are using QMetaObject::invokeMethod - if (!returnType.isEmpty()) - cs << " " << returnType << " " << argNames.at(method.inputArgs.size()) - << ";\n"; - - static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; - cs << invoke << name << "\""; - - if (!method.outputArgs.isEmpty()) - cs << ", Q_RETURN_ARG(" - << qtTypeName(method.outputArgs.at(0).location, - method.outputArgs.at(0).type, - method.annotations, - 0, - "Out") - << ", " << argNames.at(method.inputArgs.size()) << ")"; - - for (qsizetype i = 0; i < method.inputArgs.size(); ++i) - cs << ", Q_ARG(" - << qtTypeName(method.inputArgs.at(i).location, - method.inputArgs.at(i).type, - method.annotations, - i, - "In") - << ", " << argNames.at(i) << ")"; - - cs << ");\n"; - - if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.size()) << ";\n"; - } else { - if (parentClassName.isEmpty()) - cs << " //"; - else - cs << " "; - - if (!method.outputArgs.isEmpty()) - cs << "return "; - - if (parentClassName.isEmpty()) - cs << "static_cast(parent())->"; - else - cs << "parent()->"; - cs << name << "("; - - qsizetype argPos = 0; - bool first = true; - for (qsizetype i = 0; i < method.inputArgs.size(); ++i) { - cs << (first ? "" : ", ") << argNames.at(argPos++); - first = false; - } - ++argPos; // skip retval, if any - for (qsizetype i = 1; i < method.outputArgs.size(); ++i) { - cs << (first ? "" : ", ") << argNames.at(argPos++); - first = false; - } - - cs << ");\n"; - } - cs << "}\n\n"; - } - - hs << "Q_SIGNALS: // SIGNALS\n"; - for (const QDBusIntrospection::Signal &signal : interface->signals_) { - hs << " void " << signal.name << "("; - - QStringList argNames = makeArgNames(signal.outputArgs); - writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - - hs << ");\n"; // finished for header - } - - // close the class: - hs << "};\n\n"; - } - - // close the include guard - hs << "#endif\n"; - - QString mocName = moc(filename); - if (includeMocs && !mocName.isEmpty()) - cs << "\n" - "#include \"" - << mocName << "\"\n"; - - cs.flush(); - hs.flush(); - - QFile file; - const bool headerOpen = openFile(headerName, file); - if (headerOpen) - file.write(headerData); - - if (headerName == cppName) { - if (headerOpen) - file.write(cppData); - } else { - QFile cppFile; - if (openFile(cppName, cppFile)) - cppFile.write(cppData); - } -} - -int QDBusXmlToCpp::run(const QCoreApplication &app) -{ - QCommandLineParser parser; - parser.setApplicationDescription( - "Produces the C++ code to implement the interfaces defined in the input file.\n\n" - "If the file name given to the options -a and -p does not end in .cpp or .h, the\n" - "program will automatically append the suffixes and produce both files.\n" - "You can also use a colon (:) to separate the header name from the source file\n" - "name, as in '-a filename_p.h:filename.cpp'.\n\n" - "If you pass a dash (-) as the argument to either -p or -a, the output is written\n" - "to the standard output."_L1); - - parser.addHelpOption(); - parser.addVersionOption(); - parser.addPositionalArgument(u"xml-or-xml-file"_s, u"XML file to use."_s); - parser.addPositionalArgument(u"interfaces"_s, - u"List of interfaces to use."_s, - u"[interfaces ...]"_s); - - QCommandLineOption adapterCodeOption(QStringList{ u"a"_s, u"adaptor"_s }, - u"Write the adaptor code to "_s, - u"filename"_s); - parser.addOption(adapterCodeOption); - - QCommandLineOption classNameOption( - QStringList{ u"c"_s, u"classname"_s }, - u"Use as the class name for the generated classes. " - u"This option can only be used when processing a single interface."_s, - u"classname"_s); - parser.addOption(classNameOption); - - QCommandLineOption addIncludeOption(QStringList{ u"i"_s, u"include"_s }, - u"Add #include \"filename\" to the output"_s, - u"filename"_s); - parser.addOption(addIncludeOption); - - QCommandLineOption addGlobalIncludeOption(QStringList{ u"I"_s, u"global-include"_s }, - u"Add #include to the output"_s, - u"filename"_s); - parser.addOption(addGlobalIncludeOption); - - QCommandLineOption adapterParentOption( - u"l"_s, - u"When generating an adaptor, use as the parent class"_s, - u"classname"_s); - parser.addOption(adapterParentOption); - - QCommandLineOption mocIncludeOption( - QStringList{ u"m"_s, u"moc"_s }, - u"Generate #include \"filename.moc\" statements in the .cpp files"_s); - parser.addOption(mocIncludeOption); - - QCommandLineOption noNamespaceOption(QStringList{ u"N"_s, u"no-namespaces"_s }, - u"Don't use namespaces"_s); - parser.addOption(noNamespaceOption); - - QCommandLineOption proxyCodeOption(QStringList{ u"p"_s, u"proxy"_s }, - u"Write the proxy code to "_s, - u"filename"_s); - parser.addOption(proxyCodeOption); - - QCommandLineOption verboseOption(QStringList{ u"V"_s, u"verbose"_s }, u"Be verbose."_s); - parser.addOption(verboseOption); - - parser.process(app); - - QString adaptorFile = parser.value(adapterCodeOption); - globalClassName = parser.value(classNameOption); - includes = parser.values(addIncludeOption); - globalIncludes = parser.values(addGlobalIncludeOption); - parentClassName = parser.value(adapterParentOption); - includeMocs = parser.isSet(mocIncludeOption); - skipNamespaces = parser.isSet(noNamespaceOption); - QString proxyFile = parser.value(proxyCodeOption); - bool verbose = parser.isSet(verboseOption); - - wantedInterfaces = parser.positionalArguments(); - if (!wantedInterfaces.isEmpty()) { - inputFile = wantedInterfaces.takeFirst(); - - QFileInfo inputInfo(inputFile); - if (!inputInfo.exists() || !inputInfo.isFile() || !inputInfo.isReadable()) { - qCritical("Error: Input %s is not a file or cannot be accessed\n", - qPrintable(inputFile)); - return 1; - } - } - - if (verbose) - QLoggingCategory::setFilterRules(u"dbus.parser.debug=true"_s); - - QDBusIntrospection::Interfaces interfaces = readInput(); - cleanInterfaces(interfaces); - - if (!globalClassName.isEmpty() && interfaces.count() != 1) { - qCritical("Option -c/--classname can only be used with a single interface.\n"); - return 1; - } - - QStringList args = app.arguments(); - args.removeFirst(); - commandLine = PROGRAMNAME " "_L1 + args.join(u' '); - - if (!proxyFile.isEmpty() || adaptorFile.isEmpty()) - writeProxy(proxyFile, interfaces); - - if (!adaptorFile.isEmpty()) - writeAdaptor(adaptorFile, interfaces); - - return 0; -} - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME)); - QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION)); - - return QDBusXmlToCpp().run(app); -} From 261417050f1f26a3272599a3c1250afbf0c37749 Mon Sep 17 00:00:00 2001 From: myml Date: Mon, 21 Jul 2025 17:29:17 +0800 Subject: [PATCH 108/366] refactor: extract OSTree pull options initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracted the common OSTree pull options initialization code into a separate method initOStreePullOptions to avoid code duplication. The method handles: 1. Creating GVariantBuilder with common options 2. Setting refs and user agent 3. Disabling static deltas by default This change makes the pull operation code cleaner and more maintainable by centralizing the options configuration logic. refactor: 提取 OSTree 拉取选项初始化代码 将 OSTree 拉取选项的初始化代码提取到单独的 initOStreePullOptions 方法中 以避免重复代码。该方法处理: 1. 创建带有通用选项的 GVariantBuilder 2. 设置refs和user-agent 3. 默认禁用静态增量 通过集中管理选项配置逻辑,使拉取操作代码更清晰且更易于维护。 --- .../src/linglong/repo/ostree_repo.cpp | 75 +++++++------------ libs/linglong/src/linglong/repo/ostree_repo.h | 5 +- 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 62d74ff82..e6201b75e 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1270,26 +1270,37 @@ utils::error::Result OSTreeRepo::prune() return LINGLONG_OK; } -// 在pull之前获取commit size,用于计算进度,需要服务器支持ostree.sizes -utils::error::Result> -OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refString) noexcept +// 初始化一个GVariantBuilder +GVariantBuilder OSTreeRepo::initOStreePullOptions(const std::string &ref) noexcept { - LINGLONG_TRACE("get commit size " + QString::fromStdString(refString)); -#if OSTREE_CHECK_VERSION(2020, 1) - g_autoptr(GError) gErr = nullptr; - // 获取commit的metadata - std::array refs{ refString.c_str(), nullptr }; - std::string userAgent = "linglong/" LINGLONG_VERSION; + std::array refs{ ref.c_str(), nullptr }; GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{s@v}", - "refs", - g_variant_new_variant(g_variant_new_strv(refs.data(), -1))); + std::string userAgent = "linglong/" LINGLONG_VERSION; g_variant_builder_add(&builder, "{s@v}", "append-user-agent", g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); + g_variant_builder_add(&builder, + "{s@v}", + "disable-static-deltas", + g_variant_new_variant(g_variant_new_boolean(true))); + + g_variant_builder_add(&builder, + "{s@v}", + "refs", + g_variant_new_variant(g_variant_new_strv(refs.data(), -1))); + return builder; +} + +// 在pull之前获取commit size,用于计算进度,需要服务器支持ostree.sizes +utils::error::Result> +OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refString) noexcept +{ + LINGLONG_TRACE("get commit size " + QString::fromStdString(refString)); +#if OSTREE_CHECK_VERSION(2020, 1) + g_autoptr(GError) gErr = nullptr; + GVariantBuilder builder = this->initOStreePullOptions(refString); // 设置flags只获取commit的metadata g_variant_builder_add( &builder, @@ -1297,6 +1308,7 @@ OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refStrin "flags", g_variant_new_variant(g_variant_new_int32(OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY))); g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); + // 获取commit的metadata auto status = ostree_repo_pull_with_options(this->ostreeRepo.get(), remote.c_str(), pull_options, @@ -1308,7 +1320,7 @@ OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refStrin } // 使用refString获取commit的sha256 g_autofree char *resolved_rev = NULL; - if (!ostree_repo_resolve_rev(this->ostreeRepo.get(), refs[0], FALSE, &resolved_rev, &gErr)) { + if (!ostree_repo_resolve_rev(this->ostreeRepo.get(), refString.c_str(), FALSE, &resolved_rev, &gErr)) { return LINGLONG_ERR("ostree_repo_resolve_rev", gErr); } // 使用sha256获取commit id @@ -1372,7 +1384,6 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, utils::Transaction transaction; auto *cancellable = taskContext.cancellable(); - std::array refs{ refString.c_str(), nullptr }; ostreeUserData data{ .taskContext = &taskContext }; auto sizes = this->getCommitSize(pullRepo.alias.value_or(pullRepo.name), refString); @@ -1390,21 +1401,7 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, g_autoptr(GError) gErr = nullptr; - std::string userAgent = "linglong/" LINGLONG_VERSION; - GVariantBuilder builder; - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{s@v}", - "refs", - g_variant_new_variant(g_variant_new_strv(refs.data(), -1))); - g_variant_builder_add(&builder, - "{s@v}", - "append-user-agent", - g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); - g_variant_builder_add(&builder, - "{s@v}", - "disable-static-deltas", - g_variant_new_variant(g_variant_new_boolean(true))); + auto builder = this->initOStreePullOptions(refString); g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); // 这里不能使用g_main_context_push_thread_default,因为会阻塞Qt的事件循环 @@ -1434,23 +1431,9 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, refString = ostreeSpecFromReference(reference, std::nullopt, module); qWarning() << "fallback to module runtime, pull " << QString::fromStdString(refString); - refs[0] = refString.c_str(); g_clear_error(&gErr); - GVariantBuilder builder; - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, - "{s@v}", - "refs", - g_variant_new_variant(g_variant_new_strv(refs.data(), -1))); - g_variant_builder_add(&builder, - "{s@v}", - "append-user-agent", - g_variant_new_variant(g_variant_new_string(userAgent.c_str()))); - g_variant_builder_add(&builder, - "{s@v}", - "disable-static-deltas", - g_variant_new_variant(g_variant_new_boolean(true))); + GVariantBuilder builder = this->initOStreePullOptions(refString); g_autoptr(GVariant) pull_options = g_variant_ref_sink(g_variant_builder_end(&builder)); @@ -1473,7 +1456,7 @@ void OSTreeRepo::pull(service::PackageTask &taskContext, g_clear_error(&gErr); if (ostree_repo_read_commit(this->ostreeRepo.get(), - refs[0], + refString.c_str(), &layerRootDir, &commit, cancellable, diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index c755cf092..b93b7081a 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -82,8 +82,6 @@ class OSTreeRepo : public QObject const std::string &url, const package::Reference &reference, const std::string &module = "binary") const noexcept; - utils::error::Result> getCommitSize(const std::string &remote, - const std::string &refString) noexcept; void pull(service::PackageTask &taskContext, const package::Reference &reference, const std::string &module = "binary", @@ -206,6 +204,9 @@ class OSTreeRepo : public QObject const std::optional &fileSuffix = std::nullopt); // exportEntries will clear the entries/share and export all applications to the entries/share utils::error::Result exportAllEntries() noexcept; + utils::error::Result> getCommitSize(const std::string &remote, + const std::string &refString) noexcept; + GVariantBuilder initOStreePullOptions(const std::string &ref) noexcept; }; } // namespace linglong::repo From b7c6a7d47db7dec2bcdd745eb0890aeeaeb7eca4 Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 22 Jul 2025 11:24:48 +0800 Subject: [PATCH 109/366] chore: remove desktop entry utility and tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Removed DesktopEntry class implementation and its header file 2. Removed corresponding test cases from ll-tests 3. Updated CMakeLists.txt to reflect these removals 4. The functionality appears to be unused in the project 5. Cleanup helps reduce maintenance burden and code complexity chore: 移除桌面入口工具类和测试 1. 移除了 DesktopEntry 类的实现和头文件 2. 从 ll-tests 中移除了对应的测试用例 3. 更新了 CMakeLists.txt 以反映这些移除 4. 该功能在项目中似乎未被使用 5. 清理有助于减少维护负担和代码复杂度 --- .github/workflows/build.yaml | 3 + libs/linglong/tests/ll-tests/CMakeLists.txt | 1 - .../linglong/utils/xdg/desktop_entry_test.cpp | 113 --------------- libs/utils/CMakeLists.txt | 2 - .../src/linglong/utils/xdg/desktop_entry.cpp | 13 -- .../src/linglong/utils/xdg/desktop_entry.h | 137 ------------------ 6 files changed, 3 insertions(+), 266 deletions(-) delete mode 100644 libs/linglong/tests/ll-tests/src/linglong/utils/xdg/desktop_entry_test.cpp delete mode 100644 libs/utils/src/linglong/utils/xdg/desktop_entry.cpp delete mode 100644 libs/utils/src/linglong/utils/xdg/desktop_entry.h diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e3775558f..1fa1c7e1f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -54,3 +54,6 @@ jobs: .. make -j$(nproc) + - name: Run tests + run: | + ./build/libs/linglong/tests/ll-tests/ll-tests \ No newline at end of file diff --git a/libs/linglong/tests/ll-tests/CMakeLists.txt b/libs/linglong/tests/ll-tests/CMakeLists.txt index 2b6c4fd8a..6f902ee6e 100644 --- a/libs/linglong/tests/ll-tests/CMakeLists.txt +++ b/libs/linglong/tests/ll-tests/CMakeLists.txt @@ -24,7 +24,6 @@ pfl_add_executable( src/linglong/utils/error/result_test.cpp src/linglong/utils/sha256_test.cpp src/linglong/utils/transaction_test.cpp - src/linglong/utils/xdg/desktop_entry_test.cpp src/linglong/repo/config_test.cpp src/main.cpp COMPILE_FEATURES diff --git a/libs/linglong/tests/ll-tests/src/linglong/utils/xdg/desktop_entry_test.cpp b/libs/linglong/tests/ll-tests/src/linglong/utils/xdg/desktop_entry_test.cpp deleted file mode 100644 index a5a061add..000000000 --- a/libs/linglong/tests/ll-tests/src/linglong/utils/xdg/desktop_entry_test.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#include - -// compatible with old gtest -#ifndef GTEST_SKIP -# define GTEST_SKIP() return -#endif - -#include "linglong/utils/xdg/desktop_entry.h" - -#include - -using namespace linglong::utils::xdg; - -TEST(UtilsXDGDesktopEntry, Groups) -{ - auto entry = DesktopEntry::New("data/utils/xdg/org.deepin.calculator.desktop"); - ASSERT_EQ(entry.has_value(), true) << entry.error().message().toStdString(); - - auto groups = entry->groups(); - ASSERT_EQ(groups.contains(DesktopEntry::MainSection), true) << groups.join(", ").toStdString(); - ASSERT_EQ(groups.size(), 1); -} - -TEST(UtilsXDGDesktopEntry, GetString) -{ - auto entry = DesktopEntry::New("data/utils/xdg/org.deepin.calculator.desktop"); - ASSERT_EQ(entry.has_value(), true) << entry.error().message().toStdString(); - - auto testGetStringValue = [&entry](const QString &key, const QString &expectedValue) { - auto value = entry->getValue(key); - ASSERT_EQ(value.has_value(), true) << value.error().message().toStdString(); - ASSERT_EQ(value->toStdString(), expectedValue.toStdString()); - }; - - const auto testGetStringValueCases = QMap{ - { "Name", "Calculator" }, - { "Exec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator" }, - { "TryExec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator" }, - { "Terminal", "false" }, - }; - - for (auto it = testGetStringValueCases.cbegin(); it != testGetStringValueCases.cend(); ++it) { - testGetStringValue(it.key(), it.value()); - } -} - -TEST(UtilsXDGDesktopEntry, SetString) -{ - auto entry = DesktopEntry::New("data/utils/xdg/org.deepin.calculator.desktop"); - ASSERT_EQ(entry.has_value(), true) << entry.error().message().toStdString(); - - auto testSetStringValue = [&entry](const QString &key, const QString &expectedValue) { - entry->setValue(key, expectedValue); - - auto value = entry->getValue(key); - ASSERT_EQ(value.has_value(), true) << value.error().message().toStdString(); - ASSERT_EQ(value->toStdString(), expectedValue.toStdString()); - }; - - const auto testGetStringValueCases = QMap{ - { "Name", "Calculator1" }, - { "Exec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator1" }, - { "TryExec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator1j" }, - { "Terminal", "false1" }, - }; - - for (auto it = testGetStringValueCases.cbegin(); it != testGetStringValueCases.cend(); ++it) { - testSetStringValue(it.key(), it.value()); - } -} - -TEST(UtilsXDGDesktopEntry, SaveToFile) -{ - auto entry = DesktopEntry::New("data/utils/xdg/org.deepin.calculator.desktop"); - ASSERT_EQ(entry.has_value(), true) << entry.error().message().toStdString(); - - QTemporaryFile tmpFile; - tmpFile.open(); - if (!(tmpFile.isOpen() && tmpFile.isWritable())) { - qCritical() << "Cannot get a temporary file."; - GTEST_SKIP(); - } - tmpFile.close(); - - auto result = entry->saveToFile(tmpFile.fileName()); - ASSERT_EQ(result.has_value(), true); - - entry = DesktopEntry::New(tmpFile.fileName()); - ASSERT_EQ(entry.has_value(), true) << entry.error().message().toStdString(); - - const auto testGetStringValueCases = QMap{ - { "Name", "Calculator" }, - { "Exec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator" }, - { "TryExec", "/opt/apps/org.deepin.calculator/files/bin/deepin-calculator" }, - { "Terminal", "false" }, - }; - - auto testGetStringValue = [&entry](const QString &key, const QString &expectedValue) { - auto value = entry->getValue(key); - ASSERT_EQ(value.has_value(), true) << value.error().message().toStdString(); - ASSERT_EQ(value->toStdString(), expectedValue.toStdString()); - }; - - for (auto it = testGetStringValueCases.cbegin(); it != testGetStringValueCases.cend(); ++it) { - testGetStringValue(it.key(), it.value()); - } -} diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt index a39218294..a8babfb2a 100644 --- a/libs/utils/CMakeLists.txt +++ b/libs/utils/CMakeLists.txt @@ -41,8 +41,6 @@ pfl_add_library( src/linglong/utils/transaction.h src/linglong/utils/file.cpp src/linglong/utils/file.h - src/linglong/utils/xdg/desktop_entry.cpp - src/linglong/utils/xdg/desktop_entry.h src/linglong/utils/xdg/directory.h src/linglong/utils/gkeyfile_wrapper.h src/linglong/utils/hooks.cpp diff --git a/libs/utils/src/linglong/utils/xdg/desktop_entry.cpp b/libs/utils/src/linglong/utils/xdg/desktop_entry.cpp deleted file mode 100644 index 4c4b335aa..000000000 --- a/libs/utils/src/linglong/utils/xdg/desktop_entry.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#include "linglong/utils/xdg/desktop_entry.h" - -namespace linglong::utils::xdg { - -const DesktopEntry::SectionName DesktopEntry::MainSection = "Desktop Entry"; - -} // namespace linglong::utils::xdg diff --git a/libs/utils/src/linglong/utils/xdg/desktop_entry.h b/libs/utils/src/linglong/utils/xdg/desktop_entry.h deleted file mode 100644 index b8a0f6818..000000000 --- a/libs/utils/src/linglong/utils/xdg/desktop_entry.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. - * - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#pragma once - -#include "linglong/utils/error/error.h" - -#include -#include - -#include -#include - -namespace linglong::utils::xdg { - -class DesktopEntry final -{ - // constructors -public: - DesktopEntry(DesktopEntry &&) = default; - DesktopEntry(const DesktopEntry &) = delete; - auto operator=(DesktopEntry &&) -> DesktopEntry & = default; - auto operator=(const DesktopEntry &) -> DesktopEntry & = delete; - ~DesktopEntry() = default; - - static auto New(const QString &filePath) -> error::Result - { - LINGLONG_TRACE(QString("create DesktopEntry for %1").arg(filePath)); - - auto desktopEntryFile = QFile(filePath); - if (!desktopEntryFile.exists()) { - return LINGLONG_ERR("no such desktop entry file"); - } - - g_autoptr(GError) gErr = nullptr; - DesktopEntry entry; - g_key_file_load_from_file(entry.gKeyFile.get(), - filePath.toLocal8Bit().constData(), - G_KEY_FILE_KEEP_TRANSLATIONS, - &gErr); - if (gErr != nullptr) { - return LINGLONG_ERR("g_key_file_load_from_file", gErr); - } - - return entry; - } - -private: - DesktopEntry() - : gKeyFile(std::unique_ptr(g_key_file_new(), - g_key_file_free)) { }; - - // types -public: - using SectionName = QString; - -public: - static const SectionName MainSection; - - // data members -private: - std::unique_ptr gKeyFile; - - // methods -public: - template - void setValue(const QString &key, const Value &value, const SectionName §ion = MainSection); - - template - auto getValue(const QString &key, const SectionName §ion = MainSection) const - -> error::Result; - - auto groups() -> QStringList - { - gsize length = 0; - g_auto(GStrv) groups = g_key_file_get_groups(this->gKeyFile.get(), &length); - - QStringList result; - for (gsize i = 0; i < length; i++) { - auto group = groups[i]; // NOLINT - result << group; - } - - return result; - } - - auto saveToFile(const QString &filepath) -> error::Result - { - LINGLONG_TRACE(QString("save to %1").arg(filepath)); - - g_autoptr(GError) gErr = nullptr; - - g_key_file_save_to_file(this->gKeyFile.get(), filepath.toLocal8Bit().constData(), &gErr); - if (gErr != nullptr) { - return LINGLONG_ERR("g_key_file_save_to_file", gErr); - } - - return LINGLONG_OK; - } -}; - -template <> -inline void DesktopEntry::setValue(const QString &key, - const QString &value, - const SectionName §ion) -{ - g_key_file_set_string(this->gKeyFile.get(), - section.toLocal8Bit().constData(), - key.toLocal8Bit().constData(), - value.toLocal8Bit().constData()); -} - -template <> -[[nodiscard]] inline auto DesktopEntry::getValue(const QString &key, - const SectionName §ion) const - -> error::Result -{ - LINGLONG_TRACE(QString("get %1 from %2").arg(key, section)); - - g_autoptr(GError) gErr = nullptr; - - g_autofree gchar *value = g_key_file_get_string(this->gKeyFile.get(), - section.toLocal8Bit().constData(), - key.toLocal8Bit().constData(), - &gErr); - - if (gErr != nullptr) { - return LINGLONG_ERR("g_key_file_get_string", gErr); - } - - return value; -} - -} // namespace linglong::utils::xdg From 995a71e85a7d5abe9dbde17c1910a89536db559c Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 08:36:55 +0000 Subject: [PATCH 110/366] style: format code with ClangFormat and Prettier This commit fixes the style issues introduced in 2614170 according to the output from ClangFormat and Prettier. Details: None --- libs/linglong/src/linglong/repo/ostree_repo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index e6201b75e..53241853f 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1320,7 +1320,11 @@ OSTreeRepo::getCommitSize(const std::string &remote, const std::string &refStrin } // 使用refString获取commit的sha256 g_autofree char *resolved_rev = NULL; - if (!ostree_repo_resolve_rev(this->ostreeRepo.get(), refString.c_str(), FALSE, &resolved_rev, &gErr)) { + if (!ostree_repo_resolve_rev(this->ostreeRepo.get(), + refString.c_str(), + FALSE, + &resolved_rev, + &gErr)) { return LINGLONG_ERR("ostree_repo_resolve_rev", gErr); } // 使用sha256获取commit id From c728fab048c72e42c6615223ce7081141c43c6c9 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 23 Jul 2025 13:47:28 +0800 Subject: [PATCH 111/366] feat: set ns_last_pid annotation Use this annotation with ll-box to configure ns_last_pid in new pid namespace to avoid pid collisions. Signed-off-by: reddevillg --- libs/linglong/src/linglong/cli/cli.cpp | 20 +++++++++------- .../container_cfg_builder.cpp | 24 +++++++++++++++++++ .../container_cfg_builder.h | 5 ++-- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 06699d497..8bd75f582 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -607,8 +607,9 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) { LINGLONG_TRACE("command run"); - int64_t uid = getuid(); - int64_t gid = getgid(); + auto uid = getuid(); + auto gid = getgid(); + auto pid = getpid(); // NOTE: ll-box is not support running as root for now. if (uid == 0) { @@ -616,14 +617,14 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) return -1; } - auto userContainerDir = std::filesystem::path{ "/run/linglong" } / std::to_string(::getuid()); + auto userContainerDir = std::filesystem::path{ "/run/linglong" } / std::to_string(uid); if (auto ret = ensureDirectory(userContainerDir); !ret) { this->printer.printErr(ret.error()); return -1; } auto mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - auto pidFile = userContainerDir / std::to_string(::getpid()); + auto pidFile = userContainerDir / std::to_string(pid); // placeholder file auto fd = ::open(pidFile.c_str(), O_WRONLY | O_CREAT | O_EXCL, mode); if (fd == -1) { @@ -682,11 +683,9 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) // this lambda will dump reference of containerID, app, base and runtime to // /run/linglong/getuid()/getpid() to store these needed infomation - auto dumpContainerInfo = [uid, &runContext, this]() -> bool { + auto dumpContainerInfo = [&pidFile, &runContext, this]() -> bool { LINGLONG_TRACE("dump info") std::error_code ec; - auto pidFile = std::filesystem::path{ "/run/linglong" } / std::to_string(uid) - / std::to_string(::getpid()); if (!std::filesystem::exists(pidFile, ec)) { if (ec) { qCritical() << "couldn't get status of" << pidFile.c_str() << ":" @@ -712,8 +711,8 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) auto containers = getCurrentContainers().value_or(std::vector{}); for (const auto &container : containers) { + qDebug() << "found running container: " << container.package.c_str(); if (container.package != curAppRef->toString().toStdString()) { - qDebug() << "mismatch:" << container.package.c_str() << " -- " << curAppRef->toString(); continue; } @@ -751,6 +750,7 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) } cfgBuilder.setAppId(curAppRef->id.toStdString()) + .setAnnotation(generator::ANNOTATION::LAST_PID, std::to_string(pid)) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() @@ -901,6 +901,10 @@ Cli::getCurrentContainers() const noexcept continue; } + if (pidFile.file_size(ec) == 0) { + continue; + } + auto info = linglong::utils::serialize::LoadJSONFile< linglong::api::types::v1::ContainerProcessStateInfo>(file); if (!info) { diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 4072de82c..0a0532267 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -65,6 +65,30 @@ bool bindIfExist(std::vector &mounts, } } // namespace +ContainerCfgBuilder &ContainerCfgBuilder::setAnnotation(ANNOTATION key, std::string value) noexcept +{ + if (!config.annotations) { + config.annotations = std::map(); + } + + switch (key) { + case ANNOTATION::APPID: + config.annotations->insert_or_assign("org.deepin.linglong.appID", std::move(value)); + break; + case ANNOTATION::BASEDIR: + config.annotations->insert_or_assign("org.deepin.linglong.baseDir", std::move(value)); + break; + case ANNOTATION::LAST_PID: + config.annotations->insert_or_assign("cn.org.linyaps.runtime.ns_last_pid", + std::move(value)); + break; + default: + break; + } + + return *this; +} + ContainerCfgBuilder &ContainerCfgBuilder::addUIdMapping(int64_t containerID, int64_t hostID, int64_t size) noexcept diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index 7da8f0e71..cbda54d33 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -17,8 +17,9 @@ namespace linglong::generator { enum class ANNOTATION { - ANNOTATION_APPID, - ANNOTATION_BASEDIR, + APPID, + BASEDIR, + LAST_PID, }; class ContainerCfgBuilder From 7292e1b428275535d5bcff6c743ecbc96077dca4 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Wed, 23 Jul 2025 18:02:26 +0800 Subject: [PATCH 112/366] fix: share /tmp directory with host Share /tmp directory with host for maximize compability Signed-off-by: reddevillg --- .../container_cfg_builder.cpp | 33 ++++--------------- .../container_cfg_builder.h | 1 - 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 0a0532267..0da194f4f 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -243,7 +243,12 @@ ContainerCfgBuilder &ContainerCfgBuilder::bindRun() noexcept ContainerCfgBuilder &ContainerCfgBuilder::bindTmp() noexcept { - tmpMount = Mount{}; + tmpMount = Mount{ + .destination = "/tmp", + .options = string_list{ "rbind" }, + .source = "/tmp", + .type = "bind", + }; return *this; } @@ -871,30 +876,6 @@ bool ContainerCfgBuilder::buildMountHome() noexcept return true; } -bool ContainerCfgBuilder::buildTmp() noexcept -{ - if (!tmpMount) { - return true; - } - - std::srand(std::time(0)); - auto tmpPath = std::filesystem::temp_directory_path() - / ("linglong_" + std::to_string(::getuid())) / (appId + "-" + std::to_string(std::rand())); - std::error_code ec; - if (!std::filesystem::create_directories(tmpPath, ec) && ec) { - error_.reason = tmpPath.string() + "can't be created"; - error_.code = BUILD_MOUNT_TMP_ERROR; - return false; - } - - tmpMount = Mount{ .destination = "/tmp", - .options = string_list{ "rbind" }, - .source = tmpPath, - .type = "bind" }; - - return true; -} - bool ContainerCfgBuilder::buildPrivateDir() noexcept { if (!privateMount) { @@ -2074,7 +2055,7 @@ bool ContainerCfgBuilder::build() noexcept return false; } - if (!buildTmp() || !buildPrivateDir() || !buildMountHome() || !buildPrivateMapped()) { + if (!buildPrivateDir() || !buildMountHome() || !buildPrivateMapped()) { return false; } diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h index cbda54d33..96e57848a 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.h @@ -201,7 +201,6 @@ class ContainerCfgBuilder bool buildMountRuntime() noexcept; bool buildMountApp() noexcept; bool buildMountHome() noexcept; - bool buildTmp() noexcept; bool buildPrivateDir() noexcept; bool buildPrivateMapped() noexcept; bool buildMountIPC() noexcept; From 33eeea75595e97ea746e8522520f501cbd75a1b5 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Fri, 25 Jul 2025 11:46:19 +0800 Subject: [PATCH 113/366] fix: Always use copy-symlink on /etc/resolv.conf Signed-off-by: reddevillg --- .../container_cfg_builder.cpp | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp index 0da194f4f..d692b6b1a 100644 --- a/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp +++ b/libs/oci-cfg-generators/src/linglong/oci-cfg-generators/container_cfg_builder.cpp @@ -1231,23 +1231,27 @@ bool ContainerCfgBuilder::buildMountNetworkConf() noexcept std::filesystem::path resolvConf{ "/etc/resolv.conf" }; std::error_code ec; if (std::filesystem::exists(resolvConf, ec)) { - if (std::filesystem::is_symlink(resolvConf, ec) && hostRootMount) { - // If /etc/resolv.conf is a symlink, its target may be a relative path that is - // invalid inside the container. To work around this, we create a new symlink - // in the bundle directory pointing to the actual target, and then mount it with - // the 'copy-symlink' option, which tells the runtime to recreate the symlink - // inside the container. - std::array buf{}; - auto *rpath = realpath(resolvConf.string().c_str(), buf.data()); - if (rpath == nullptr) { - error_.reason = - "Failed to read symlink " + resolvConf.string() + ": " + strerror(errno); - error_.code = BUILD_NETWORK_CONF_ERROR; - return false; + // /etc/resolv.conf is volatile on host, we create a new symlink in the bundle + // directory pointing to the actual target, and then mount it with the + // 'copy-symlink' option, which tells the runtime to recreate the symlink inside + // the container. + // NOTE: it's not working if /etc/resolv.conf is a symlink, and points to a + // different path after container started. + if (hostRootMount) { + auto target = resolvConf; + if (std::filesystem::is_symlink(resolvConf, ec)) { + std::array buf{}; + auto *rpath = realpath(resolvConf.string().c_str(), buf.data()); + if (rpath == nullptr) { + error_.reason = + "Failed to read symlink " + resolvConf.string() + ": " + strerror(errno); + error_.code = BUILD_NETWORK_CONF_ERROR; + return false; + } + target = std::filesystem::path{ rpath }; } - std::filesystem::path target = std::filesystem::path{ "/run/host/rootfs" } - / std::filesystem::path{ rpath }.lexically_relative("/"); + target = std::filesystem::path{ "/run/host/rootfs" } / target.lexically_relative("/"); auto bundleResolvConf = bundlePath / "resolv.conf"; std::filesystem::create_symlink(target, bundleResolvConf, ec); if (ec) { @@ -1256,7 +1260,6 @@ bool ContainerCfgBuilder::buildMountNetworkConf() noexcept error_.code = BUILD_NETWORK_CONF_ERROR; return false; } - networkConfMount->emplace_back(Mount{ .destination = resolvConf.string(), .options = string_list{ "rbind", "copy-symlink" }, .source = bundleResolvConf, From f7cf75b8679e086d868418f44a9a6e0084e7a2de Mon Sep 17 00:00:00 2001 From: ComixHe Date: Mon, 28 Jul 2025 11:25:54 +0800 Subject: [PATCH 114/366] feat(run): add option '--env' Adding a '--env' option to the ll-cli run command, allowing users to set environment variables when running applications. This feature supports multiple environment variables in KEY=VALUE format with input validation to ensure proper formatting. Signed-off-by: ComixHe --- apps/ll-cli/src/main.cpp | 12 ++++++++++++ libs/linglong/src/linglong/cli/cli.cpp | 8 ++++++++ libs/linglong/src/linglong/cli/cli.h | 1 + 3 files changed, 21 insertions(+) diff --git a/apps/ll-cli/src/main.cpp b/apps/ll-cli/src/main.cpp index 0dabc922d..0d2f6998e 100644 --- a/apps/ll-cli/src/main.cpp +++ b/apps/ll-cli/src/main.cpp @@ -240,6 +240,18 @@ ll-cli run org.deepin.demo -- bash -x /path/to/bash/script)")); ->add_option("--url", options.fileUrls, _("Pass url to applications running in a sandbox")) ->type_name("URL") ->expected(0, -1); + cliRun->add_option("--env", options.envs, _("Set environment variables for the application")) + ->type_name("ENV") + ->expected(0, -1) + ->check([](const std::string &env) -> std::string { + if (env.find('=') == std::string::npos) { + return std::string{ _( + "Input parameter is invalid, please input valid parameter instead") }; + } + + return {}; + }); + cliRun->add_option("COMMAND", options.commands, _("Run commands in a running sandbox")); // add sub command ps diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 8bd75f582..0678c63ac 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -773,6 +773,14 @@ int Cli::run([[maybe_unused]] CLI::App *subcommand) .options = std::vector{ "bind" }, .source = socketDir.string(), .type = "bind" }); + + for (const auto &env : options.envs) { + auto split = env.cbegin() + env.find('='); // already checked by CLI + cfgBuilder.appendEnv(std::string(env.cbegin(), split), + std::string(split + 1, env.cend()), + true); + } + #ifdef LINGLONG_FONT_CACHE_GENERATOR cfgBuilder.enableFontCache(); #endif diff --git a/libs/linglong/src/linglong/cli/cli.h b/libs/linglong/src/linglong/cli/cli.h index 75feacbc3..48741b4fe 100644 --- a/libs/linglong/src/linglong/cli/cli.h +++ b/libs/linglong/src/linglong/cli/cli.h @@ -44,6 +44,7 @@ struct CliOptions { std::vector filePaths; std::vector fileUrls; + std::vector envs; std::string workDir; std::string appid; std::string instance; From fe1bd7da21d854d0d69b6fc9c86678f13d853065 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 28 Jul 2025 13:23:03 +0800 Subject: [PATCH 115/366] fix: fix bash completion 1. Correct ll-builder repo completion 2. Don't pull data from remote when completion "ll-cli install" and "ll-cli search" Signed-off-by: reddevillg --- .../bash-completion/completions/ll-builder | 2 +- misc/share/bash-completion/completions/ll-cli | 49 ++----------------- 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/misc/share/bash-completion/completions/ll-builder b/misc/share/bash-completion/completions/ll-builder index 283718a7a..77b54b71e 100755 --- a/misc/share/bash-completion/completions/ll-builder +++ b/misc/share/bash-completion/completions/ll-builder @@ -96,7 +96,7 @@ _ll_builder_complete() { fi if [[ ${prev} == "remove" || ${prev} == "set-default" ]]; then - output_options="${output_options} $(__ll_cli_get_repo_name_list)" + output_options="${output_options} $(__ll_builder_get_repo_name_list)" fi ;; migrate) diff --git a/misc/share/bash-completion/completions/ll-cli b/misc/share/bash-completion/completions/ll-cli index 6bfce0de4..8f45633ad 100644 --- a/misc/share/bash-completion/completions/ll-cli +++ b/misc/share/bash-completion/completions/ll-cli @@ -20,10 +20,6 @@ __ll_cli_get_installed_list() { ll-cli list | tail -n+2 | awk '{print $1}' | tr '\n' ' ' } -__ll_cli_get_app_list() { - ll-cli search $1 | tail -n+2 | awk '{print $1}' | sort | uniq | tr '\n' ' ' -} - __ll_cli_get_layer_list() { ls $1*.layer 2>/dev/null | tr '\n' ' ' } @@ -32,14 +28,6 @@ __ll_cli_get_repo_alias_list() { ll-cli repo show | tail -n+3 | awk '{print $3}' | tr "\n" " " } -# 只补全当前目录下的 .layer 和 .uab 文件,不包括目录 -__ll_cli_get_layer_uab_files_bash() { - local cur="$1" - local dir="${cur%/*}" - [[ "$cur" == */* ]] || dir="." - find "$dir" -maxdepth 1 -type f \( -name '*.layer' -o -name '*.uab' \) -printf '%P\n' -} - __filter_exist_options() { local aviable_opts for opt in $1; do @@ -114,33 +102,10 @@ _ll_cli_complete() { ;; install) install_options="--module --force -y" - # 判断当前补全文本是否以 ./ 开头,若是则只补全本地layer/uab文件且不补全目录 - if [[ "$cur" == ./* ]]; then - local dir prefix files - if [[ "$cur" == */* ]]; then - dir="${cur%/*}" - prefix="${dir}/" - else - dir="." - prefix="" - fi - # 列出目录下 .layer 和 .uab 文件,只要文件不要目录 - files=$(find "$dir" -maxdepth 1 -type f \( -name '*.layer' -o -name '*.uab' \) -printf '%f\n') - # 拼回补全前缀 - files=$(printf "%s\n" $files | sed "s|^|$prefix|") - COMPREPLY=( $(compgen -W "$files" -- "$cur") ) - return 0 - else - search_target="." - if [[ -n "${cur}" ]]; then - search_target=${cur} - fi - local app_list - if [[ "${prev}" == "install" ]]; then - app_list="$(__ll_cli_get_app_list "${search_target}")" - fi - output_options="${output_options} ${install_options} ${app_list}" - fi + output_options="${output_options} ${install_options}" + COMPREPLY=($(compgen -W "${output_options}" -- "${cur}")) + _filedir @(layer|uab) + return 0 ;; uninstall) local uninstall_options @@ -164,12 +129,8 @@ _ll_cli_complete() { output_options="${output_options} $(__ll_cli_get_installed_app_list)" ;; search) - search_target="." - if [[ x${cur} != x ]]; then - search_target=${cur} - fi search_options="--type --dev" - output_options="${output_options} ${search_options} $(__ll_cli_get_app_list ${search_target})" + output_options="${output_options} ${search_options}" ;; repo) local repo_subcommands="add remove update set-default show" From e6394ed758746a0aa114618ca9ace342d25d2830 Mon Sep 17 00:00:00 2001 From: reddevillg Date: Mon, 28 Jul 2025 13:59:29 +0800 Subject: [PATCH 116/366] fix: Don't bind host statics in build stage 1. Don't bind host statics in build statics, because build script may write to those directories. 2. add /sbin to merge list. Signed-off-by: reddevillg --- libs/linglong/src/linglong/builder/linglong_builder.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libs/linglong/src/linglong/builder/linglong_builder.cpp b/libs/linglong/src/linglong/builder/linglong_builder.cpp index 5c94469fc..b33f533a1 100644 --- a/libs/linglong/src/linglong/builder/linglong_builder.cpp +++ b/libs/linglong/src/linglong/builder/linglong_builder.cpp @@ -754,7 +754,6 @@ utils::error::Result Builder::processBuildDepends() noexcept .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .bindHostStatics() .addExtraMount(ocppi::runtime::config::types::Mount{ .destination = "/project", .options = { { "rbind", "ro" } }, @@ -887,7 +886,6 @@ utils::error::Result Builder::buildStageBuild(const QStringList &args) noe .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .bindHostStatics() .setStartContainerHooks( std::vector{ ocppi::runtime::config::types::Hook{ .path = "/sbin/ldconfig", @@ -1036,7 +1034,6 @@ utils::error::Result Builder::buildStagePreCommit() noexcept .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) .bindDefault() - .bindHostStatics() .addExtraMount(ocppi::runtime::config::types::Mount{ .destination = "/project", .options = { { "rbind", "rw" } }, @@ -1080,7 +1077,7 @@ utils::error::Result Builder::buildStagePreCommit() noexcept src.append(runtimeOverlay->upperDirPath()); } } - mergeOutput(src, buildOutput, QStringList({ "bin/", "lib/" })); + mergeOutput(src, buildOutput, QStringList({ "bin/", "sbin/", "lib/" })); return LINGLONG_OK; } @@ -1524,12 +1521,12 @@ utils::error::Result Builder::build(const QStringList &args) noexcept return LINGLONG_OK; } - printMessage("Successfully build " + this->project.package.id); - if (!(res = runtimeCheck())) { return LINGLONG_ERR("stage runtime check error", res); } + printMessage("Successfully build " + this->project.package.id); + return LINGLONG_OK; } From 0f1a1cecfb096859c459fbd0e44fcc1c1e5e30e2 Mon Sep 17 00:00:00 2001 From: myml Date: Wed, 30 Jul 2025 10:49:26 +0800 Subject: [PATCH 117/366] feat: add test coverage workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加单元测试覆盖率工作流 --- .github/workflows/build.yaml | 37 ++++++---------------------------- .github/workflows/codecov.yaml | 32 +++++++++++++++++++++++++++++ tools/generate-coverage.sh | 10 +++++++-- 3 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/codecov.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1fa1c7e1f..9342ef5c9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,37 +13,12 @@ jobs: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y cmake \ - debhelper-compat \ - erofsfuse \ - intltool \ - libcli11-dev \ - libcurl4-openssl-dev \ - libdeflate-dev \ - libelf-dev \ - libexpected-dev \ - libfuse3-dev \ - libglib2.0-dev \ - libgmock-dev \ - libgtest-dev \ - liblz4-dev \ - liblzma-dev \ - libostree-dev \ - libpcre2-dev \ - libselinux1-dev \ - libssl-dev \ - libsystemd-dev \ - libyaml-cpp-dev \ - libzstd-dev \ - nlohmann-json3-dev \ - pkg-config \ - qtbase5-dev \ - qtbase5-private-dev \ - systemd \ - zlib1g-dev + + - uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: cmake debhelper-compat erofsfuse intltool libcli11-dev libcurl4-openssl-dev libdeflate-dev libelf-dev libexpected-dev libfuse3-dev libglib2.0-dev libgmock-dev libgtest-dev liblz4-dev liblzma-dev libostree-dev libpcre2-dev libselinux1-dev libssl-dev libsystemd-dev libyaml-cpp-dev libzstd-dev nlohmann-json3-dev pkg-config qtbase5-dev qtbase5-private-dev systemd zlib1g-dev + version: 1.0 + - name: Build run: | mkdir build diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml new file mode 100644 index 000000000..9bf74c485 --- /dev/null +++ b/.github/workflows/codecov.yaml @@ -0,0 +1,32 @@ +name: coverage +on: + pull_request_target: + push: + branches: + - master + - 'release/**' +jobs: + codecov: + name: codecov + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: gcovr cmake debhelper-compat erofsfuse intltool libcli11-dev libcurl4-openssl-dev libdeflate-dev libelf-dev libexpected-dev libfuse3-dev libglib2.0-dev libgmock-dev libgtest-dev liblz4-dev liblzma-dev libostree-dev libpcre2-dev libselinux1-dev libssl-dev libsystemd-dev libyaml-cpp-dev libzstd-dev nlohmann-json3-dev pkg-config qtbase5-dev qtbase5-private-dev systemd zlib1g-dev + version: 1.0 + + - name: Generate coverage + run: | + ./tools/generate-coverage.sh + + - name: Upload Report to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./build-generate-coverage/report/index.xml + disable_search: true + disable_telem: true \ No newline at end of file diff --git a/tools/generate-coverage.sh b/tools/generate-coverage.sh index b103042ce..3b264bb08 100755 --- a/tools/generate-coverage.sh +++ b/tools/generate-coverage.sh @@ -18,7 +18,7 @@ command -v ccache &>/dev/null && { } # shellcheck disable=SC2086 -cmake --fresh -B "$builddir" -S . $USE_CCACHE || exit 255 +cmake --fresh -B "$builddir" -S . "$USE_CCACHE" || exit 255 cmake --build "$builddir" -j "$(nproc)" || exit 255 @@ -26,4 +26,10 @@ cmake --build "$builddir" -t test mkdir -p "$builddir"/report || exit 255 -gcovr --filter "src/*" --html-nested "$builddir"/report/index.html +gcovr \ + --filter "apps/.*" \ + --filter "libs/utils/.*" \ + --filter "libs/linglong/src/.*" \ + --html-nested "$builddir"/report/index.html \ + --xml "$builddir"/report/index.xml \ + --print-summary From bf1899d32825709d62566a10bc821f00dc3a9fc2 Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 29 Jul 2025 20:31:21 +0800 Subject: [PATCH 118/366] chore: update external dependency libraries used 1. Update external tl-expected and cli11 to new version. 2. tl-expected and cli11 only import header files. --- CMakeLists.txt | 6 +- external/CLI11/.all-contributorsrc | 701 - external/CLI11/.ci/azure-build.yml | 23 - external/CLI11/.ci/azure-cmake-new.yml | 17 - external/CLI11/.ci/azure-cmake.yml | 17 - external/CLI11/.ci/azure-test.yml | 9 - external/CLI11/.clang-format | 86 - external/CLI11/.clang-tidy | 83 - external/CLI11/.cmake-format.yaml | 6 - external/CLI11/.codacy.yml | 18 - external/CLI11/.codecov.yml | 7 - external/CLI11/.editorconfig | 13 - external/CLI11/.github/CONTRIBUTING.md | 90 - .../.github/actions/quick_cmake/action.yml | 25 - external/CLI11/.github/codecov.yml | 7 - external/CLI11/.github/dependabot.yml | 13 - external/CLI11/.github/labeler_merged.yml | 4 - external/CLI11/.github/workflows/build.yml | 59 - external/CLI11/.github/workflows/docs.yml | 91 - external/CLI11/.github/workflows/fuzz.yml | 54 - .../CLI11/.github/workflows/pr_merged.yml | 15 - external/CLI11/.github/workflows/tests.yml | 377 - external/CLI11/.gitignore | 20 - external/CLI11/.pre-commit-config.yaml | 93 - external/CLI11/.remarkrc | 7 - external/CLI11/CHANGELOG.md | 1116 -- external/CLI11/CLI/CLI.hpp | 11527 ++++++++++++++++ external/CLI11/CLI11.CPack.Description.txt | 1 - external/CLI11/CLI11.hpp.in | 95 - external/CLI11/CMakeLists.txt | 237 - external/CLI11/CPPLINT.cfg | 15 - external/CLI11/LICENSE | 25 - external/CLI11/README.md | 1850 --- external/CLI11/azure-pipelines.yml | 177 - external/CLI11/book/.gitignore | 20 - external/CLI11/book/CMakeLists.txt | 7 - external/CLI11/book/README.md | 94 - external/CLI11/book/SUMMARY.md | 15 - external/CLI11/book/book.json | 12 - .../CLI11/book/chapters/advanced-topics.md | 152 - .../book/chapters/an-advanced-example.md | 39 - external/CLI11/book/chapters/basics.md | 39 - external/CLI11/book/chapters/config.md | 421 - external/CLI11/book/chapters/flags.md | 167 - external/CLI11/book/chapters/formatting.md | 86 - external/CLI11/book/chapters/installation.md | 238 - external/CLI11/book/chapters/internals.md | 54 - external/CLI11/book/chapters/options.md | 481 - external/CLI11/book/chapters/subcommands.md | 194 - external/CLI11/book/chapters/toolkits.md | 40 - external/CLI11/book/chapters/validators.md | 66 - external/CLI11/book/code/CMakeLists.txt | 32 - external/CLI11/book/code/flags.cpp | 36 - external/CLI11/book/code/geet.cpp | 50 - external/CLI11/book/code/intro.cpp | 15 - external/CLI11/book/code/simplest.cpp | 11 - external/CLI11/book/package.json | 14 - external/CLI11/cmake/CLI11.pc.in | 9 - .../CLI11/cmake/CLI11ConfigVersion.cmake.in | 13 - .../CLI11/cmake/CLI11GeneratePkgConfig.cmake | 7 - external/CLI11/cmake/CLI11Warnings.cmake | 37 - external/CLI11/cmake/CLI11precompiled.pc.in | 11 - external/CLI11/cmake/CLIsingle.hpp.in | 10 - external/CLI11/cmake/CodeCoverage.cmake | 243 - external/CLI11/docs/.gitignore | 2 - external/CLI11/docs/CLI11.svg | 114 - external/CLI11/docs/CLI11_100.png | Bin 3355 -> 0 bytes external/CLI11/docs/CLI11_300.png | Bin 9957 -> 0 bytes external/CLI11/docs/CMakeLists.txt | 11 - external/CLI11/docs/Doxyfile | 2475 ---- external/CLI11/docs/mainpage.md | 24 - external/CLI11/examples/CMakeLists.txt | 257 - external/CLI11/examples/arg_capture.cpp | 34 - .../CLI11/examples/callback_passthrough.cpp | 28 - external/CLI11/examples/config_app.cpp | 50 - external/CLI11/examples/custom_parse.cpp | 39 - external/CLI11/examples/digit_args.cpp | 21 - external/CLI11/examples/enum.cpp | 33 - external/CLI11/examples/enum_ostream.cpp | 50 - external/CLI11/examples/formatter.cpp | 37 - external/CLI11/examples/groups.cpp | 39 - .../CLI11/examples/inter_argument_order.cpp | 51 - external/CLI11/examples/json.cpp | 123 - external/CLI11/examples/modhelp.cpp | 35 - external/CLI11/examples/nested.cpp | 30 - external/CLI11/examples/option_groups.cpp | 46 - external/CLI11/examples/positional_arity.cpp | 46 - .../CLI11/examples/positional_validation.cpp | 37 - external/CLI11/examples/prefix_command.cpp | 35 - external/CLI11/examples/ranges.cpp | 41 - external/CLI11/examples/retired.cpp | 46 - external/CLI11/examples/shapes.cpp | 56 - external/CLI11/examples/simple.cpp | 38 - external/CLI11/examples/subcom_help.cpp | 21 - .../examples/subcom_in_files/CMakeLists.txt | 1 - .../examples/subcom_in_files/subcommand_a.cpp | 37 - .../examples/subcom_in_files/subcommand_a.hpp | 23 - .../subcom_in_files/subcommand_main.cpp | 26 - .../CLI11/examples/subcom_partitioned.cpp | 46 - external/CLI11/examples/subcommands.cpp | 34 - external/CLI11/examples/testEXE.cpp | 28 - external/CLI11/examples/validators.cpp | 25 - external/CLI11/fuzz/CMakeLists.txt | 51 - external/CLI11/fuzz/cli11_app_fuzz.cpp | 55 - external/CLI11/fuzz/cli11_file_fuzz.cpp | 38 - external/CLI11/fuzz/fuzzApp.cpp | 151 - external/CLI11/fuzz/fuzzApp.hpp | 118 - external/CLI11/fuzz/fuzzCommand.cpp | 25 - external/CLI11/fuzz/fuzz_dictionary1.txt | 174 - external/CLI11/fuzz/fuzz_dictionary2.txt | 92 - external/CLI11/include/CLI/App.hpp | 1441 -- external/CLI11/include/CLI/Argv.hpp | 29 - external/CLI11/include/CLI/CLI.hpp | 40 - external/CLI11/include/CLI/Config.hpp | 53 - external/CLI11/include/CLI/ConfigFwd.hpp | 185 - external/CLI11/include/CLI/Encoding.hpp | 54 - external/CLI11/include/CLI/Error.hpp | 360 - external/CLI11/include/CLI/Formatter.hpp | 25 - external/CLI11/include/CLI/FormatterFwd.hpp | 189 - external/CLI11/include/CLI/Macros.hpp | 131 - external/CLI11/include/CLI/Option.hpp | 808 -- external/CLI11/include/CLI/Split.hpp | 48 - external/CLI11/include/CLI/StringTools.hpp | 267 - external/CLI11/include/CLI/Timer.hpp | 135 - external/CLI11/include/CLI/TypeTools.hpp | 1732 --- external/CLI11/include/CLI/Validators.hpp | 896 -- external/CLI11/include/CLI/Version.hpp | 16 - external/CLI11/include/CLI/impl/App_inl.hpp | 2288 --- external/CLI11/include/CLI/impl/Argv_inl.hpp | 88 - .../CLI11/include/CLI/impl/Config_inl.hpp | 611 - .../CLI11/include/CLI/impl/Encoding_inl.hpp | 154 - .../CLI11/include/CLI/impl/Formatter_inl.hpp | 299 - .../CLI11/include/CLI/impl/Option_inl.hpp | 688 - external/CLI11/include/CLI/impl/Split_inl.hpp | 143 - .../include/CLI/impl/StringTools_inl.hpp | 575 - .../CLI11/include/CLI/impl/Validators_inl.hpp | 367 - external/CLI11/meson.build | 23 - external/CLI11/meson_options.txt | 1 - external/CLI11/scripts/ExtractVersion.py | 17 - external/CLI11/scripts/MakeSingleHeader.py | 160 - external/CLI11/scripts/check_style.sh | 10 - external/CLI11/scripts/check_style_docker.sh | 14 - .../CLI11/scripts/clang-format-pre-commit | 36 - external/CLI11/scripts/mdlint_style.rb | 9 - external/CLI11/src/CMakeLists.txt | 140 - external/CLI11/src/Precompile.cpp | 15 - external/CLI11/subprojects/catch2.wrap | 11 - external/CLI11/tests/.syntastic_cpp_config | 1 - external/CLI11/tests/AppTest.cpp | 2665 ---- external/CLI11/tests/BoostOptionTypeTest.cpp | 126 - external/CLI11/tests/CMakeLists.txt | 368 - external/CLI11/tests/ComplexTypeTest.cpp | 189 - external/CLI11/tests/ConfigFileTest.cpp | 3804 ----- external/CLI11/tests/CreationTest.cpp | 821 -- external/CLI11/tests/DeprecatedTest.cpp | 12 - external/CLI11/tests/EncodingTest.cpp | 104 - external/CLI11/tests/FormatterTest.cpp | 209 - external/CLI11/tests/FuzzFailTest.cpp | 100 - external/CLI11/tests/HelpTest.cpp | 1354 -- external/CLI11/tests/HelpersTest.cpp | 1611 --- external/CLI11/tests/NewParseTest.cpp | 618 - external/CLI11/tests/OptionGroupTest.cpp | 801 -- external/CLI11/tests/OptionTypeTest.cpp | 1314 -- external/CLI11/tests/OptionalTest.cpp | 358 - external/CLI11/tests/SetTest.cpp | 729 - external/CLI11/tests/SimpleTest.cpp | 34 - external/CLI11/tests/StringParseTest.cpp | 117 - external/CLI11/tests/SubcommandTest.cpp | 2143 --- external/CLI11/tests/TimerTest.cpp | 68 - external/CLI11/tests/TransformTest.cpp | 1018 -- external/CLI11/tests/TrueFalseTest.cpp | 29 - external/CLI11/tests/WindowsTest.cpp | 19 - external/CLI11/tests/app_helper.hpp | 132 - .../CLI11/tests/applications/ensure_utf8.cpp | 35 - .../tests/applications/ensure_utf8_twice.cpp | 36 - external/CLI11/tests/catch.hpp | 36 - external/CLI11/tests/data/unicode.txt | 1 - .../tests/find_package_tests/CMakeLists.txt | 19 - external/CLI11/tests/fuzzFail/fuzz_app_fail1 | Bin 41 -> 0 bytes external/CLI11/tests/fuzzFail/fuzz_app_fail2 | 1 - external/CLI11/tests/fuzzFail/fuzz_app_fail3 | Bin 27 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail1 | 0 .../CLI11/tests/fuzzFail/fuzz_app_file_fail10 | 3 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail11 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail12 | Bin 17 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail13 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail14 | 4 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail15 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail16 | Bin 13 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail17 | 9 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail18 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail19 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail2 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail20 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail21 | Bin 24 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail22 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail23 | Bin 14 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail24 | Bin 25 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail25 | Bin 36 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail26 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail27 | 2 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail28 | 5 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail29 | 4 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail3 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail30 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail31 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail32 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail33 | 2 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail34 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail35 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail36 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail37 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail38 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail39 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail4 | 1 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail5 | 6 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail6 | Bin 26 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail7 | 3 - .../CLI11/tests/fuzzFail/fuzz_app_file_fail8 | Bin 14 -> 0 bytes .../CLI11/tests/fuzzFail/fuzz_app_file_fail9 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail1 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail2 | Bin 113 -> 0 bytes external/CLI11/tests/fuzzFail/fuzz_file_fail3 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail4 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail5 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail6 | Bin 221 -> 0 bytes external/CLI11/tests/fuzzFail/fuzz_file_fail7 | 1 - external/CLI11/tests/fuzzFail/fuzz_file_fail8 | 1 - external/CLI11/tests/informational.cpp | 56 - external/CLI11/tests/link_test_1.cpp | 10 - external/CLI11/tests/link_test_2.cpp | 17 - external/CLI11/tests/main.cpp | 8 - external/CLI11/tests/meson.build | 100 - external/CLI11/tests/mesonTest/README.md | 10 - external/CLI11/tests/mesonTest/main.cpp | 17 - external/CLI11/tests/mesonTest/meson.build | 5 - .../tests/package_config_tests/CMakeLists.txt | 21 - external/tl-expected/.appveyor.yml | 10 - external/tl-expected/.clang-format | 1 - .../tl-expected/.github/workflows/cmake.yml | 131 - external/tl-expected/.gitignore | 3 - external/tl-expected/.travis.yml | 268 - external/tl-expected/CMakeLists.txt | 117 - external/tl-expected/COPYING | 121 - external/tl-expected/README.md | 76 - .../cmake/tl-expected-config.cmake.in | 3 - external/tl-expected/include/tl/expected.hpp | 65 +- external/tl-expected/tests/assertions.cpp | 18 - external/tl-expected/tests/assignment.cpp | 75 - external/tl-expected/tests/bases.cpp | 191 - external/tl-expected/tests/constexpr.cpp | 6 - external/tl-expected/tests/constructors.cpp | 134 - external/tl-expected/tests/emplace.cpp | 50 - external/tl-expected/tests/extensions.cpp | 830 -- external/tl-expected/tests/issues.cpp | 195 - external/tl-expected/tests/main.cpp | 2 - external/tl-expected/tests/noexcept.cpp | 6 - external/tl-expected/tests/observers.cpp | 36 - external/tl-expected/tests/relops.cpp | 17 - external/tl-expected/tests/swap.cpp | 107 - external/tl-expected/tests/test.cpp | 32 - libs/linglong/src/linglong/cli/cli.h | 2 +- tools/update-external.sh | 20 +- 263 files changed, 11598 insertions(+), 46397 deletions(-) delete mode 100644 external/CLI11/.all-contributorsrc delete mode 100644 external/CLI11/.ci/azure-build.yml delete mode 100644 external/CLI11/.ci/azure-cmake-new.yml delete mode 100644 external/CLI11/.ci/azure-cmake.yml delete mode 100644 external/CLI11/.ci/azure-test.yml delete mode 100644 external/CLI11/.clang-format delete mode 100644 external/CLI11/.clang-tidy delete mode 100644 external/CLI11/.cmake-format.yaml delete mode 100644 external/CLI11/.codacy.yml delete mode 100644 external/CLI11/.codecov.yml delete mode 100644 external/CLI11/.editorconfig delete mode 100644 external/CLI11/.github/CONTRIBUTING.md delete mode 100644 external/CLI11/.github/actions/quick_cmake/action.yml delete mode 100644 external/CLI11/.github/codecov.yml delete mode 100644 external/CLI11/.github/dependabot.yml delete mode 100644 external/CLI11/.github/labeler_merged.yml delete mode 100644 external/CLI11/.github/workflows/build.yml delete mode 100644 external/CLI11/.github/workflows/docs.yml delete mode 100644 external/CLI11/.github/workflows/fuzz.yml delete mode 100644 external/CLI11/.github/workflows/pr_merged.yml delete mode 100644 external/CLI11/.github/workflows/tests.yml delete mode 100644 external/CLI11/.gitignore delete mode 100644 external/CLI11/.pre-commit-config.yaml delete mode 100644 external/CLI11/.remarkrc delete mode 100644 external/CLI11/CHANGELOG.md create mode 100644 external/CLI11/CLI/CLI.hpp delete mode 100644 external/CLI11/CLI11.CPack.Description.txt delete mode 100644 external/CLI11/CLI11.hpp.in delete mode 100644 external/CLI11/CMakeLists.txt delete mode 100644 external/CLI11/CPPLINT.cfg delete mode 100644 external/CLI11/LICENSE delete mode 100644 external/CLI11/README.md delete mode 100644 external/CLI11/azure-pipelines.yml delete mode 100644 external/CLI11/book/.gitignore delete mode 100644 external/CLI11/book/CMakeLists.txt delete mode 100644 external/CLI11/book/README.md delete mode 100644 external/CLI11/book/SUMMARY.md delete mode 100644 external/CLI11/book/book.json delete mode 100644 external/CLI11/book/chapters/advanced-topics.md delete mode 100644 external/CLI11/book/chapters/an-advanced-example.md delete mode 100644 external/CLI11/book/chapters/basics.md delete mode 100644 external/CLI11/book/chapters/config.md delete mode 100644 external/CLI11/book/chapters/flags.md delete mode 100644 external/CLI11/book/chapters/formatting.md delete mode 100644 external/CLI11/book/chapters/installation.md delete mode 100644 external/CLI11/book/chapters/internals.md delete mode 100644 external/CLI11/book/chapters/options.md delete mode 100644 external/CLI11/book/chapters/subcommands.md delete mode 100644 external/CLI11/book/chapters/toolkits.md delete mode 100644 external/CLI11/book/chapters/validators.md delete mode 100644 external/CLI11/book/code/CMakeLists.txt delete mode 100644 external/CLI11/book/code/flags.cpp delete mode 100644 external/CLI11/book/code/geet.cpp delete mode 100644 external/CLI11/book/code/intro.cpp delete mode 100644 external/CLI11/book/code/simplest.cpp delete mode 100644 external/CLI11/book/package.json delete mode 100644 external/CLI11/cmake/CLI11.pc.in delete mode 100644 external/CLI11/cmake/CLI11ConfigVersion.cmake.in delete mode 100644 external/CLI11/cmake/CLI11GeneratePkgConfig.cmake delete mode 100644 external/CLI11/cmake/CLI11Warnings.cmake delete mode 100644 external/CLI11/cmake/CLI11precompiled.pc.in delete mode 100644 external/CLI11/cmake/CLIsingle.hpp.in delete mode 100644 external/CLI11/cmake/CodeCoverage.cmake delete mode 100644 external/CLI11/docs/.gitignore delete mode 100644 external/CLI11/docs/CLI11.svg delete mode 100644 external/CLI11/docs/CLI11_100.png delete mode 100644 external/CLI11/docs/CLI11_300.png delete mode 100644 external/CLI11/docs/CMakeLists.txt delete mode 100644 external/CLI11/docs/Doxyfile delete mode 100644 external/CLI11/docs/mainpage.md delete mode 100644 external/CLI11/examples/CMakeLists.txt delete mode 100644 external/CLI11/examples/arg_capture.cpp delete mode 100644 external/CLI11/examples/callback_passthrough.cpp delete mode 100644 external/CLI11/examples/config_app.cpp delete mode 100644 external/CLI11/examples/custom_parse.cpp delete mode 100644 external/CLI11/examples/digit_args.cpp delete mode 100644 external/CLI11/examples/enum.cpp delete mode 100644 external/CLI11/examples/enum_ostream.cpp delete mode 100644 external/CLI11/examples/formatter.cpp delete mode 100644 external/CLI11/examples/groups.cpp delete mode 100644 external/CLI11/examples/inter_argument_order.cpp delete mode 100644 external/CLI11/examples/json.cpp delete mode 100644 external/CLI11/examples/modhelp.cpp delete mode 100644 external/CLI11/examples/nested.cpp delete mode 100644 external/CLI11/examples/option_groups.cpp delete mode 100644 external/CLI11/examples/positional_arity.cpp delete mode 100644 external/CLI11/examples/positional_validation.cpp delete mode 100644 external/CLI11/examples/prefix_command.cpp delete mode 100644 external/CLI11/examples/ranges.cpp delete mode 100644 external/CLI11/examples/retired.cpp delete mode 100644 external/CLI11/examples/shapes.cpp delete mode 100644 external/CLI11/examples/simple.cpp delete mode 100644 external/CLI11/examples/subcom_help.cpp delete mode 100644 external/CLI11/examples/subcom_in_files/CMakeLists.txt delete mode 100644 external/CLI11/examples/subcom_in_files/subcommand_a.cpp delete mode 100644 external/CLI11/examples/subcom_in_files/subcommand_a.hpp delete mode 100644 external/CLI11/examples/subcom_in_files/subcommand_main.cpp delete mode 100644 external/CLI11/examples/subcom_partitioned.cpp delete mode 100644 external/CLI11/examples/subcommands.cpp delete mode 100644 external/CLI11/examples/testEXE.cpp delete mode 100644 external/CLI11/examples/validators.cpp delete mode 100644 external/CLI11/fuzz/CMakeLists.txt delete mode 100644 external/CLI11/fuzz/cli11_app_fuzz.cpp delete mode 100644 external/CLI11/fuzz/cli11_file_fuzz.cpp delete mode 100644 external/CLI11/fuzz/fuzzApp.cpp delete mode 100644 external/CLI11/fuzz/fuzzApp.hpp delete mode 100644 external/CLI11/fuzz/fuzzCommand.cpp delete mode 100644 external/CLI11/fuzz/fuzz_dictionary1.txt delete mode 100644 external/CLI11/fuzz/fuzz_dictionary2.txt delete mode 100644 external/CLI11/include/CLI/App.hpp delete mode 100644 external/CLI11/include/CLI/Argv.hpp delete mode 100644 external/CLI11/include/CLI/CLI.hpp delete mode 100644 external/CLI11/include/CLI/Config.hpp delete mode 100644 external/CLI11/include/CLI/ConfigFwd.hpp delete mode 100644 external/CLI11/include/CLI/Encoding.hpp delete mode 100644 external/CLI11/include/CLI/Error.hpp delete mode 100644 external/CLI11/include/CLI/Formatter.hpp delete mode 100644 external/CLI11/include/CLI/FormatterFwd.hpp delete mode 100644 external/CLI11/include/CLI/Macros.hpp delete mode 100644 external/CLI11/include/CLI/Option.hpp delete mode 100644 external/CLI11/include/CLI/Split.hpp delete mode 100644 external/CLI11/include/CLI/StringTools.hpp delete mode 100644 external/CLI11/include/CLI/Timer.hpp delete mode 100644 external/CLI11/include/CLI/TypeTools.hpp delete mode 100644 external/CLI11/include/CLI/Validators.hpp delete mode 100644 external/CLI11/include/CLI/Version.hpp delete mode 100644 external/CLI11/include/CLI/impl/App_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Argv_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Config_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Encoding_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Formatter_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Option_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Split_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/StringTools_inl.hpp delete mode 100644 external/CLI11/include/CLI/impl/Validators_inl.hpp delete mode 100644 external/CLI11/meson.build delete mode 100644 external/CLI11/meson_options.txt delete mode 100755 external/CLI11/scripts/ExtractVersion.py delete mode 100755 external/CLI11/scripts/MakeSingleHeader.py delete mode 100755 external/CLI11/scripts/check_style.sh delete mode 100755 external/CLI11/scripts/check_style_docker.sh delete mode 100755 external/CLI11/scripts/clang-format-pre-commit delete mode 100644 external/CLI11/scripts/mdlint_style.rb delete mode 100644 external/CLI11/src/CMakeLists.txt delete mode 100644 external/CLI11/src/Precompile.cpp delete mode 100644 external/CLI11/subprojects/catch2.wrap delete mode 100644 external/CLI11/tests/.syntastic_cpp_config delete mode 100644 external/CLI11/tests/AppTest.cpp delete mode 100644 external/CLI11/tests/BoostOptionTypeTest.cpp delete mode 100644 external/CLI11/tests/CMakeLists.txt delete mode 100644 external/CLI11/tests/ComplexTypeTest.cpp delete mode 100644 external/CLI11/tests/ConfigFileTest.cpp delete mode 100644 external/CLI11/tests/CreationTest.cpp delete mode 100644 external/CLI11/tests/DeprecatedTest.cpp delete mode 100644 external/CLI11/tests/EncodingTest.cpp delete mode 100644 external/CLI11/tests/FormatterTest.cpp delete mode 100644 external/CLI11/tests/FuzzFailTest.cpp delete mode 100644 external/CLI11/tests/HelpTest.cpp delete mode 100644 external/CLI11/tests/HelpersTest.cpp delete mode 100644 external/CLI11/tests/NewParseTest.cpp delete mode 100644 external/CLI11/tests/OptionGroupTest.cpp delete mode 100644 external/CLI11/tests/OptionTypeTest.cpp delete mode 100644 external/CLI11/tests/OptionalTest.cpp delete mode 100644 external/CLI11/tests/SetTest.cpp delete mode 100644 external/CLI11/tests/SimpleTest.cpp delete mode 100644 external/CLI11/tests/StringParseTest.cpp delete mode 100644 external/CLI11/tests/SubcommandTest.cpp delete mode 100644 external/CLI11/tests/TimerTest.cpp delete mode 100644 external/CLI11/tests/TransformTest.cpp delete mode 100644 external/CLI11/tests/TrueFalseTest.cpp delete mode 100644 external/CLI11/tests/WindowsTest.cpp delete mode 100644 external/CLI11/tests/app_helper.hpp delete mode 100644 external/CLI11/tests/applications/ensure_utf8.cpp delete mode 100644 external/CLI11/tests/applications/ensure_utf8_twice.cpp delete mode 100644 external/CLI11/tests/catch.hpp delete mode 100644 external/CLI11/tests/data/unicode.txt delete mode 100644 external/CLI11/tests/find_package_tests/CMakeLists.txt delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_fail1 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_fail2 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_fail3 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail1 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail10 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail11 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail12 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail13 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail14 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail15 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail16 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail17 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail18 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail19 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail2 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail20 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail21 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail22 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail23 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail24 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail25 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail26 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail27 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail28 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail29 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail3 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail30 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail31 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail32 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail33 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail34 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail35 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail36 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail37 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail38 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail39 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail4 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail5 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail6 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail7 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail8 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_app_file_fail9 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail1 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail2 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail3 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail4 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail5 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail6 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail7 delete mode 100644 external/CLI11/tests/fuzzFail/fuzz_file_fail8 delete mode 100644 external/CLI11/tests/informational.cpp delete mode 100644 external/CLI11/tests/link_test_1.cpp delete mode 100644 external/CLI11/tests/link_test_2.cpp delete mode 100644 external/CLI11/tests/main.cpp delete mode 100644 external/CLI11/tests/meson.build delete mode 100644 external/CLI11/tests/mesonTest/README.md delete mode 100644 external/CLI11/tests/mesonTest/main.cpp delete mode 100644 external/CLI11/tests/mesonTest/meson.build delete mode 100644 external/CLI11/tests/package_config_tests/CMakeLists.txt delete mode 100644 external/tl-expected/.appveyor.yml delete mode 100644 external/tl-expected/.clang-format delete mode 100644 external/tl-expected/.github/workflows/cmake.yml delete mode 100644 external/tl-expected/.gitignore delete mode 100644 external/tl-expected/.travis.yml delete mode 100644 external/tl-expected/CMakeLists.txt delete mode 100644 external/tl-expected/COPYING delete mode 100644 external/tl-expected/README.md delete mode 100644 external/tl-expected/cmake/tl-expected-config.cmake.in delete mode 100644 external/tl-expected/tests/assertions.cpp delete mode 100644 external/tl-expected/tests/assignment.cpp delete mode 100644 external/tl-expected/tests/bases.cpp delete mode 100644 external/tl-expected/tests/constexpr.cpp delete mode 100644 external/tl-expected/tests/constructors.cpp delete mode 100644 external/tl-expected/tests/emplace.cpp delete mode 100644 external/tl-expected/tests/extensions.cpp delete mode 100644 external/tl-expected/tests/issues.cpp delete mode 100644 external/tl-expected/tests/main.cpp delete mode 100644 external/tl-expected/tests/noexcept.cpp delete mode 100644 external/tl-expected/tests/observers.cpp delete mode 100644 external/tl-expected/tests/relops.cpp delete mode 100644 external/tl-expected/tests/swap.cpp delete mode 100644 external/tl-expected/tests/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 773c53982..d361b8459 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,7 @@ endif() # NOTE: UOS v20 do not have tl-expected packaged. find_package(tl-expected 1.0.0 QUIET) if(NOT tl-expected_FOUND) + message(STATUS "tl-expected not found, using external tl-expected") # list(APPEND linglong_EXTERNALS tl-expected) # tl-expected requires 3.14 add_library(tl-expected INTERFACE) add_library(tl::expected ALIAS tl-expected) @@ -161,7 +162,10 @@ endif() # NOTE: UOS v20 do not have cli11 packaged. find_package(CLI11 2.4.1 QUIET) if(NOT CLI11_FOUND) - list(APPEND linglong_EXTERNALS "CLI11 CLI11::CLI11") + message(STATUS "CLI11 not found, using external CLI11") + add_library(CLI11 INTERFACE) + add_library(CLI11::CLI11 ALIAS CLI11) + target_include_directories(CLI11 INTERFACE ./external/CLI11) endif() find_package(PkgConfig REQUIRED) diff --git a/external/CLI11/.all-contributorsrc b/external/CLI11/.all-contributorsrc deleted file mode 100644 index 14ba0211e..000000000 --- a/external/CLI11/.all-contributorsrc +++ /dev/null @@ -1,701 +0,0 @@ -{ - "projectName": "CLI11", - "projectOwner": "CLIUtils", - "repoType": "github", - "repoHost": "https://github.com", - "files": [ - "README.md" - ], - "imageSize": 100, - "commit": true, - "commitConvention": "atom", - "contributors": [ - { - "login": "henryiii", - "name": "Henry Schreiner", - "avatar_url": "https://avatars1.githubusercontent.com/u/4616906?v=4", - "profile": "http://iscinumpy.gitlab.io", - "contributions": [ - "bug", - "doc", - "code" - ] - }, - { - "login": "phlptp", - "name": "Philip Top", - "avatar_url": "https://avatars0.githubusercontent.com/u/20667153?v=4", - "profile": "https://github.com/phlptp", - "contributions": [ - "bug", - "doc", - "code" - ] - }, - { - "login": "cbachhuber", - "name": "Christoph Bachhuber", - "avatar_url": "https://avatars0.githubusercontent.com/u/27212661?v=4", - "profile": "https://www.linkedin.com/in/cbachhuber/", - "contributions": [ - "example", - "code" - ] - }, - { - "login": "lambdafu", - "name": "Marcus Brinkmann", - "avatar_url": "https://avatars1.githubusercontent.com/u/1138455?v=4", - "profile": "https://lambdafu.net/", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "SkyToGround", - "name": "Jonas Nilsson", - "avatar_url": "https://avatars1.githubusercontent.com/u/58835?v=4", - "profile": "https://github.com/SkyToGround", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "dvj", - "name": "Doug Johnston", - "avatar_url": "https://avatars2.githubusercontent.com/u/77217?v=4", - "profile": "https://github.com/dvj", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "lczech", - "name": "Lucas Czech", - "avatar_url": "https://avatars0.githubusercontent.com/u/4741887?v=4", - "profile": "http://lucas-czech.de", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "rafiw", - "name": "Rafi Wiener", - "avatar_url": "https://avatars3.githubusercontent.com/u/3034707?v=4", - "profile": "https://github.com/rafiw", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "mensinda", - "name": "Daniel Mensinger", - "avatar_url": "https://avatars3.githubusercontent.com/u/3407462?v=4", - "profile": "https://github.com/mensinda", - "contributions": [ - "platform" - ] - }, - { - "login": "jbriales", - "name": "Jesus Briales", - "avatar_url": "https://avatars1.githubusercontent.com/u/6850478?v=4", - "profile": "https://github.com/jbriales", - "contributions": [ - "code", - "bug" - ] - }, - { - "login": "seanfisk", - "name": "Sean Fisk", - "avatar_url": "https://avatars0.githubusercontent.com/u/410322?v=4", - "profile": "https://seanfisk.com/", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "fpeng1985", - "name": "fpeng1985", - "avatar_url": "https://avatars1.githubusercontent.com/u/87981?v=4", - "profile": "https://github.com/fpeng1985", - "contributions": [ - "code" - ] - }, - { - "login": "almikhayl", - "name": "almikhayl", - "avatar_url": "https://avatars2.githubusercontent.com/u/6747040?v=4", - "profile": "https://github.com/almikhayl", - "contributions": [ - "code", - "platform" - ] - }, - { - "login": "andrew-hardin", - "name": "Andrew Hardin", - "avatar_url": "https://avatars0.githubusercontent.com/u/16496326?v=4", - "profile": "https://github.com/andrew-hardin", - "contributions": [ - "code" - ] - }, - { - "login": "SX91", - "name": "Anton", - "avatar_url": "https://avatars2.githubusercontent.com/u/754754?v=4", - "profile": "https://github.com/SX91", - "contributions": [ - "code" - ] - }, - { - "login": "helmesjo", - "name": "Fred Helmesjö", - "avatar_url": "https://avatars0.githubusercontent.com/u/2501070?v=4", - "profile": "https://github.com/helmesjo", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "skannan89", - "name": "Kannan", - "avatar_url": "https://avatars0.githubusercontent.com/u/11918764?v=4", - "profile": "https://github.com/skannan89", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "kraj", - "name": "Khem Raj", - "avatar_url": "https://avatars3.githubusercontent.com/u/465279?v=4", - "profile": "http://himvis.com", - "contributions": [ - "code" - ] - }, - { - "login": "mogigoma", - "name": "Mak Kolybabi", - "avatar_url": "https://avatars2.githubusercontent.com/u/130862?v=4", - "profile": "https://www.mogigoma.com/", - "contributions": [ - "doc" - ] - }, - { - "login": "msoeken", - "name": "Mathias Soeken", - "avatar_url": "https://avatars0.githubusercontent.com/u/1998245?v=4", - "profile": "http://msoeken.github.io", - "contributions": [ - "doc" - ] - }, - { - "login": "nathanhourt", - "name": "Nathan Hourt", - "avatar_url": "https://avatars2.githubusercontent.com/u/271977?v=4", - "profile": "https://github.com/nathanhourt", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "pleroux0", - "name": "Paul le Roux", - "avatar_url": "https://avatars2.githubusercontent.com/u/39619854?v=4", - "profile": "https://github.com/pleroux0", - "contributions": [ - "code", - "platform" - ] - }, - { - "login": "chfast", - "name": "Paweł Bylica", - "avatar_url": "https://avatars1.githubusercontent.com/u/573380?v=4", - "profile": "https://github.com/chfast", - "contributions": [ - "platform" - ] - }, - { - "login": "peterazmanov", - "name": "Peter Azmanov", - "avatar_url": "https://avatars0.githubusercontent.com/u/15322318?v=4", - "profile": "https://github.com/peterazmanov", - "contributions": [ - "code" - ] - }, - { - "login": "delpinux", - "name": "Stéphane Del Pino", - "avatar_url": "https://avatars0.githubusercontent.com/u/35096584?v=4", - "profile": "https://github.com/delpinux", - "contributions": [ - "code" - ] - }, - { - "login": "metopa", - "name": "Viacheslav Kroilov", - "avatar_url": "https://avatars2.githubusercontent.com/u/3974178?v=4", - "profile": "https://github.com/metopa", - "contributions": [ - "code" - ] - }, - { - "login": "ChristosT", - "name": "christos", - "avatar_url": "https://avatars0.githubusercontent.com/u/6725596?v=4", - "profile": "http://cs.odu.edu/~ctsolakis", - "contributions": [ - "code" - ] - }, - { - "login": "deining", - "name": "deining", - "avatar_url": "https://avatars3.githubusercontent.com/u/18169566?v=4", - "profile": "https://github.com/deining", - "contributions": [ - "doc" - ] - }, - { - "login": "elszon", - "name": "elszon", - "avatar_url": "https://avatars0.githubusercontent.com/u/2971495?v=4", - "profile": "https://github.com/elszon", - "contributions": [ - "code" - ] - }, - { - "login": "ncihnegn", - "name": "ncihnegn", - "avatar_url": "https://avatars3.githubusercontent.com/u/12021721?v=4", - "profile": "https://github.com/ncihnegn", - "contributions": [ - "code" - ] - }, - { - "login": "nurelin", - "name": "nurelin", - "avatar_url": "https://avatars3.githubusercontent.com/u/5276274?v=4", - "profile": "https://github.com/nurelin", - "contributions": [ - "code" - ] - }, - { - "login": "ryan4729", - "name": "ryan4729", - "avatar_url": "https://avatars3.githubusercontent.com/u/40183301?v=4", - "profile": "https://github.com/ryan4729", - "contributions": [ - "test" - ] - }, - { - "login": "slurps-mad-rips", - "name": "Isabella Muerte", - "avatar_url": "https://avatars0.githubusercontent.com/u/63051?v=4", - "profile": "https://izzys.casa", - "contributions": [ - "platform" - ] - }, - { - "login": "KOLANICH", - "name": "KOLANICH", - "avatar_url": "https://avatars1.githubusercontent.com/u/240344?v=4", - "profile": "https://github.com/KOLANICH", - "contributions": [ - "platform" - ] - }, - { - "login": "jgerityneurala", - "name": "James Gerity", - "avatar_url": "https://avatars2.githubusercontent.com/u/57360646?v=4", - "profile": "https://github.com/jgerityneurala", - "contributions": [ - "doc" - ] - }, - { - "login": "jsoref", - "name": "Josh Soref", - "avatar_url": "https://avatars0.githubusercontent.com/u/2119212?v=4", - "profile": "https://github.com/jsoref", - "contributions": [ - "tool" - ] - }, - { - "login": "geir-t", - "name": "geir-t", - "avatar_url": "https://avatars3.githubusercontent.com/u/35292136?v=4", - "profile": "https://github.com/geir-t", - "contributions": [ - "platform" - ] - }, - { - "login": "certik", - "name": "Ondřej Čertík", - "avatar_url": "https://avatars3.githubusercontent.com/u/20568?v=4", - "profile": "https://ondrejcertik.com/", - "contributions": [ - "bug" - ] - }, - { - "login": "samhocevar", - "name": "Sam Hocevar", - "avatar_url": "https://avatars2.githubusercontent.com/u/245089?v=4", - "profile": "http://sam.hocevar.net/", - "contributions": [ - "code" - ] - }, - { - "login": "rcurtin", - "name": "Ryan Curtin", - "avatar_url": "https://avatars0.githubusercontent.com/u/1845039?v=4", - "profile": "http://www.ratml.org/", - "contributions": [ - "doc" - ] - }, - { - "login": "mbhall88", - "name": "Michael Hall", - "avatar_url": "https://avatars3.githubusercontent.com/u/20403931?v=4", - "profile": "https://mbh.sh", - "contributions": [ - "doc" - ] - }, - { - "login": "ferdymercury", - "name": "ferdymercury", - "avatar_url": "https://avatars3.githubusercontent.com/u/10653970?v=4", - "profile": "https://github.com/ferdymercury", - "contributions": [ - "doc" - ] - }, - { - "login": "jakoblover", - "name": "Jakob Lover", - "avatar_url": "https://avatars0.githubusercontent.com/u/14160441?v=4", - "profile": "https://github.com/jakoblover", - "contributions": [ - "code" - ] - }, - { - "login": "ZeeD26", - "name": "Dominik Steinberger", - "avatar_url": "https://avatars2.githubusercontent.com/u/2487468?v=4", - "profile": "https://github.com/ZeeD26", - "contributions": [ - "code" - ] - }, - { - "login": "dfleury2", - "name": "D. Fleury", - "avatar_url": "https://avatars1.githubusercontent.com/u/4805384?v=4", - "profile": "https://github.com/dfleury2", - "contributions": [ - "code" - ] - }, - { - "login": "dbarowy", - "name": "Dan Barowy", - "avatar_url": "https://avatars3.githubusercontent.com/u/573142?v=4", - "profile": "https://github.com/dbarowy", - "contributions": [ - "doc" - ] - }, - { - "login": "paddy-hack", - "name": "Olaf Meeuwissen", - "avatar_url": "https://avatars.githubusercontent.com/u/6804372?v=4", - "profile": "https://github.com/paddy-hack", - "contributions": [ - "code" - ] - }, - { - "login": "dryleev", - "name": "dryleev", - "avatar_url": "https://avatars.githubusercontent.com/u/83670813?v=4", - "profile": "https://github.com/dryleev", - "contributions": [ - "code" - ] - }, - { - "login": "AnticliMaxtic", - "name": "Max", - "avatar_url": "https://avatars.githubusercontent.com/u/43995389?v=4", - "profile": "https://github.com/AnticliMaxtic", - "contributions": [ - "code" - ] - }, - { - "login": "alexdewar", - "name": "Alex Dewar", - "avatar_url": "https://avatars.githubusercontent.com/u/23149834?v=4", - "profile": "https://profiles.sussex.ac.uk/p281168-alex-dewar/publications", - "contributions": [ - "code" - ] - }, - { - "login": "trokhymchuk", - "name": "Artem Trokhymchuk ", - "avatar_url": "https://avatars.githubusercontent.com/u/66204814?v=4", - "profile": "https://github.com/trokhymchuk", - "contributions": [ - "code" - ] - }, - { - "login": "dherrera-fb", - "name": "dherrera-fb", - "avatar_url": "https://avatars.githubusercontent.com/u/89840711?v=4", - "profile": "https://github.com/dherrera-fb", - "contributions": [ - "code" - ] - }, - { - "login": "VolkerChristian", - "name": "Volker Christian", - "avatar_url": "https://avatars.githubusercontent.com/u/18554540?v=4", - "profile": "https://github.com/VolkerChristian", - "contributions": [ - "code" - ] - }, - { - "login": "thewtex", - "name": "Matt McCormick", - "avatar_url": "https://avatars.githubusercontent.com/u/25432?v=4", - "profile": "https://www.mmmccormick.com/", - "contributions": [ - "code" - ] - }, - { - "login": "polistern", - "name": "polistern", - "avatar_url": "https://avatars.githubusercontent.com/u/55511995?v=4", - "profile": "http://polistern.i2p/", - "contributions": [ - "code" - ] - }, - { - "login": "andreasxp", - "name": "Andrey Zhukov", - "avatar_url": "https://avatars.githubusercontent.com/u/28830446?v=4", - "profile": "https://github.com/andreasxp", - "contributions": [ - "code" - ] - }, - { - "login": "SherlockInSpace", - "name": "Ryan Sherlock", - "avatar_url": "https://avatars.githubusercontent.com/u/5507786?v=4", - "profile": "https://github.com/SherlockInSpace", - "contributions": [ - "code" - ] - }, - { - "login": "Krzmbrzl", - "name": "Robert Adam", - "avatar_url": "https://avatars.githubusercontent.com/u/12751591?v=4", - "profile": "https://github.com/Krzmbrzl", - "contributions": [ - "code" - ] - }, - { - "login": "RangeMachine", - "name": "RangeMachine", - "avatar_url": "https://avatars.githubusercontent.com/u/11577601?v=4", - "profile": "https://github.com/RangeMachine", - "contributions": [ - "code" - ] - }, - { - "login": "ptheywood", - "name": "Peter Heywood", - "avatar_url": "https://avatars.githubusercontent.com/u/628937?v=4", - "profile": "http://ptheywood.uk/", - "contributions": [ - "code" - ] - }, - { - "login": "peterh", - "name": "Peter Harris", - "avatar_url": "https://avatars.githubusercontent.com/u/79339?v=4", - "profile": "https://github.com/peterh", - "contributions": [ - "code" - ] - }, - { - "login": "PeteAudinate", - "name": "PeteAudinate", - "avatar_url": "https://avatars.githubusercontent.com/u/99274874?v=4", - "profile": "https://github.com/PeteAudinate", - "contributions": [ - "code" - ] - }, - { - "login": "captainurist", - "name": "captainurist", - "avatar_url": "https://avatars.githubusercontent.com/u/73941350?v=4", - "profile": "https://github.com/captainurist", - "contributions": [ - "code" - ] - }, - { - "login": "djerius", - "name": "djerius", - "avatar_url": "https://avatars.githubusercontent.com/u/196875?v=4", - "profile": "https://github.com/djerius", - "contributions": [ - "code" - ] - }, - { - "login": "shameekganguly", - "name": "shameekganguly", - "avatar_url": "https://avatars.githubusercontent.com/u/2412842?v=4", - "profile": "https://github.com/shameekganguly", - "contributions": [ - "code" - ] - }, - { - "login": "ayum", - "name": "ayum", - "avatar_url": "https://avatars.githubusercontent.com/u/6747040?v=4", - "profile": "https://github.com/ayum", - "contributions": [ - "code" - ] - }, - { - "login": "BenjaminBeichler", - "name": "Benjamin Beichler", - "avatar_url": "https://avatars.githubusercontent.com/u/1441492?v=4", - "profile": "https://github.com/BenjaminBeichler", - "contributions": [ - "code" - ] - }, - { - "login": "DarkWingMcQuack", - "name": "DarkWingMcQuack", - "avatar_url": "https://avatars.githubusercontent.com/u/38857302?v=4", - "profile": "https://github.com/DarkWingMcQuack", - "contributions": [ - "code" - ] - }, - { - "login": "eli-schwartz", - "name": "Eli Schwartz", - "avatar_url": "https://avatars.githubusercontent.com/u/6551424?v=4", - "profile": "https://github.com/eli-schwartz", - "contributions": [ - "code" - ] - }, - { - "login": "bruxisma", - "name": "Izzy Muerte", - "avatar_url": "https://avatars.githubusercontent.com/u/63051?v=4", - "profile": "https://izzys.casa/", - "contributions": [ - "code" - ] - }, - { - "login": "j-rivero", - "name": "Jose Luis Rivero", - "avatar_url": "https://avatars.githubusercontent.com/u/2098802?v=4", - "profile": "https://github.com/j-rivero", - "contributions": [ - "code" - ] - }, - { - "login": "looopTools", - "name": "Lars Nielsen", - "avatar_url": "https://avatars.githubusercontent.com/u/1943536?v=4", - "profile": "https://github.com/looopTools", - "contributions": [ - "code" - ] - }, - { - "login": "cetius", - "name": "Marcin Ropa", - "avatar_url": "https://avatars.githubusercontent.com/u/6552472?v=4", - "profile": "https://github.com/cetius", - "contributions": [ - "code" - ] - }, - { - "login": "nathanielhourt", - "name": "Nathaniel Hourt", - "avatar_url": "https://avatars.githubusercontent.com/u/271977?v=4", - "profile": "https://github.com/nathanielhourt", - "contributions": [ - "code" - ] - } - ], - "contributorsSortAlphabetically": true, - "contributorsPerLine": 7, - "skipCi": true, - "commitType": "docs" -} diff --git a/external/CLI11/.ci/azure-build.yml b/external/CLI11/.ci/azure-build.yml deleted file mode 100644 index 04ee5d6be..000000000 --- a/external/CLI11/.ci/azure-build.yml +++ /dev/null @@ -1,23 +0,0 @@ -steps: - # Needed on GCC 4.8 docker image for some reason - - script: mkdir build - displayName: "Make build directory" - - - task: CMake@1 - inputs: - cmakeArgs: - .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=$(cli11.single) - -DCMAKE_CXX_STANDARD=$(cli11.std) - -DCLI11_SINGLE_FILE_TESTS=$(cli11.single) - -DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options) - displayName: "Configure" - - - script: cmake --build . -- -j2 --keep-going - displayName: "Build Unix" - workingDirectory: build - condition: ne( variables['Agent.OS'], 'Windows_NT' ) - - - script: cmake --build . - displayName: "Build Windows" - workingDirectory: build - condition: eq( variables['Agent.OS'], 'Windows_NT' ) diff --git a/external/CLI11/.ci/azure-cmake-new.yml b/external/CLI11/.ci/azure-cmake-new.yml deleted file mode 100644 index 56a2fb4d9..000000000 --- a/external/CLI11/.ci/azure-cmake-new.yml +++ /dev/null @@ -1,17 +0,0 @@ -steps: - # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification - - bash: | - wget --no-check-certificate "https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz" - echo "898f0b5ca6e2ea5286998e97bd33f030d7d09f18ca4b88be661fdfbad5dadd88 cmake-3.28.0-linux-x86_64.tar.gz" | shasum -sca 256 - displayName: Download CMake - - - task: ExtractFiles@1 - inputs: - archiveFilePatterns: "cmake*.tar.gz" - destinationFolder: "cmake_program" - displayName: Extract CMake - - - bash: - echo - "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.28.0-linux-x86_64/bin" - displayName: Add CMake to PATH diff --git a/external/CLI11/.ci/azure-cmake.yml b/external/CLI11/.ci/azure-cmake.yml deleted file mode 100644 index a2f3d983a..000000000 --- a/external/CLI11/.ci/azure-cmake.yml +++ /dev/null @@ -1,17 +0,0 @@ -steps: - # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification - - bash: | - wget --no-check-certificate "https://cmake.org/files/v3.14/cmake-3.14.3-Linux-x86_64.tar.gz" - echo "29faa62fb3a0b6323caa3d9557e1a5f1205614c0d4c5c2a9917f16a74f7eff68 cmake-3.14.3-Linux-x86_64.tar.gz" | shasum -sca 256 - displayName: Download CMake - - - task: ExtractFiles@1 - inputs: - archiveFilePatterns: "cmake*.tar.gz" - destinationFolder: "cmake_program" - displayName: Extract CMake - - - bash: - echo - "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.14.3-Linux-x86_64/bin" - displayName: Add CMake to PATH diff --git a/external/CLI11/.ci/azure-test.yml b/external/CLI11/.ci/azure-test.yml deleted file mode 100644 index c9dc9a280..000000000 --- a/external/CLI11/.ci/azure-test.yml +++ /dev/null @@ -1,9 +0,0 @@ -steps: - - script: ctest --output-on-failure -C $(cli11.build_type) -T test - displayName: "Test" - workingDirectory: build - - - task: PublishTestResults@2 - inputs: - testResultsFormat: "cTest" - testResultsFiles: "**/Test.xml" diff --git a/external/CLI11/.clang-format b/external/CLI11/.clang-format deleted file mode 100644 index 6a5d1063d..000000000 --- a/external/CLI11/.clang-format +++ /dev/null @@ -1,86 +0,0 @@ -Language: Cpp -BasedOnStyle: LLVM -# AccessModifierOffset: -2 -# AlignAfterOpenBracket: Align -# AlignConsecutiveAssignments: false -# AlignConsecutiveDeclarations: false -# AlignEscapedNewlinesLeft: false -# AlignOperands: true -# AlignTrailingComments: true -# AllowAllParametersOfDeclarationOnNextLine: true -# AllowShortBlocksOnASingleLine: false -# AllowShortCaseLabelsOnASingleLine: false -# AllowShortFunctionsOnASingleLine: All -# AllowShortIfStatementsOnASingleLine: false -# AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType: None -# AlwaysBreakAfterReturnType: None -# AlwaysBreakBeforeMultilineStrings: false -# AlwaysBreakTemplateDeclarations: false -BinPackArguments: false -BinPackParameters: false -# BraceWrapping: -# AfterClass: false -# AfterControlStatement: false -# AfterEnum: false -# AfterFunction: false -# AfterNamespace: false -# AfterObjCDeclaration: false -# AfterStruct: false -# AfterUnion: false -# BeforeCatch: false -# BeforeElse: false -# IndentBraces: false -# BreakBeforeBinaryOperators: None -# BreakBeforeBraces: Attach -# BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false -# BreakAfterJavaFieldAnnotations: false -# BreakStringLiterals: true -ColumnLimit: 120 -# CommentPragmas: '^ IWYU pragma:' -# ConstructorInitializerAllOnOneLineOrOnePerLine: false -# ConstructorInitializerIndentWidth: 4 -# ContinuationIndentWidth: 4 -# Cpp11BracedListStyle: true -# DerivePointerAlignment: false -# DisableFormat: false -# ExperimentalAutoDetectBinPacking: false -# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -# IncludeIsMainRegex: '$' -# IndentCaseLabels: false -IndentWidth: 4 -# IndentWrappedFunctionNames: false -# JavaScriptQuotes: Leave -# JavaScriptWrapImports: true -# KeepEmptyLinesAtTheStartOfBlocks: true -# MacroBlockBegin: '' -# MacroBlockEnd: '' -# MaxEmptyLinesToKeep: 1 -# NamespaceIndentation: None -# ObjCBlockIndentWidth: 2 -# ObjCSpaceAfterProperty: false -# ObjCSpaceBeforeProtocolList: true -# PenaltyBreakBeforeFirstCallParameter: 19 -# PenaltyBreakComment: 300 -# PenaltyBreakFirstLessLess: 120 -# PenaltyBreakString: 1000 -# PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 -# PointerAlignment: Right -# ReflowComments: true -SortIncludes: true -# SpaceAfterCStyleCast: false -# SpaceAfterTemplateKeyword: true -# SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: Never -# SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 2 -# SpacesInAngles: false -# SpacesInContainerLiterals: true -# SpacesInCStyleCastParentheses: false -# SpacesInParentheses: false -# SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never diff --git a/external/CLI11/.clang-tidy b/external/CLI11/.clang-tidy deleted file mode 100644 index 727b76525..000000000 --- a/external/CLI11/.clang-tidy +++ /dev/null @@ -1,83 +0,0 @@ -# Checks that will be implemented in future PRs: -# performance-unnecessary-value-param, hints to ~110 issues. Be careful with implementing the suggested changes of this one, as auto-fixes may break the code -# bugprone-forwarding-reference-overload probably should be enabled and fixed. -# clang-diagnostic-float-equal can be fixed by using _a from Catch::literals -# bugprone-exception-escape due to main being a bit simple in examples -# modernize-avoid-c-arrays trips up in TEMPLATE_TEST_CASE catch macro -# modernize-return-braced-init-list triggers on lambdas ? -# modernize-make-unique requires C++14 -# modernize-type_traits requires C++17 -# readability-avoid-const-params-in-decls Affected by the pre-compile split - -Checks: | - *bugprone*, - -bugprone-easily-swappable-parameters, - -bugprone-forwarding-reference-overload, - -bugprone-exception-escape, - clang-analyzer-optin.cplusplus.VirtualCall, - clang-analyzer-optin.performance.Padding, - -clang-diagnostic-float-equal, - cppcoreguidelines-init-variables, - cppcoreguidelines-prefer-member-initializer, - cppcoreguidelines-pro-type-static-cast-downcast, - cppcoreguidelines-slicing, - google-*, - -google-runtime-references, - llvm-include-order, - llvm-namespace-comment, - misc-definitions-in-headers, - misc-misplaced-const, - misc-non-copyable-objects, - misc-static-assert, - misc-throw-by-value-catch-by-reference, - misc-throw-by-value-catch-by-reference, - misc-uniqueptr-reset-release, - misc-unused-parameters, - modernize*, - -modernize-use-trailing-return-type, - -modernize-concat-nested-namespaces, - -modernize-return-braced-init-list, - -modernize-make-unique, - -modernize-type-traits, - -modernize-macro-to-enum, - *performance*, - -performance-unnecessary-value-param, - -performance-inefficient-string-concatenation, - readability-const-return-type, - readability-container-size-empty, - readability-delete-null-pointer, - readability-else-after-return, - readability-implicit-bool-conversion, - readability-inconsistent-declaration-parameter-name, - readability-make-member-function-const, - readability-misplaced-array-index, - readability-non-const-parameter, - readability-qualified-auto, - readability-redundant-function-ptr-dereference, - readability-redundant-smartptr-get, - readability-redundant-string-cstr, - readability-simplify-subscript-expr, - readability-static-accessed-through-instance, - readability-static-definition-in-anonymous-namespace, - readability-string-compare, - readability-suspicious-call-argument, - readability-uniqueptr-delete-release, - -CheckOptions: - - key: google-readability-braces-around-statements.ShortStatementLines - value: "3" - - key: performance-for-range-copy.WarnOnAllAutoCopies - value: true - - key: performance-inefficient-string-concatenation.StrictMode - value: true - - key: performance-unnecessary-value-param.AllowedTypes - value: "exception_ptr$;" - - key: readability-implicit-bool-conversion.AllowPointerConditions - value: true - - key: modernize-use-nodiscard.ReplacementString - value: "CLI11_NODISCARD" - -HeaderFilterRegex: "CLI.*hpp" - -FormatStyle: file -# WarningsAsErrors: "*" diff --git a/external/CLI11/.cmake-format.yaml b/external/CLI11/.cmake-format.yaml deleted file mode 100644 index 543ddf19f..000000000 --- a/external/CLI11/.cmake-format.yaml +++ /dev/null @@ -1,6 +0,0 @@ -format: - line_width: 99 - -# Causes a few issues - can be solved later, possibly. -markup: - enable_markup: false diff --git a/external/CLI11/.codacy.yml b/external/CLI11/.codacy.yml deleted file mode 100644 index 03a1e522b..000000000 --- a/external/CLI11/.codacy.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -engines: - rubocop: - enabled: true - duplication: - enabled: true - metrics: - enabled: true - coverage: - enabled: false -languages: - -exclude_paths: - - "fuzz/**/*" - - "fuzz/*" - - "scripts/**/*" - - "scripts/*" - - "**.md" diff --git a/external/CLI11/.codecov.yml b/external/CLI11/.codecov.yml deleted file mode 100644 index 61c2e2f21..000000000 --- a/external/CLI11/.codecov.yml +++ /dev/null @@ -1,7 +0,0 @@ -ignore: - - "tests" - - "examples" - - "book" - - "docs" - - "test_package" - - "fuzz" diff --git a/external/CLI11/.editorconfig b/external/CLI11/.editorconfig deleted file mode 100644 index 3c6f665e6..000000000 --- a/external/CLI11/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -root = true - -[*] -indent_style = space -insert_final_newline = true -end_of_line = lf -trim_trailing_whitespace = true - -[*.cpp,*.hpp,*.py] -indent_size = 4 - -[*.yml] -indent_size = 2 diff --git a/external/CLI11/.github/CONTRIBUTING.md b/external/CLI11/.github/CONTRIBUTING.md deleted file mode 100644 index 7e4abed11..000000000 --- a/external/CLI11/.github/CONTRIBUTING.md +++ /dev/null @@ -1,90 +0,0 @@ -# Contributing - -Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few -guidelines to get you started: - -Make sure you are comfortable with the license; all contributions are licensed -under the original license. - -## Adding functionality - -Make sure any new functions you add are are: - -- Documented by `///` documentation for Doxygen -- Mentioned in the instructions in the README, though brief mentions are okay -- Explained in your PR (or previously explained in an Issue mentioned in the PR) -- Completely covered by tests - -In general, make sure the addition is well thought out and does not increase the -complexity of CLI11 needlessly. - -## Things you should know - -- Once you make the PR, tests will run to make sure your code works on all - supported platforms -- The test coverage is also measured, and that should remain 100% -- Formatting should be done with pre-commit, otherwise the format check will not - pass. However, it is trivial to apply this to your PR, so don't worry about - this check. If you do want to run it, see below. -- Everything must pass clang-tidy as well, run with - `-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy)"` (if you set - `"$(which clang-tidy) -fix"`, make sure you use a single threaded build - process, or just build one example target). -- Your changes must also conform to most of the - [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) - rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused - cpplint filters and justifications, see [CPPLINT.cfg](/CPPLINT.cfg). - -## Pre-commit - -Format is handled by pre-commit. You should install it (or use -[pipx](https://pypa.github.io/pipx/)): - -```bash -python3 -m pip install pre-commit -``` - -Then, you can run it on the items you've added to your staging area, or all -files: - -```bash -pre-commit run -# OR -pre-commit run --all-files -``` - -And, if you want to always use it, you can install it as a git hook (hence the -name, pre-commit): - -```bash -pre-commit install -``` - -## For maintainers: remember to add contributions - -In a commit to a PR, just add -"`@all-contributors please add for `" or similar (see -). Use `code` for code, `bug` if an issue was -submitted, `platform` for packaging stuff, and `doc` for documentation updates. - -To run locally, do: - -```bash -yarn add --dev all-contributors-cli -yarn all-contributors add username code,bug -``` - -## For maintainers: Making a release - -Remember to replace the emoji in the readme, being careful not to replace the -ones in all-contributors if any overlap. - -Steps: - -- Update changelog if needed -- Update the version in `include/CLI/Version.hpp`. -- Find and replace in README (new minor/major release only): - - Replace " 🆕" and "🆕 " with "" (ignores the description line) - - Check for `\/\/$` (vi syntax) to catch leftover `// 🆕` - - Replace "🚧" with "🆕" (manually ignore the description line) -- Make a release in the GitHub UI, use a name such as "Version X.Y(.Z): Title" diff --git a/external/CLI11/.github/actions/quick_cmake/action.yml b/external/CLI11/.github/actions/quick_cmake/action.yml deleted file mode 100644 index d2b3825fe..000000000 --- a/external/CLI11/.github/actions/quick_cmake/action.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Quick CMake config -description: "Runs CMake 3.5+ (if already setup)" -inputs: - args: - description: "Other arguments" - required: false - default: "" - cmake-version: - description: "The CMake version to run" - required: true - -runs: - using: composite - steps: - - name: CMake ${{ inputs.cmake-version }} - uses: jwlawson/actions-setup-cmake@v1.14 - with: - cmake-version: "${{ inputs.cmake-version }}" - - run: | - mkdir -p build-tmp - touch build-tmp/tmp - rm -r build-tmp/* - (cd build-tmp && cmake .. ${{ inputs.args }}) - rm -r build-tmp - shell: bash diff --git a/external/CLI11/.github/codecov.yml b/external/CLI11/.github/codecov.yml deleted file mode 100644 index 0e106f710..000000000 --- a/external/CLI11/.github/codecov.yml +++ /dev/null @@ -1,7 +0,0 @@ -codecov: - notify: - after_n_builds: 8 -coverage: - status: - project: - informational: true diff --git a/external/CLI11/.github/dependabot.yml b/external/CLI11/.github/dependabot.yml deleted file mode 100644 index 40aaf098f..000000000 --- a/external/CLI11/.github/dependabot.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 -updates: - # Maintain dependencies for GitHub Actions - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - target-branch: "main" - open-pull-requests-limit: 10 - groups: - actions: - patterns: - - "*" diff --git a/external/CLI11/.github/labeler_merged.yml b/external/CLI11/.github/labeler_merged.yml deleted file mode 100644 index 96e1ca701..000000000 --- a/external/CLI11/.github/labeler_merged.yml +++ /dev/null @@ -1,4 +0,0 @@ -needs changelog: - - all: ["!CHANGELOG.md"] -needs README: - - all: ["!README.md"] diff --git a/external/CLI11/.github/workflows/build.yml b/external/CLI11/.github/workflows/build.yml deleted file mode 100644 index 57d54dc16..000000000 --- a/external/CLI11/.github/workflows/build.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Build -on: - push: - branches: - - main - - v* - tags: - - "*" - pull_request: - -jobs: - single-header: - name: Single header - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - - uses: actions/setup-python@v5 - with: - python-version: "3.x" - - - name: Prepare CMake config - run: cmake -S . -B build -DCLI11_SINGLE_FILE=ON - - - name: Make package - run: cmake --build build --target package_source - - - name: Copy source packages - run: | - mkdir -p CLI11-Source - cp build/CLI11-*-Source.* CLI11-Source - cp build/CLI11-*-Source.* . - - - name: Make header - run: cmake --build build --target CLI11-generate-single-file - - - name: Copy file to main folder - run: cp build/include/CLI11.hpp CLI11.hpp - - - uses: actions/upload-artifact@v4 - with: - name: CLI11.hpp - path: CLI11.hpp - - - uses: actions/upload-artifact@v4 - with: - name: CLI11-Source - path: CLI11-Source - - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: | - CLI11.hpp - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/external/CLI11/.github/workflows/docs.yml b/external/CLI11/.github/workflows/docs.yml deleted file mode 100644 index 6b79b352f..000000000 --- a/external/CLI11/.github/workflows/docs.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: Docs - -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - apidocs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: mattnotmitt/doxygen-action@v1 - with: - doxyfile-path: ./docs/Doxyfile - - - uses: actions/upload-artifact@v4 - with: - name: api-docs - path: html - - gitbook: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: 16 - - - uses: awalsh128/cache-apt-pkgs-action@v1 - with: - packages: calibre calibre-bin libxss1 libasound2 - version: 1 - - - name: Install JS requirements - working-directory: book - run: | - npm install - - - name: Build book - working-directory: book - run: | - npx gitbook build . public - npx gitbook pdf . public/cli11.pdf - - - uses: actions/upload-artifact@v4 - with: - name: gitbook - path: book/public - - pages: - runs-on: ubuntu-latest - needs: [apidocs, gitbook] - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - if: > - success() - && github.ref == 'refs/heads/main' - && github.repository == 'CLIUtils/CLI11' - steps: - - uses: actions/configure-pages@v4 - id: pages - - - uses: actions/download-artifact@v4 - with: - name: api-docs - path: _site - - - uses: actions/download-artifact@v4 - with: - name: gitbook - path: _site/book - - - uses: actions/upload-pages-artifact@v3 - - - uses: actions/deploy-pages@v4 - id: deployment diff --git a/external/CLI11/.github/workflows/fuzz.yml b/external/CLI11/.github/workflows/fuzz.yml deleted file mode 100644 index 413f150fb..000000000 --- a/external/CLI11/.github/workflows/fuzz.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Fuzz -on: - workflow_dispatch: - push: - branches: - - main - - v* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - quick_fuzz1: - name: quickfuzz1 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Configure - run: | - cmake -S . -B build \ - -DCMAKE_CXX_STANDARD=17 \ - -DCLI11_SINGLE_FILE_TESTS=OFF \ - -DCLI11_BUILD_EXAMPLES=OFF \ - -DCLI11_FUZZ_TARGET=ON \ - -DCLI11_BUILD_TESTS=OFF \ - -DCLI11_BUILD_DOCS=OFF \ - -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_COMPILER_FORCED=ON \ - -DCMAKE_CXX_FLAGS="-g -O1 -fsanitize=fuzzer,undefined,address" - - - name: Build - run: cmake --build build -j4 - - - name: Test_app - run: | - cd build - make QUICK_CLI11_APP_FUZZ - - - name: Test_file - run: | - cd build - make QUICK_CLI11_FILE_FUZZ - - - - name: artifacts - if: failure() - uses: actions/upload-artifact@v4 - with: - name: file_failure - path: ./build/fuzz/cli11_*_fail_artifact.txt diff --git a/external/CLI11/.github/workflows/pr_merged.yml b/external/CLI11/.github/workflows/pr_merged.yml deleted file mode 100644 index 56f6f741f..000000000 --- a/external/CLI11/.github/workflows/pr_merged.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: PR merged -on: - pull_request_target: - types: [closed] - -jobs: - label-merged: - name: Changelog needed - runs-on: ubuntu-latest - if: github.event.pull_request.merged == true - steps: - - uses: actions/labeler@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - configuration-path: .github/labeler_merged.yml diff --git a/external/CLI11/.github/workflows/tests.yml b/external/CLI11/.github/workflows/tests.yml deleted file mode 100644 index d2c44e008..000000000 --- a/external/CLI11/.github/workflows/tests.yml +++ /dev/null @@ -1,377 +0,0 @@ -name: Tests -on: - push: - branches: - - main - - v* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - CTEST_OUTPUT_ON_FAILURE: "1" - -jobs: - coverage: - name: Coverage - runs-on: ubuntu-latest - strategy: - matrix: - std: ["11", "14", "17", "20"] - precompile: ["ON", "OFF"] - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Get LCov - run: | - wget https://github.com/linux-test-project/lcov/releases/download/v1.16/lcov-1.16.tar.gz - tar -xzf lcov-1.16.tar.gz - cd lcov-1.16 - sudo make install - - - name: Configure - run: | - cmake -S . -B build \ - -DCMAKE_CXX_STANDARD=${{matrix.std}} \ - -DCLI11_SINGLE_FILE_TESTS=OFF \ - -DCLI11_BUILD_EXAMPLES=OFF \ - -DCLI11_PRECOMPILED=${{matrix.precompile}} \ - -DCMAKE_BUILD_TYPE=Coverage - - - name: Build - run: cmake --build build -j4 - - - name: Test - run: cmake --build build --target CLI11_coverage - - - name: Prepare coverage - run: | - lcov --directory . --capture --output-file coverage.info - lcov --remove coverage.info '*/tests/*' '*/examples/*' '/usr/*' '*/book/*' '*/fuzz/*' --output-file coverage.info - lcov --list coverage.info - working-directory: build - - - uses: codecov/codecov-action@v4 - with: - files: build/coverage.info - functionalities: fixes - - catch2-3: - name: Catch 2 3.x - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: Get Catch 2 - run: brew install catch2 - - - name: Configure - run: | - cmake -S . -B build \ - -DCMAKE_CXX_STANDARD=14 \ - -DCLI11_SINGLE_FILE_TESTS=OFF \ - -DCLI11_BUILD_EXAMPLES=OFF \ - -DCLI11_PRECOMPILED=ON - - - name: Build - run: cmake --build build -j4 - - - name: Test - run: cmake --build build --target test - - - clang-tidy: - name: Clang-Tidy - runs-on: ubuntu-latest - container: silkeh/clang:17 - steps: - - uses: actions/checkout@v4 - - - name: Configure - run: > - cmake -S . -B build -DCMAKE_CXX_STANDARD=17 - -DCMAKE_CXX_CLANG_TIDY="$(which - clang-tidy);--use-color;--warnings-as-errors=*" - - - name: Build - run: cmake --build build -j4 -- --keep-going - - cuda11-build: - name: CUDA 11 build only - runs-on: ubuntu-latest - container: nvidia/cuda:11.8.0-devel-ubuntu22.04 - steps: - - name: Add build tools - run: apt-get update && apt-get install -y wget git cmake - - uses: actions/checkout@v4 - with: - submodules: true - - name: Configure - run: cmake -S . -B build -DCLI11_CUDA_TESTS=ON - - name: Build - run: cmake --build build -j2 - - cuda12-build: - name: CUDA 12 build only - runs-on: ubuntu-latest - container: nvidia/cuda:12.3.1-devel-ubuntu22.04 - steps: - - name: Add build tools - run: apt-get update && apt-get install -y wget git cmake - - uses: actions/checkout@v4 - with: - submodules: true - - name: Configure - run: cmake -S . -B build -DCLI11_CUDA_TESTS=ON - - name: Build - run: cmake --build build -j2 - - boost-build: - name: Boost build - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Add boost - run: sudo apt-get update && sudo apt-get install -y libboost-dev - # NOTE: If a boost version matching all requirements cannot be found, - # this build step will fail - - name: Configure - run: cmake -S . -B build -DCLI11_BOOST=ON - - name: Build - run: cmake --build build -j2 - - name: Run tests - run: ctest --output-on-failure - working-directory: build - - meson-build: - name: Meson build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Prepare commands - run: | - pipx install meson - pipx install ninja - - - name: Configure - run: meson setup build-meson . -Dtests=true - - - name: Build - run: meson compile -C build-meson - - install: - name: install tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Configure - run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install - - name: Build - run: cmake --build build -j2 - - name: install - run: cmake --install build - - name: Run tests - run: ctest --output-on-failure -L Packaging - working-directory: build - - install-precompiled: - name: install tests precompiled - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Configure - run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install -DCLI11_PRECOMPILED=ON - - name: Build - run: cmake --build build -j2 - - name: install - run: cmake --install build - - name: Run tests - run: ctest --output-on-failure -L Packaging - working-directory: build - - install-single_file: - name: install tests single file - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Configure - run: cmake -S . -B build -DCLI11_INSTALL_PACKAGE_TESTS=ON -DCMAKE_INSTALL_PREFIX=/home/runner/work/install -DCLI11_SINGLE_FILE=ON - - name: Build - run: cmake --build build -j2 - - name: install - run: cmake --install build - - name: Run tests - run: ctest --output-on-failure -L Packaging - working-directory: build - - cmake-config-ubuntu-2004: - name: CMake config check (Ubuntu 20.04) - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - - name: Check CMake 3.5 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.5" - if: success() || failure() - - - name: Check CMake 3.6 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.6" - if: success() || failure() - - - name: Check CMake 3.7 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.7" - if: success() || failure() - - - name: Check CMake 3.8 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.8" - if: success() || failure() - - - name: Check CMake 3.9 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.9" - if: success() || failure() - - - name: Check CMake 3.10 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.10" - if: success() || failure() - - - name: Check CMake 3.11 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.11" - if: success() || failure() - - - name: Check CMake 3.12 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.12" - if: success() || failure() - - - name: Check CMake 3.13 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.13" - if: success() || failure() - - - name: Check CMake 3.14 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.14" - args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON - if: success() || failure() - - - name: Check CMake 3.15 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.15" - if: success() || failure() - - - name: Check CMake 3.16 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.16" - if: success() || failure() - - cmake-config-ubuntu-2204: - name: CMake config check (Ubuntu 22.04) - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - - name: Check CMake 3.17 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.17" - if: success() || failure() - - - name: Check CMake 3.18 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.18" - if: success() || failure() - - - name: Check CMake 3.19 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.19" - if: success() || failure() - - - name: Check CMake 3.20 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.20" - if: success() || failure() - - - name: Check CMake 3.21 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.21" - if: success() || failure() - - - name: Check CMake 3.22 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.22" - if: success() || failure() - - - name: Check CMake 3.23 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.23" - if: success() || failure() - - - name: Check CMake 3.24 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.24" - if: success() || failure() - - - name: Check CMake 3.25 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.25" - if: success() || failure() - - - name: Check CMake 3.26 (full) - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.26" - args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON - if: success() || failure() - - - name: Check CMake 3.27 - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.27" - if: success() || failure() - - - name: Check CMake 3.28 (full) - uses: ./.github/actions/quick_cmake - with: - cmake-version: "3.28" - args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON - if: success() || failure() diff --git a/external/CLI11/.gitignore b/external/CLI11/.gitignore deleted file mode 100644 index 7b9bcb27f..000000000 --- a/external/CLI11/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -a.out* -*.swp -/*build* -/test_package/build -/Makefile -/CMakeFiles/* -/cmake_install.cmake -/*.kdev4 -/.vscode -/html/* -!/meson.build -/CMakeUserPresets.json - -/node_modules/* -/package.json -/yarn.lock -/CLI11.hpp - -/subprojects/Catch2-* -/subprojects/packagecache diff --git a/external/CLI11/.pre-commit-config.yaml b/external/CLI11/.pre-commit-config.yaml deleted file mode 100644 index 5c0fd894b..000000000 --- a/external/CLI11/.pre-commit-config.yaml +++ /dev/null @@ -1,93 +0,0 @@ -exclude: ^(.github/workflows/|docs/img/) -ci: - autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" - autofix_commit_msg: "style: pre-commit.ci fixes" - -repos: - - repo: https://github.com/psf/black - rev: 24.1.1 - hooks: - - id: black - - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: check-added-large-files - - id: check-case-conflict - - id: check-merge-conflict - - id: check-symlinks - - id: check-yaml - - id: check-toml - - id: end-of-file-fixer - - id: mixed-line-ending - - id: trailing-whitespace - - id: check-shebang-scripts-are-executable - - id: check-executables-have-shebangs - - id: debug-statements - - - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.6 - hooks: - - id: clang-format - types_or: [c++, c, cuda] - - - repo: https://github.com/cheshirekow/cmake-format-precommit - rev: v0.6.13 - hooks: - - id: cmake-format - additional_dependencies: [pyyaml] - - - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v4.0.0-alpha.8" - hooks: - - id: prettier - types_or: [yaml, markdown, html, css, scss, javascript, json] - args: [--prose-wrap=always] - - - repo: https://github.com/markdownlint/markdownlint - rev: v0.12.0 - hooks: - - id: markdownlint - args: ["--style=scripts/mdlint_style.rb"] - # Uncomment on macOS - Apple has deprecated Ruby, so macOS is stuck on 2.6 - # language_version: 3.1.2 - - # - repo: local - # hooks: - # - id: remarklint - # name: remarklint - # language: node - # entry: remark - # types: [markdown] - # args: ["--frail", "--quiet"] - # additional_dependencies: - # [ - # remark, - # remark-lint, - # remark-cli, - # remark-preset-lint-recommended, - # remark-lint-list-item-indent, - # remark-lint-no-undefined-references, - # ] - - - repo: local - hooks: - - id: disallow-caps - name: Disallow improper capitalization - language: pygrep - entry: PyBind|Numpy|Cmake|CCache|PyTest|Github - exclude: .pre-commit-config.yaml - - - repo: local - hooks: - - id: avoid-msvc-macro - name: Avoid MSVC <=2017 min/max macro (use extra parens) - language: pygrep - entry: \b(min|max)\( - exclude: .pre-commit-config.yaml - - - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 - hooks: - - id: codespell - args: ["-L", "atleast,ans,doub,inout"] diff --git a/external/CLI11/.remarkrc b/external/CLI11/.remarkrc deleted file mode 100644 index 73cad8328..000000000 --- a/external/CLI11/.remarkrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "plugins": [ - "remark-preset-lint-recommended", - ["remark-lint-list-item-indent", "space"], - ["remark-lint-no-undefined-references", {"allow": ["^1"]}] - ] -} diff --git a/external/CLI11/CHANGELOG.md b/external/CLI11/CHANGELOG.md deleted file mode 100644 index 8293b13de..000000000 --- a/external/CLI11/CHANGELOG.md +++ /dev/null @@ -1,1116 +0,0 @@ -# Changelog - -## Version 2.4: Unicode and TOML support - -This version adds Unicode support, support for TOML standard including multiline -strings, digit separators, string escape sequences,and dot notation. An initial -round of a fuzzer was added to testing which has caught several bugs related to -config file processing, and a few other edge cases not previously observed. - -- Add Unicode support and bug fixes [#804][], [#923][], [#876][], [#848][], - [#832][], [#987][] -- Match TOML standard for string and numerical entries, multiline strings - [#968][], [#967][],[#964][], [#935][] -- Add validation for environmental variables [#926][] -- Add an escape string transform [#970][] -- Add A REVERSE multi-option policy to support multiple config files and other - applications [#918][] -- Add usage message replacement [#768][] -- Allow using dot notation for subcommand arguments such as `--sub1.field` - [#789][] -- Bugfix: Fuzzing tests and fixes [#930][], [#905][], [#874][], [#846][] -- Bugfix: Missing coverage tests [#928][] -- Bugfix: CMake package and package config tests and fixes [#916][] -- Bugfix: Support for Windows ARM compilation and tests [#913][], [#914][] -- Bugfix: Environmental variable checks in non-triggered subcommands [#904][] -- Bugfix: Environmental variables were not being correctly process by config - pointer [#891][] -- Bugfix: Undefined behavior in `sum_string_vector` [#893][] -- Bugfix: Warnings and updates for CUDA 11 support [#851][] -- Backend: Add tests for newer compilers (lost with Travis CI) [#972][] -- Backend: Increase minimum CMake to 3.5 [#898][] -- Backend: Remove integrated Conan support (provided now by Conan center) - [#853][] -- Tests: Support Catch2 Version 3 [#896][], [#980][] - -[#768]: https://github.com/CLIUtils/CLI11/pull/768 -[#789]: https://github.com/CLIUtils/CLI11/pull/789 -[#804]: https://github.com/CLIUtils/CLI11/pull/804 -[#832]: https://github.com/CLIUtils/CLI11/pull/832 -[#846]: https://github.com/CLIUtils/CLI11/pull/846 -[#848]: https://github.com/CLIUtils/CLI11/pull/848 -[#851]: https://github.com/CLIUtils/CLI11/pull/851 -[#853]: https://github.com/CLIUtils/CLI11/pull/853 -[#874]: https://github.com/CLIUtils/CLI11/pull/874 -[#876]: https://github.com/CLIUtils/CLI11/pull/876 -[#891]: https://github.com/CLIUtils/CLI11/pull/891 -[#893]: https://github.com/CLIUtils/CLI11/pull/893 -[#896]: https://github.com/CLIUtils/CLI11/pull/896 -[#898]: https://github.com/CLIUtils/CLI11/pull/898 -[#904]: https://github.com/CLIUtils/CLI11/pull/904 -[#905]: https://github.com/CLIUtils/CLI11/pull/905 -[#913]: https://github.com/CLIUtils/CLI11/pull/913 -[#914]: https://github.com/CLIUtils/CLI11/pull/914 -[#916]: https://github.com/CLIUtils/CLI11/pull/916 -[#918]: https://github.com/CLIUtils/CLI11/pull/918 -[#923]: https://github.com/CLIUtils/CLI11/pull/923 -[#926]: https://github.com/CLIUtils/CLI11/pull/926 -[#928]: https://github.com/CLIUtils/CLI11/pull/928 -[#930]: https://github.com/CLIUtils/CLI11/pull/930 -[#935]: https://github.com/CLIUtils/CLI11/pull/935 -[#964]: https://github.com/CLIUtils/CLI11/pull/964 -[#967]: https://github.com/CLIUtils/CLI11/pull/967 -[#968]: https://github.com/CLIUtils/CLI11/pull/968 -[#970]: https://github.com/CLIUtils/CLI11/pull/970 -[#972]: https://github.com/CLIUtils/CLI11/pull/972 -[#980]: https://github.com/CLIUtils/CLI11/pull/980 -[#987]: https://github.com/CLIUtils/CLI11/pull/987 - -### Version 2.4.1: Missing header - -A transitive include that might be present in some standard libraries is now -included directly. This also fixes a test on architectures that need libatomic -linked and fix an inadvertent breaking change regarding unused defaults for -config files - -- Bugfix: Include cstdint [#996][] -- Bugfix: Fix change in operation of config_ptr with unused default in the count - method [#1003][] -- Tests: Include libatomic if required for fuzzing test [#1000][] - -[#996]: https://github.com/CLIUtils/CLI11/pull/996 -[#1000]: https://github.com/CLIUtils/CLI11/pull/1000 -[#1003]: https://github.com/CLIUtils/CLI11/pull/1003 - -## Version 2.3: Precompilation Support - -This version adds a pre-compiled mode to CLI11, which allows you to precompile -the library, saving time on incremental rebuilds, making CLI11 more competitive -on compile time with classic compiled CLI libraries. The header-only mode is -still default, and is not yet distributed via binaries. - -- Add `CLI11_PRECOMPILED` as an option [#762][] -- Bugfix: Include `` in `FormatterFwd` [#727][] -- Bugfix: Add missing `Macros.hpp` to `Error.hpp` [#755][] -- Bugfix: Fix subcommand callback trigger [#733][] -- Bugfix: Variable rename to avoid warning [#734][] -- Bugfix: `split_program_name` single file name error [#740][] -- Bugfix: Better support for min/max overrides on MSVC [#741][] -- Bugfix: Support MSVC 2022 [#748][] -- Bugfix: Support negated flag in config file [#775][] -- Bugfix: Better errors for some confusing config file situations [#781][] -- Backend: Restore coverage testing (lost with Travis CI) [#747][] - -[#727]: https://github.com/CLIUtils/CLI11/pull/727 -[#733]: https://github.com/CLIUtils/CLI11/pull/733 -[#734]: https://github.com/CLIUtils/CLI11/pull/734 -[#740]: https://github.com/CLIUtils/CLI11/pull/740 -[#741]: https://github.com/CLIUtils/CLI11/pull/741 -[#747]: https://github.com/CLIUtils/CLI11/pull/747 -[#748]: https://github.com/CLIUtils/CLI11/pull/748 -[#755]: https://github.com/CLIUtils/CLI11/pull/755 -[#762]: https://github.com/CLIUtils/CLI11/pull/762 -[#775]: https://github.com/CLIUtils/CLI11/pull/775 -[#781]: https://github.com/CLIUtils/CLI11/pull/781 - -### Version 2.3.1: Missing implementation - -A function implementation was missing after the pre-compile move, missed due to -the fact we lost 100% after losing coverage checking. We are working on filling -out 100% coverage again to ensure this doesn't happen again! - -- Bugfix: `App::get_option_group` implementation missing [#793][] -- Bugfix: Fix spacing when setting an empty footer [#796][] -- Bugfix: Address Klocwork static analysis checking issues [#785][] - -[#785]: https://github.com/CLIUtils/CLI11/pull/785 -[#793]: https://github.com/CLIUtils/CLI11/pull/793 -[#796]: https://github.com/CLIUtils/CLI11/pull/796 - -### Version 2.3.2: Minor maintenance - -This version provides a few fixes collected over the last three months before -adding features for 2.4. - -- Bugfix: Consistently use ADL for `lexical_cast`, making it easier to extend - for custom template types [#820][] -- Bugfix: Tweak the parsing of files for flags with `disable_flag_override` - [#800][] -- Bugfix: Handle out of bounds long long [#807][] -- Bugfix: Spacing of `make_description` min option output [#808][] -- Bugfix: Print last parsed subcommand's help message [#822][] -- Bugfix: Avoid floating point warning in GCC 12 [#803][] -- Bugfix: Fix a few gcc warnings [#813][] -- Backend: Max CMake tested 3.22 -> 3.24 [#823][] - -[#800]: https://github.com/CLIUtils/CLI11/pull/800 -[#803]: https://github.com/CLIUtils/CLI11/pull/803 -[#807]: https://github.com/CLIUtils/CLI11/pull/807 -[#808]: https://github.com/CLIUtils/CLI11/pull/808 -[#813]: https://github.com/CLIUtils/CLI11/pull/813 -[#820]: https://github.com/CLIUtils/CLI11/pull/820 -[#822]: https://github.com/CLIUtils/CLI11/pull/822 -[#823]: https://github.com/CLIUtils/CLI11/pull/823 - -## Version 2.2: Option and Configuration Flexibility - -New features include support for output of an empty vector, a summing option -policy that can be applied more broadly, and an option to validate optional -arguments to discriminate from positional arguments. A new validator to check -for files on a default path is included to allow one or more default paths for -configuration files or other file arguments. A number of bug fixes and code -cleanup for various build configurations. Clean up of some error outputs and -extension of existing capability to new types or situations. - -There is a possible minor breaking change in behavior of certain types which -wrapped an integer, such as `std::atomic` or `std::optional` when used -in a flag. The default behavior is now as a single argument value vs. summing -all the arguments. The default summing behavior is now restricted to pure -integral types, int64_t, int, uint32_t, etc. Use the new `sum` multi option -policy to revert to the older behavior. The summing behavior on wrapper types -was not originally intended. - -- Add `MultiOptionPolicy::Sum` and refactor the `add_flag` to fix a bug when - using `std::optional` as type. [#709][] -- Add support for an empty vector result in TOML and as a default string. - [#660][] -- Add `.validate_optional_arguments()` to support discriminating positional - arguments from vector option arguments. [#668][] -- Add `CLI::FileOnDefaultPath` to check for files on a specified default path. - [#698][] -- Change default value display in help messages from `=XXXX` to `[XXXXX]` to - make it clearer. [#666][] -- Modify the Range Validator to support additional types and clean up the error - output. [#690][] -- Bugfix: The trigger on parse modifier did not work on positional argument.s - [#713][] -- Bugfix: The single header file generation was missing custom namespace - generation. [#707][] -- Bugfix: Clean up File Error handling in the argument processing. [#678][] -- Bugfix: Fix a stack overflow error if nameless commands had fallthrough. - [#665][] -- Bugfix: A subcommand callback could be executed multiple times if it was a - member of an option group. [#666][] -- Bugfix: Fix an issue with vectors of multi argument types where partial - argument sets did not result in an error. [#661][] -- Bugfix: Fix an issue with type the template matching on C++20 and add some CI - builds for C++20. [#663][] -- Bugfix: Fix typo in C++20 detection on MSVC. [#706][] -- Bugfix: An issue where the detection of RTTI being disabled on certain MSVC - platforms did not disable the use of dynamic cast calls. [#666][] -- Bugfix: Resolve strict-overflow warning on some GCC compilers. [#666][] -- Backend: Add additional tests concerning the use of aliases for option groups - in config files. [#666][] -- Build: Add support for testing in meson and cleanup symbolic link generation. - [#701][], [#697][] -- Build: Support building in WebAssembly. [#679][] - -[#660]: https://github.com/CLIUtils/CLI11/pull/660 -[#661]: https://github.com/CLIUtils/CLI11/pull/661 -[#663]: https://github.com/CLIUtils/CLI11/pull/663 -[#665]: https://github.com/CLIUtils/CLI11/pull/665 -[#666]: https://github.com/CLIUtils/CLI11/pull/666 -[#668]: https://github.com/CLIUtils/CLI11/pull/668 -[#678]: https://github.com/CLIUtils/CLI11/pull/678 -[#679]: https://github.com/CLIUtils/CLI11/pull/679 -[#690]: https://github.com/CLIUtils/CLI11/pull/690 -[#697]: https://github.com/CLIUtils/CLI11/pull/697 -[#698]: https://github.com/CLIUtils/CLI11/pull/698 -[#701]: https://github.com/CLIUtils/CLI11/pull/701 -[#706]: https://github.com/CLIUtils/CLI11/pull/706 -[#707]: https://github.com/CLIUtils/CLI11/pull/707 -[#709]: https://github.com/CLIUtils/CLI11/pull/709 -[#713]: https://github.com/CLIUtils/CLI11/pull/713 - -## Version 2.1: Names and callbacks - -The name restrictions for options and subcommands are now much looser, allowing -a wider variety of characters than before, even spaces can be used (use quotes -to include a space in most shells). The default configuration parser was -improved, allowing your configuration to sit in a larger file. And option -callbacks have a few new settings, allowing them to be run even if the option is -not passed, or every time the option is parsed. - -- Option/subcommand name restrictions have been relaxed. Most characters are now - allowed. [#627][] -- The config parser can accept streams, specify a specific section, and inline - comment characters are supported [#630][] -- `force_callback` & `trigger_on_parse` added, allowing a callback to always run - on parse even if not present or every time the option is parsed [#631][] -- Bugfix(cmake): Only add `CONFIGURE_DEPENDS` if CLI11 is the main project - [#633][] -- Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent - path [#635][] -- Bugfix: The single header file generation was missing the include guard. - [#620][] - -[#620]: https://github.com/CLIUtils/CLI11/pull/620 -[#627]: https://github.com/CLIUtils/CLI11/pull/627 -[#630]: https://github.com/CLIUtils/CLI11/pull/630 -[#631]: https://github.com/CLIUtils/CLI11/pull/631 -[#633]: https://github.com/CLIUtils/CLI11/pull/633 -[#635]: https://github.com/CLIUtils/CLI11/pull/635 - -### Version 2.1.1: Quick Windows fix - -- A collision with `min`/`max` macros on Windows has been fixed. [#642][] -- Tests pass with Boost again [#646][] -- Running the pre-commit hooks in development no longer requires docker for - clang-format [#647][] - -[#642]: https://github.com/CLIUtils/CLI11/pull/642 -[#646]: https://github.com/CLIUtils/CLI11/pull/646 -[#647]: https://github.com/CLIUtils/CLI11/pull/647 - -## Version 2.1.2: Better subproject builds - -- Use `main` for the main branch of the repository [#657][] -- Bugfix(cmake): Enforce at least C++11 when using CMake target [#656][] -- Build: Don't run doxygen and CTest includes if a submodule [#656][] -- Build: Avoid a warning on CMake 3.22 [#656][] -- Build: Support compiling the tests with an external copy of Catch2 [#653][] - -[#653]: https://github.com/CLIUtils/CLI11/pull/653 -[#656]: https://github.com/CLIUtils/CLI11/pull/656 -[#657]: https://github.com/CLIUtils/CLI11/pull/657 - -## Version 2.0: Simplification - -This version focuses on cleaning up deprecated functionality, and some minor -default changes. The config processing is TOML compliant now. Atomics and -complex numbers are directly supported, along with other container improvements. -A new version flag option has finally been added. Subcommands are significantly -improved with new features and bugfixes for corner cases. This release contains -a lot of backend cleanup, including a complete overhaul of the testing system -and single file generation system. - -- Built-in config format is TOML compliant now [#435][] - - Support multiline TOML [#528][] - - Support for configurable quotes [#599][] - - Support short/positional options in config mode [#443][] -- More powerful containers, support for `%%` separator [#423][] -- Support atomic types [#520][] and complex types natively [#423][] -- Add a type validator `CLI::TypeValidator` [#526][] -- Add a version flag easily [#452][], with help message [#601][] -- Support `->silent()` on subcommands. [#529][] -- Add alias section to help for subcommands [#545][] -- Allow quotes to specify a program name [#605][] -- Backend: redesigned MakeSingleFiles to have a higher level of manual control, - to support future features. [#546][] -- Backend: moved testing from GTest to Catch2 [#574][] -- Bugfix: avoid duplicated and missed calls to the final callback [#584][] -- Bugfix: support embedded newlines in more places [#592][] -- Bugfix: avoid listing helpall as a required flag [#530][] -- Bugfix: avoid a clash with WINDOWS define [#563][] -- Bugfix: the help flag didn't get processed when a config file was required - [#606][] -- Bugfix: fix description of non-configurable subcommands in config [#604][] -- Build: support pkg-config [#523][] - -> ### Converting from CLI11 1.9 -> -> - Removed deprecated set commands, use validators instead. [#565][] -> - The final "defaulted" bool has been removed, use `->capture_default_str()` -> instead. Use `app.option_defaults()->always_capture_default()` to set this -> for all future options. [#597][] -> - Use `add_option` on a complex number instead of `add_complex`, which has -> been removed. - -[#423]: https://github.com/CLIUtils/CLI11/pull/423 -[#435]: https://github.com/CLIUtils/CLI11/pull/435 -[#443]: https://github.com/CLIUtils/CLI11/pull/443 -[#452]: https://github.com/CLIUtils/CLI11/pull/452 -[#520]: https://github.com/CLIUtils/CLI11/pull/520 -[#523]: https://github.com/CLIUtils/CLI11/pull/523 -[#526]: https://github.com/CLIUtils/CLI11/pull/526 -[#528]: https://github.com/CLIUtils/CLI11/pull/528 -[#529]: https://github.com/CLIUtils/CLI11/pull/529 -[#530]: https://github.com/CLIUtils/CLI11/pull/530 -[#545]: https://github.com/CLIUtils/CLI11/pull/545 -[#546]: https://github.com/CLIUtils/CLI11/pull/546 -[#563]: https://github.com/CLIUtils/CLI11/pull/563 -[#565]: https://github.com/CLIUtils/CLI11/pull/565 -[#574]: https://github.com/CLIUtils/CLI11/pull/574 -[#584]: https://github.com/CLIUtils/CLI11/pull/584 -[#592]: https://github.com/CLIUtils/CLI11/pull/592 -[#597]: https://github.com/CLIUtils/CLI11/pull/597 -[#599]: https://github.com/CLIUtils/CLI11/pull/599 -[#601]: https://github.com/CLIUtils/CLI11/pull/601 -[#604]: https://github.com/CLIUtils/CLI11/pull/604 -[#605]: https://github.com/CLIUtils/CLI11/pull/605 -[#606]: https://github.com/CLIUtils/CLI11/pull/606 - -## Version 1.9: Config files and cleanup - -Config file handling was revamped to fix common issues, and now supports reading -[TOML](https://github.com/toml-lang/toml). - -Adding options is significantly more powerful with support for things like -`std::tuple` and `std::array`, including with transforms. Several new -configuration options were added to facilitate a wider variety of apps. GCC 4.7 -is no longer supported. - -- Config files refactored, supports TOML (may become default output in 2.0) - [#362][] -- Added two template parameter form of `add_option`, allowing `std::optional` to - be supported without a special import [#285][] -- `string_view` now supported in reasonable places [#300][], [#285][] -- `immediate_callback`, `final_callback`, and `parse_complete_callback` added to - support controlling the App callback order [#292][], [#313][] -- Multiple positional arguments maintain order if `positionals_at_end` is set. - [#306][] -- Pair/tuple/array now supported, and validators indexed to specific components - in the objects [#307][], [#310][] -- Footer callbacks supported [#309][] -- Subcommands now support needs (including nameless subcommands) [#317][] -- More flexible type size, more useful `add_complex` [#325][], [#370][] -- Added new validators `CLI::NonNegativeNumber` and `CLI::PositiveNumber` - [#342][] -- Transform now supports arrays [#349][] -- Option groups can be hidden [#356][] -- Add `CLI::deprecate_option` and `CLI::retire_option` functions [#358][] -- More flexible and safer Option `default_val` [#387][] -- Backend: Cleaner type traits [#286][] -- Backend: File checking updates [#341][] -- Backend: Using pre-commit to format, checked in GitHub Actions [#336][] -- Backend: Clang-tidy checked again, CMake option now `CL11_CLANG_TIDY` [#390][] -- Backend: Warning cleanup, more checks from klocwork [#350][], Effective C++ - [#354][], clang-tidy [#360][], CUDA NVCC [#365][], cross compile [#373][], - sign conversion [#382][], and cpplint [#400][] -- Docs: CLI11 Tutorial now hosted in the same repository [#304][], [#318][], - [#374][] -- Bugfix: Fixed undefined behavior in `checked_multiply` [#290][] -- Bugfix: `->check()` was adding the name to the wrong validator [#320][] -- Bugfix: Resetting config option works properly [#301][] -- Bugfix: Hidden flags were showing up in error printout [#333][] -- Bugfix: Enum conversion no longer broken if stream operator added [#348][] -- Build: The meson build system supported [#299][] -- Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is - now required. [#160][] -- Build: Restructured significant portions of CMake build system [#394][] - -> ### Converting from CLI11 1.8 -> -> - Some deprecated methods dropped -> - `add_set*` should be replaced with `->check`/`->transform` and -> `CLI::IsMember` since 1.8 -> - `get_defaultval` was replaced by `get_default_str` in 1.8 -> - The true/false 4th argument to `add_option` is expected to be removed in -> 2.0, use `->capture_default_str()` since 1.8 - -[#160]: https://github.com/CLIUtils/CLI11/pull/160 -[#285]: https://github.com/CLIUtils/CLI11/pull/285 -[#286]: https://github.com/CLIUtils/CLI11/pull/286 -[#290]: https://github.com/CLIUtils/CLI11/pull/290 -[#292]: https://github.com/CLIUtils/CLI11/pull/292 -[#299]: https://github.com/CLIUtils/CLI11/pull/299 -[#300]: https://github.com/CLIUtils/CLI11/pull/300 -[#301]: https://github.com/CLIUtils/CLI11/pull/301 -[#304]: https://github.com/CLIUtils/CLI11/pull/304 -[#306]: https://github.com/CLIUtils/CLI11/pull/306 -[#307]: https://github.com/CLIUtils/CLI11/pull/307 -[#309]: https://github.com/CLIUtils/CLI11/pull/309 -[#310]: https://github.com/CLIUtils/CLI11/pull/310 -[#313]: https://github.com/CLIUtils/CLI11/pull/313 -[#317]: https://github.com/CLIUtils/CLI11/pull/317 -[#318]: https://github.com/CLIUtils/CLI11/pull/318 -[#320]: https://github.com/CLIUtils/CLI11/pull/320 -[#325]: https://github.com/CLIUtils/CLI11/pull/325 -[#333]: https://github.com/CLIUtils/CLI11/pull/333 -[#336]: https://github.com/CLIUtils/CLI11/pull/336 -[#341]: https://github.com/CLIUtils/CLI11/pull/341 -[#342]: https://github.com/CLIUtils/CLI11/pull/342 -[#348]: https://github.com/CLIUtils/CLI11/pull/348 -[#349]: https://github.com/CLIUtils/CLI11/pull/349 -[#350]: https://github.com/CLIUtils/CLI11/pull/350 -[#354]: https://github.com/CLIUtils/CLI11/pull/354 -[#356]: https://github.com/CLIUtils/CLI11/pull/356 -[#358]: https://github.com/CLIUtils/CLI11/pull/358 -[#360]: https://github.com/CLIUtils/CLI11/pull/360 -[#362]: https://github.com/CLIUtils/CLI11/pull/362 -[#365]: https://github.com/CLIUtils/CLI11/pull/365 -[#370]: https://github.com/CLIUtils/CLI11/pull/370 -[#373]: https://github.com/CLIUtils/CLI11/pull/373 -[#374]: https://github.com/CLIUtils/CLI11/pull/374 -[#382]: https://github.com/CLIUtils/CLI11/pull/382 -[#387]: https://github.com/CLIUtils/CLI11/pull/387 -[#390]: https://github.com/CLIUtils/CLI11/pull/390 -[#394]: https://github.com/CLIUtils/CLI11/pull/394 -[#400]: https://github.com/CLIUtils/CLI11/pull/400 - -### Version 1.9.1: Backporting fixes - -This is a patch version that backports fixes from the development of 2.0. - -- Support relative inclusion [#475][] -- Fix cases where spaces in paths could break CMake support [#471][] -- Fix an issue with string conversion [#421][] -- Cross-compiling improvement for Conan.io [#430][] -- Fix option group default propagation [#450][] -- Fix for C++20 [#459][] -- Support compiling with RTTI off [#461][] - -[#421]: https://github.com/CLIUtils/CLI11/pull/421 -[#430]: https://github.com/CLIUtils/CLI11/pull/430 -[#450]: https://github.com/CLIUtils/CLI11/pull/450 -[#459]: https://github.com/CLIUtils/CLI11/pull/459 -[#461]: https://github.com/CLIUtils/CLI11/pull/461 -[#471]: https://github.com/CLIUtils/CLI11/pull/471 -[#475]: https://github.com/CLIUtils/CLI11/pull/475 - -## Version 1.8: Transformers, default strings, and flags - -Set handling has been completely replaced by a new backend that works as a -Validator or Transformer. This provides a single interface instead of the 16 -different functions in App. It also allows ordered collections to be used, -custom functions for filtering, and better help and error messages. You can also -use a collection of pairs (like `std::map`) to transform the match into an -output. Also new are inverted flags, which can cancel or reduce the count of -flags, and can also support general flag types. A new `add_option_fn` lets you -more easily program CLI11 options with the types you choose. Vector options now -support a custom separator. Apps can now be composed with unnamed subcommand -support. The final bool "defaults" flag when creating options has been replaced -by `->capture_default_str()` (ending an old limitation in construction made this -possible); the old method is still available but may be removed in future -versions. - -- Replaced default help capture: `.add_option("name", value, "", True)` becomes - `.add_option("name", value)->capture_default_str()` [#242][] -- Added `.always_capture_default()` [#242][] -- New `CLI::IsMember` validator replaces set validation [#222][] -- `IsMember` also supports container of pairs, transform allows modification of - result [#228][] -- Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` - [#253][] -- Much more powerful flags with different values [#211][], general types - [#235][] -- `add_option` now supports bool due to unified bool handling [#211][] -- Support for composable unnamed subcommands [#216][] -- Reparsing is better supported with `.remaining_for_passthrough()` [#265][] -- Custom vector separator using `->delimiter(char)` [#209][], [#221][], [#240][] -- Validators added for IP4 addresses and positive numbers [#210][] and numbers - [#262][] -- Minimum required Boost for optional Optionals has been corrected to 1.61 - [#226][] -- Positionals can stop options from being parsed with `app.positionals_at_end()` - [#223][] -- Added `validate_positionals` [#262][] -- Positional parsing is much more powerful [#251][], duplicates supported - [#247][] -- Validators can be negated with `!` [#230][], and now handle tname functions - [#228][] -- Better enum support and streaming helper [#233][] and [#228][] -- Cleanup for shadow warnings [#232][] -- Better alignment on multiline descriptions [#269][] -- Better support for aarch64 [#266][] -- Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, - `CLI11_TESTING` must be used [#277][] -- Drop auto-detection of experimental optional and boost::optional; must be - enabled explicitly (too fragile) [#277][] [#279][] - -> ### Converting from CLI11 1.7 -> -> - `.add_option(..., true)` should be replaced by -> `.add_option(...)->capture_default_str()` or -> `app.option_defaults()->always_capture_default()` can be used -> - `app.add_set("--name", value, {"choice1", "choice2"})` should become -> `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))` -> - The `_ignore_case` version of this can be replaced by adding -> `CLI::ignore_case` to the argument list in `IsMember` -> - The `_ignore_underscore` version of this can be replaced by adding -> `CLI::ignore_underscore` to the argument list in `IsMember` -> - The `_ignore_case_underscore` version of this can be replaced by adding both -> functions listed above to the argument list in `IsMember` -> - If you want an exact match to the original choice after one of the modifier -> functions matches, use `->transform` instead of `->check` -> - The `_mutable` versions of this can be replaced by passing a pointer or -> shared pointer into `IsMember` -> - An error with sets now produces a `ValidationError` instead of a -> `ConversionError` - -[#209]: https://github.com/CLIUtils/CLI11/pull/209 -[#210]: https://github.com/CLIUtils/CLI11/pull/210 -[#211]: https://github.com/CLIUtils/CLI11/pull/211 -[#216]: https://github.com/CLIUtils/CLI11/pull/216 -[#221]: https://github.com/CLIUtils/CLI11/pull/221 -[#222]: https://github.com/CLIUtils/CLI11/pull/222 -[#223]: https://github.com/CLIUtils/CLI11/pull/223 -[#226]: https://github.com/CLIUtils/CLI11/pull/226 -[#228]: https://github.com/CLIUtils/CLI11/pull/228 -[#230]: https://github.com/CLIUtils/CLI11/pull/230 -[#232]: https://github.com/CLIUtils/CLI11/pull/232 -[#233]: https://github.com/CLIUtils/CLI11/pull/233 -[#235]: https://github.com/CLIUtils/CLI11/pull/235 -[#240]: https://github.com/CLIUtils/CLI11/pull/240 -[#242]: https://github.com/CLIUtils/CLI11/pull/242 -[#247]: https://github.com/CLIUtils/CLI11/pull/247 -[#251]: https://github.com/CLIUtils/CLI11/pull/251 -[#253]: https://github.com/CLIUtils/CLI11/pull/253 -[#262]: https://github.com/CLIUtils/CLI11/pull/262 -[#265]: https://github.com/CLIUtils/CLI11/pull/265 -[#266]: https://github.com/CLIUtils/CLI11/pull/266 -[#269]: https://github.com/CLIUtils/CLI11/pull/269 -[#277]: https://github.com/CLIUtils/CLI11/pull/277 -[#279]: https://github.com/CLIUtils/CLI11/pull/279 - -## Version 1.7: Parse breakup - -The parsing procedure now maps much more sensibly to complex, nested subcommand -structures. Each phase of the parsing happens on all subcommands before moving -on with the next phase of the parse. This allows several features, like required -environment variables, to work properly even through subcommand boundaries. -Passing the same subcommand multiple times is better supported. Several new -features were added as well, including Windows style option support, parsing -strings directly, and ignoring underscores in names. Adding a set that you plan -to change later must now be done with `add_mutable_set`. - -- Support Windows style options with `->allow_windows_style_options`. [#187][] - On by default on Windows. [#190][] -- Added `parse(string)` to split up and parse a command-line style string - directly. [#186][] -- Added `ignore_underscore` and related functions, to ignore underscores when - matching names. [#185][] -- The default INI Config will now add quotes to strings with spaces [#195][] -- The default message now will mention the help-all flag also if present - [#197][] -- Added `->description` to set Option descriptions [#199][] -- Mutating sets (introduced in Version 1.6) now have a clear add method, - `add_mutable_set*`, since the set reference should not expire [#200][] -- Subcommands now track how many times they were parsed in a parsing process. - `count()` with no arguments will return the number of times a subcommand was - encountered. [#178][] -- Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and - `requirements`; all subcommands complete a phase before moving on. [#178][] -- Calling parse multiple times is now officially supported without `clear` - (automatic). [#178][] -- Dropped the mostly undocumented `short_circuit` property, as help flag parsing - is a bit more complex, and the default callback behavior of options now works - properly. [#179][] -- Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183][] -- Cleanup warnings [#191][] -- Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and - `set_type_name`. Use without the `set_` instead. [#192][] - -> ### Converting from CLI11 1.6 -> -> - `->short_circuit()` is no longer needed, just remove it if you were using -> it - raising an exception will happen in the proper place now without it. -> - `->add_set*` becomes `->add_mutable_set*` if you were using the editable set -> feature -> - `footer`, `name`, `callback`, and `type_name` must be used instead of the -> `set_*` versions (deprecated previously). - -[#178]: https://github.com/CLIUtils/CLI11/pull/178 -[#183]: https://github.com/CLIUtils/CLI11/pull/183 -[#185]: https://github.com/CLIUtils/CLI11/pull/185 -[#186]: https://github.com/CLIUtils/CLI11/pull/186 -[#187]: https://github.com/CLIUtils/CLI11/pull/187 -[#190]: https://github.com/CLIUtils/CLI11/pull/190 -[#191]: https://github.com/CLIUtils/CLI11/pull/191 -[#192]: https://github.com/CLIUtils/CLI11/pull/192 -[#197]: https://github.com/CLIUtils/CLI11/pull/197 -[#195]: https://github.com/CLIUtils/CLI11/issues/195 -[#199]: https://github.com/CLIUtils/CLI11/pull/199 -[#200]: https://github.com/CLIUtils/CLI11/pull/200 - -### Version 1.7.1: Quick patch - -This version provides a quick patch for a (correct) warning from GCC 8 for the -windows options code. - -- Fix for Windows style option parsing [#201][] -- Improve `add_subcommand` when throwing an exception [#204][] -- Better metadata for Conan package [#202][] - -[#201]: https://github.com/CLIUtils/CLI11/pull/201 -[#202]: https://github.com/CLIUtils/CLI11/pull/202 -[#204]: https://github.com/CLIUtils/CLI11/pull/204 - -## Version 1.6: Formatting help - -Added a new formatting system [#109][]. You can now set the formatter on Apps. -This has also simplified the internals of Apps and Options a bit by separating -most formatting code. - -- Added `CLI::Formatter` and `formatter` slot for apps, inherited. -- `FormatterBase` is the minimum required. -- `FormatterLambda` provides for the easy addition of an arbitrary function. -- Added `help_all` support (not added by default). - -Changes to the help system (most normal users will not notice this): - -- Renamed `single_name` to `get_name(false, false)` (the default). -- The old `get_name()` is now `get_name(false, true)`. -- The old `get_pname()` is now `get_name(true, false)`. -- Removed `help_*` functions. -- Protected function `_has_help_positional` removed. -- `format_help` can now be chained. -- Added getters for the missing parts of options (help no longer uses any - private parts). -- Help flags now use new `short_circuit` property to simplify parsing. [#121][] - -New for Config file reading and writing [#121][]: - -- Overridable, bidirectional Config. -- ConfigINI provided and used by default. -- Renamed ini to config in many places. -- Has `config_formatter()` and `get_config_formatter()`. -- Dropped prefix argument from `config_to_str`. -- Added `ConfigItem`. -- Added an example of a custom config format using [nlohmann/json][]. [#138][] - -Validators are now much more powerful [#118][], all built in validators upgraded -to the new form: - -- A subclass of `CLI::Validator` is now also accepted. -- They now can set the type name to things like `PATH` and `INT in [1-4]`. -- Validators can be combined with `&` and `|`. -- Old form simple validators are still accepted. - -Other changes: - -- Fixing `parse(args)`'s `args` setting and ordering after parse. [#141][] -- Replaced `set_custom_option` with `type_name` and `type_size` instead of - `set_custom_option`. Methods return `this`. [#136][] -- Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. - [#136][] -- Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. - [#136][] -- Fixed support `N<-1` for `type_size`. [#140][] -- Added `->each()` to make adding custom callbacks easier. [#126][] -- Allow empty options `add_option("-n",{})` to be edited later with `each` - [#142][] -- Added filter argument to `get_subcommands`, `get_options`; use empty filter - `{}` to avoid filtering. -- Added `get_groups()` to get groups. -- Better support for manual options with `get_option`, `set_results`, and - `empty`. [#119][] -- `lname` and `sname` have getters, added `const get_parent`. [#120][] -- Using `add_set` will now capture L-values for sets, allowing further - modification. [#113][] -- Dropped duplicate way to run `get_type_name` (`get_typeval`). -- Removed `requires` in favor of `needs` (deprecated in last version). [#112][] -- Const added to argv. [#126][] - -Backend and testing changes: - -- Internally, `type_name` is now a lambda function; for sets, this reads the set - live. [#116][] -- Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141][] -- Better CMake policy handling. [#110][] -- Includes are properly sorted. [#120][] -- Testing (only) now uses submodules. [#111][] - -[#109]: https://github.com/CLIUtils/CLI11/pull/109 -[#110]: https://github.com/CLIUtils/CLI11/pull/110 -[#111]: https://github.com/CLIUtils/CLI11/pull/111 -[#112]: https://github.com/CLIUtils/CLI11/pull/112 -[#113]: https://github.com/CLIUtils/CLI11/issues/113 -[#116]: https://github.com/CLIUtils/CLI11/pull/116 -[#118]: https://github.com/CLIUtils/CLI11/pull/118 -[#119]: https://github.com/CLIUtils/CLI11/pull/119 -[#120]: https://github.com/CLIUtils/CLI11/pull/120 -[#121]: https://github.com/CLIUtils/CLI11/pull/121 -[#126]: https://github.com/CLIUtils/CLI11/pull/126 -[#136]: https://github.com/CLIUtils/CLI11/pull/136 -[#138]: https://github.com/CLIUtils/CLI11/pull/138 -[#140]: https://github.com/CLIUtils/CLI11/pull/140 -[#141]: https://github.com/CLIUtils/CLI11/pull/141 -[#142]: https://github.com/CLIUtils/CLI11/pull/142 -[nlohmann/json]: https://github.com/nlohmann/json - -### Version 1.6.1: Platform fixes - -This version provides a few fixes for special cases, such as mixing with -`Windows.h` and better defaults for systems like Hunter. The one new feature is -the ability to produce "branded" single file output for providing custom -namespaces or custom macro names. - -- Added fix and test for including Windows.h [#145][] -- No longer build single file by default if main project, supports systems stuck - on Python 2.6 [#149][], [#151][] -- Branding support for single file output [#150][] - -[#145]: https://github.com/CLIUtils/CLI11/pull/145 -[#149]: https://github.com/CLIUtils/CLI11/pull/149 -[#150]: https://github.com/CLIUtils/CLI11/pull/150 -[#151]: https://github.com/CLIUtils/CLI11/pull/151 - -### Version 1.6.2: Help-all - -This version fixes some formatting bugs with help-all. It also adds fixes for -several warnings, including an experimental optional error on Clang 7. Several -smaller fixes. - -- Fixed help-all formatting [#163][] - - Printing help-all on nested command now fixed (App) - - Missing space after help-all restored (Default formatter) - - More detail printed on help all (Default formatter) - - Help-all subcommands get indented with inner blank lines removed (Default - formatter) - - `detail::find_and_replace` added to utilities -- Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156][] -- Fixed warning about local variable hiding class member with MSVC [#157][] -- Fixed compile error with default settings on Clang 7 and libc++ [#158][] -- Fixed special case of `--help` on subcommands (general fix planned for 1.7) - [#168][] -- Removing an option with links [#179][] - -[#156]: https://github.com/CLIUtils/CLI11/issues/156 -[#157]: https://github.com/CLIUtils/CLI11/issues/157 -[#158]: https://github.com/CLIUtils/CLI11/issues/158 -[#163]: https://github.com/CLIUtils/CLI11/pull/163 -[#168]: https://github.com/CLIUtils/CLI11/issues/168 -[#179]: https://github.com/CLIUtils/CLI11/pull/179 - -## Version 1.5: Optionals - -This version introduced support for optionals, along with clarification and -examples of custom conversion overloads. Enums now have been dropped from the -automatic conversion system, allowing explicit protection for out-of-range ints -(or a completely custom conversion). This version has some internal cleanup and -improved support for the newest compilers. Several bugs were fixed, as well. - -Note: This is the final release with `requires`, please switch to `needs`. - -- Fix unlimited short options eating two values before checking for positionals - when no space present [#90][] -- Symmetric exclude text when excluding options, exclude can be called multiple - times [#64][] -- Support for `std::optional`, `std::experimental::optional`, and - `boost::optional` added if `__has_include` is supported [#95][] -- All macros/CMake variables now start with `CLI11_` instead of just `CLI_` - [#95][] -- The internal stream was not being cleared before use in some cases. Fixed. - [#95][] -- Using an enum now requires explicit conversion overload [#97][] -- The separator `--` now is removed when it ends unlimited arguments [#100][] - -Other, non-user facing changes: - -- Added `Macros.hpp` with better C++ mode discovery [#95][] -- Deprecated macros added for all platforms -- C++17 is now tested on supported platforms [#95][] -- Informational printout now added to CTest [#95][] -- Better single file generation [#95][] -- Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next - version of GTest) -- Types now have a specific size, separate from the expected number - cleaner - and more powerful internally [#92][] -- Examples now run as part of testing [#99][] - -[#64]: https://github.com/CLIUtils/CLI11/issues/64 -[#90]: https://github.com/CLIUtils/CLI11/issues/90 -[#92]: https://github.com/CLIUtils/CLI11/issues/92 -[#95]: https://github.com/CLIUtils/CLI11/pull/95 -[#97]: https://github.com/CLIUtils/CLI11/pull/97 -[#99]: https://github.com/CLIUtils/CLI11/pull/99 -[#100]: https://github.com/CLIUtils/CLI11/pull/100 - -### Version 1.5.1: Access - -This patch release adds better access to the App programmatically, to assist -with writing custom converters to other formats. It also improves the help -output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way -unlimited options and positionals interact. - -- Make mixing unlimited positionals and options more intuitive [#102][] -- Add missing getters `get_options` and `get_description` to App [#105][] -- The app name now can be set, and will override the auto name if present - [#105][] -- Add `(REQUIRED)` for required options [#104][] -- Print simple name for Needs/Excludes [#104][] -- Use Needs instead of Requires in help print [#104][] -- Groups now are listed in the original definition order [#106][] - -[#102]: https://github.com/CLIUtils/CLI11/issues/102 -[#104]: https://github.com/CLIUtils/CLI11/pull/104 -[#105]: https://github.com/CLIUtils/CLI11/pull/105 -[#106]: https://github.com/CLIUtils/CLI11/pull/106 - -### Version 1.5.2: LICENSE in single header mode - -This is a quick patch release that makes LICENSE part of the single header file, -making it easier to include. Minor cleanup from codacy. No significant code -changes from 1.5.1. - -### Version 1.5.3: Compiler compatibility - -This version fixes older AppleClang compilers by removing the optimization for -casting. The minimum version of Boost Optional supported has been clarified to -be 1.58. CUDA 7.0 NVCC is now supported. - -### Version 1.5.4: Optionals - -This version fixes the optional search in the single file version; some macros -were not yet defined when it did the search. You can define the -`CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search. - -## Version 1.4: More feedback - -This version adds lots of smaller fixes and additions after the refactor in -version 1.3. More ways to download and use CLI11 in CMake have been added. INI -files have improved support. - -- Lexical cast is now more strict than before [#68][] and fails on overflow - [#84][] -- Added `get_parent()` to access the parent from a subcommand -- Added `ExistingPath` validator [#73][] -- `app.allow_ini_extras()` added to allow extras in INI files [#70][] -- Multiline INI comments now supported -- Descriptions can now be written with `config_to_str` [#66][] -- Double printing of error message fixed [#77][] -- Renamed `requires` to `needs` to avoid C++20 keyword [#75][], [#82][] -- MakeSingleHeader now works if outside of git [#78][] -- Adding install support for CMake [#79][], improved support for `find_package` - [#83][], [#84][] -- Added support for Conan.io [#83][] - -[#70]: https://github.com/CLIUtils/CLI11/issues/70 -[#75]: https://github.com/CLIUtils/CLI11/issues/75 -[#84]: https://github.com/CLIUtils/CLI11/pull/84 -[#83]: https://github.com/CLIUtils/CLI11/pull/83 -[#82]: https://github.com/CLIUtils/CLI11/pull/82 -[#79]: https://github.com/CLIUtils/CLI11/pull/79 -[#78]: https://github.com/CLIUtils/CLI11/pull/78 -[#77]: https://github.com/CLIUtils/CLI11/pull/77 -[#73]: https://github.com/CLIUtils/CLI11/pull/73 -[#68]: https://github.com/CLIUtils/CLI11/pull/68 -[#66]: https://github.com/CLIUtils/CLI11/pull/66 - -## Version 1.3: Refactor - -This version focused on refactoring several key systems to ensure correct -behavior in the interaction of different settings. Most caveats about features -only working on the main App have been addressed, and extra arguments have been -reworked. Inheritance of defaults makes configuring CLI11 much easier without -having to subclass. Policies add new ways to handle multiple arguments to match -your favorite CLI programs. Error messages and help messages are better and more -flexible. Several bugs and odd behaviors in the parser have been fixed. - -- Added a version macro, `CLI11_VERSION`, along with `*_MAJOR`, `*_MINOR`, and - `*_PATCH`, for programmatic access to the version. -- Reworked the way defaults are set and inherited; explicit control given to - user with `->option_defaults()` - [#48](https://github.com/CLIUtils/CLI11/pull/48) -- Hidden options now are based on an empty group name, instead of special - "hidden" keyword [#48](https://github.com/CLIUtils/CLI11/pull/48) -- `parse` no longer returns (so `CLI11_PARSE` is always usable) - [#37](https://github.com/CLIUtils/CLI11/pull/37) -- Added `remaining()` and `remaining_size()` - [#37](https://github.com/CLIUtils/CLI11/pull/37) -- `allow_extras` and `prefix_command` are now valid on subcommands - [#37](https://github.com/CLIUtils/CLI11/pull/37) -- Added `take_last` to only take last value passed - [#40](https://github.com/CLIUtils/CLI11/pull/40) -- Added `multi_option_policy` and shortcuts to provide more control than just a - take last policy [#59](https://github.com/CLIUtils/CLI11/pull/59) -- More detailed error messages in a few cases - [#41](https://github.com/CLIUtils/CLI11/pull/41) -- Footers can be added to help [#42](https://github.com/CLIUtils/CLI11/pull/42) -- Help flags are easier to customize - [#43](https://github.com/CLIUtils/CLI11/pull/43) -- Subcommand now support groups [#46](https://github.com/CLIUtils/CLI11/pull/46) -- `CLI::RuntimeError` added, for easy exit with error codes - [#45](https://github.com/CLIUtils/CLI11/pull/45) -- The clang-format script is now no longer "hidden" - [#48](https://github.com/CLIUtils/CLI11/pull/48) -- The order is now preserved for subcommands (list and callbacks) - [#49](https://github.com/CLIUtils/CLI11/pull/49) -- Tests now run individually, utilizing CMake 3.10 additions if possible - [#50](https://github.com/CLIUtils/CLI11/pull/50) -- Failure messages are now customizable, with a shorter default - [#52](https://github.com/CLIUtils/CLI11/pull/52) -- Some improvements to error codes - [#53](https://github.com/CLIUtils/CLI11/pull/53) -- `require_subcommand` now offers a two-argument form and negative values on the - one-argument form are more useful - [#51](https://github.com/CLIUtils/CLI11/pull/51) -- Subcommands no longer match after the max required number is obtained - [#51](https://github.com/CLIUtils/CLI11/pull/51) -- Unlimited options no longer prioritize over remaining/unlimited positionals - [#51](https://github.com/CLIUtils/CLI11/pull/51) -- Added `->transform` which modifies the string parsed - [#54](https://github.com/CLIUtils/CLI11/pull/54) -- Changed of API in validators to `void(std::string &)` (const for users), - throwing providing nicer errors - [#54](https://github.com/CLIUtils/CLI11/pull/54) -- Added `CLI::ArgumentMismatch` [#56](https://github.com/CLIUtils/CLI11/pull/56) - and fixed missing failure if one arg expected - [#55](https://github.com/CLIUtils/CLI11/issues/55) -- Support for minimum unlimited expected arguments - [#56](https://github.com/CLIUtils/CLI11/pull/56) -- Single internal arg parse function - [#56](https://github.com/CLIUtils/CLI11/pull/56) -- Allow options to be disabled from INI file, rename `add_config` to - `set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60) - -> ### Converting from CLI11 1.2 -> -> - `app.parse` no longer returns a vector. Instead, use `app.remaining(true)`. -> - `"hidden"` is no longer a special group name, instead use `""` -> - Validators API has changed to return an error string; use `.empty()` to get -> the old bool back -> - Use `.set_help_flag` instead of accessing the help pointer directly -> (discouraged, but not removed yet) -> - `add_config` has been renamed to `set_config` -> - Errors thrown in some cases are slightly more specific - -## Version 1.2: Stability - -This release focuses on making CLI11 behave properly in corner cases, and with -config files on the command line. This includes fixes for a variety of reported -issues. A few features were added to make life easier, as well; such as a new -flag callback and a macro for the parse command. - -- Added functional form of flag - [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14 -- Fixed Config file search if passed on command line - [#30](https://github.com/CLIUtils/CLI11/issues/30) -- Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not - support returning arg) -- The name string can now contain spaces around commas - [#29](https://github.com/CLIUtils/CLI11/pull/29) -- `set_default_str` now only sets string, and `set_default_val` will evaluate - the default string given [#26](https://github.com/CLIUtils/CLI11/issues/26) -- Required positionals now take priority over subcommands - [#23](https://github.com/CLIUtils/CLI11/issues/23) -- Extra requirements enforced by Travis - -## Version 1.1: Feedback - -This release incorporates feedback from the release announcement. The examples -are slowly being expanded, some corner cases improved, and some new -functionality for tricky parsing situations. - -- Added simple support for enumerations, allow non-printable objects - [#12](https://github.com/CLIUtils/CLI11/issues/12) -- Added `app.parse_order()` with original parse order - ([#13](https://github.com/CLIUtils/CLI11/issues/13), - [#16](https://github.com/CLIUtils/CLI11/pull/16)) -- Added `prefix_command()`, which is like `allow_extras` but instantly stops and - returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), - [#17](https://github.com/CLIUtils/CLI11/pull/17)) -- Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10), - [#20](https://github.com/CLIUtils/CLI11/pull/20)) -- Some improvements to CMake, detect Python and no dependencies on Python 2 - (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), - [#21](https://github.com/CLIUtils/CLI11/pull/21)) - -## Version 1.0: Official release - -This is the first stable release for CLI11. Future releases will try to remain -backward compatible and will follow semantic versioning if possible. There were -a few small changes since version 0.9: - -- Cleanup using `clang-tidy` and `clang-format` -- Small improvements to Timers, easier to subclass Error -- Move to 3-Clause BSD license - -## Version 0.9: Polish - -This release focused on cleaning up the most exotic compiler warnings, fixing a -few oddities of the config parser, and added a more natural method to check -subcommands. - -- Better CMake named target (CLI11) -- More warnings added, fixed -- Ini output now includes `=false` when `default_also` is true -- Ini no longer lists the help pointer -- Added test for inclusion in multiple files and linking, fixed issues (rarely - needed for CLI, but nice for tools) -- Support for complex numbers -- Subcommands now test true/false directly or with `->parsed()`, cleaner parse - -## Version 0.8: CLIUtils - -This release moved the repository to the CLIUtils main organization. - -- Moved to CLIUtils on GitHub -- Fixed docs build and a few links - -## Version 0.7: Code coverage 100% - -Lots of small bugs fixed when adding code coverage, better in edge cases. Much -more powerful ini support. - -- Allow comments in ini files (lines starting with `;`) -- Ini files support flags, vectors, subcommands -- Added CodeCov code coverage reports -- Lots of small bugfixes related to adding tests to increase coverage to 100% -- Error handling now uses scoped enum in errors -- Reparsing rules changed a little to accommodate Ini files. Callbacks are now - called when parsing INI, and reset any time results are added. -- Adding extra utilities in full version only, `Timer` (not needed for parsing, - but useful for general CLI applications). -- Better support for custom `add_options` like functions. - -## Version 0.6: Cleanup - -Lots of cleanup and docs additions made it into this release. Parsing is simpler -and more robust; fall through option added and works as expected; much more -consistent variable names internally. - -- Simplified parsing to use `vector` only -- Fixed fallthrough, made it optional as well (default: off): `.fallthrough()`. -- Added string versions of `->requires()` and `->excludes()` for consistency. -- Renamed protected members for internal consistency, grouped docs. -- Added the ability to add a number to `.require_subcommand()`. - -## Version 0.5: Windows support - -- Allow `Hidden` options. -- Throw `OptionAlreadyAdded` errors for matching subcommands or options, with - ignore-case included, tests -- `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`. - Subcommands inherit setting from parent App on creation. -- Subcommands now can be "chained", that is, left over arguments can now include - subcommands that then get parsed. Subcommands are now a list - (`get_subcommands`). Added `got_subcommand(App_or_name)` to check for - subcommands. -- Added `.allow_extras()` to disable error on failure. Parse returns a vector of - leftover options. Renamed error to `ExtrasError`, and now triggers on extra - options too. -- Added `require_subcommand` to `App`, to simplify forcing subcommands. Do - **not** do `add_subcommand()->require_subcommand`, since that is the - subcommand, not the main `App`. -- Added printout of ini file text given parsed options, skips flags. -- Support for quotes and spaces in ini files -- Fixes to allow support for Windows (added Appveyor) (Uses `-`, not `/` syntax) - -## Version 0.4: Ini support - -- Updates to help print -- Removed `run`, please use `parse` unless you subclass and add it -- Supports ini files mixed with command line, tested -- Added Range for further Plumbum compatibility -- Added function to print out ini file - -## Version 0.3: Plumbum compatibility - -- Added `->requires`, `->excludes`, and `->envname` from - [Plumbum](http://plumbum.readthedocs.io/en/latest/) -- Supports `->mandatory` from Plumbum -- More tests for help strings, improvements in formatting -- Support type and set syntax in positionals help strings -- Added help groups, with `->group("name")` syntax -- Added initial support for ini file reading with `add_config` option. -- Supports GCC 4.7 again -- Clang 3.5 now required for tests due to googlemock usage, 3.4 should still - work otherwise -- Changes `setup` for an explicit help bool in constructor/`add_subcommand` - -## Version 0.2: Leaner and meaner - -- Moved to simpler syntax, where `Option` pointers are returned and operated on -- Removed `make_` style options -- Simplified Validators, now only requires `->check(function)` -- Removed Combiners -- Fixed pointers to Options, stored in `unique_ptr` now -- Added `Option_p` and `App_p`, mostly for internal use -- Startup sequence, including help flag, can be modified by subclasses - -## Version 0.1: First release - -First release before major cleanup. Still has make syntax and combiners; very -clever syntax but not the best or most commonly expected way to work. diff --git a/external/CLI11/CLI/CLI.hpp b/external/CLI11/CLI/CLI.hpp new file mode 100644 index 000000000..9fa9cc026 --- /dev/null +++ b/external/CLI11/CLI/CLI.hpp @@ -0,0 +1,11527 @@ +// CLI11: Version 2.5.0 +// Originally designed by Henry Schreiner +// https://github.com/CLIUtils/CLI11 +// +// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts +// from: v2.5.0 +// +// CLI11 2.5.0 Copyright (c) 2017-2025 University of Cincinnati, developed by Henry +// Schreiner under NSF AWARD 1414736. All rights reserved. +// +// Redistribution and use in source and binary forms of CLI11, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +// Standard combined includes: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CLI11_VERSION_MAJOR 2 +#define CLI11_VERSION_MINOR 5 +#define CLI11_VERSION_PATCH 0 +#define CLI11_VERSION "2.5.0" + + + + +// The following version macro is very similar to the one in pybind11 +#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER) +#if __cplusplus >= 201402L +#define CLI11_CPP14 +#if __cplusplus >= 201703L +#define CLI11_CPP17 +#if __cplusplus > 201703L +#define CLI11_CPP20 +#if __cplusplus > 202002L +#define CLI11_CPP23 +#if __cplusplus > 202302L +#define CLI11_CPP26 +#endif +#endif +#endif +#endif +#endif +#elif defined(_MSC_VER) && __cplusplus == 199711L +// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard was fully implemented) +// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer +#if _MSVC_LANG >= 201402L +#define CLI11_CPP14 +#if _MSVC_LANG > 201402L && _MSC_VER >= 1910 +#define CLI11_CPP17 +#if _MSVC_LANG > 201703L && _MSC_VER >= 1910 +#define CLI11_CPP20 +#if _MSVC_LANG > 202002L && _MSC_VER >= 1922 +#define CLI11_CPP23 +#endif +#endif +#endif +#endif +#endif + +#if defined(CLI11_CPP14) +#define CLI11_DEPRECATED(reason) [[deprecated(reason)]] +#elif defined(_MSC_VER) +#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason)) +#else +#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason))) +#endif + +// GCC < 10 doesn't ignore this in unevaluated contexts +#if !defined(CLI11_CPP17) || \ + (defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 10 && __GNUC__ > 4) +#define CLI11_NODISCARD +#else +#define CLI11_NODISCARD [[nodiscard]] +#endif + +/** detection of rtti */ +#ifndef CLI11_USE_STATIC_RTTI +#if (defined(_HAS_STATIC_RTTI) && _HAS_STATIC_RTTI) +#define CLI11_USE_STATIC_RTTI 1 +#elif defined(__cpp_rtti) +#if (defined(_CPPRTTI) && _CPPRTTI == 0) +#define CLI11_USE_STATIC_RTTI 1 +#else +#define CLI11_USE_STATIC_RTTI 0 +#endif +#elif (defined(__GCC_RTTI) && __GXX_RTTI) +#define CLI11_USE_STATIC_RTTI 0 +#else +#define CLI11_USE_STATIC_RTTI 1 +#endif +#endif + +/** availability */ +#if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM +#if __has_include() +// Filesystem cannot be used if targeting macOS < 10.15 +#if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 +#define CLI11_HAS_FILESYSTEM 0 +#elif defined(__wasi__) +// As of wasi-sdk-14, filesystem is not implemented +#define CLI11_HAS_FILESYSTEM 0 +#else +#include +#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703 +#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9 +#define CLI11_HAS_FILESYSTEM 1 +#elif defined(__GLIBCXX__) +// if we are using gcc and Version <9 default to no filesystem +#define CLI11_HAS_FILESYSTEM 0 +#else +#define CLI11_HAS_FILESYSTEM 1 +#endif +#else +#define CLI11_HAS_FILESYSTEM 0 +#endif +#endif +#endif +#endif + +/** availability */ +#if !defined(CLI11_CPP26) && !defined(CLI11_HAS_CODECVT) +#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 5 +#define CLI11_HAS_CODECVT 0 +#else +#define CLI11_HAS_CODECVT 1 +#include +#endif +#else +#if defined(CLI11_HAS_CODECVT) +#if CLI11_HAS_CODECVT > 0 +#include +#endif +#else +#define CLI11_HAS_CODECVT 0 +#endif +#endif + +/** disable deprecations */ +#if defined(__GNUC__) // GCC or clang +#define CLI11_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define CLI11_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") + +#elif defined(_MSC_VER) +#define CLI11_DIAGNOSTIC_PUSH __pragma(warning(push)) +#define CLI11_DIAGNOSTIC_POP __pragma(warning(pop)) + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED __pragma(warning(disable : 4996)) + +#else +#define CLI11_DIAGNOSTIC_PUSH +#define CLI11_DIAGNOSTIC_POP + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED + +#endif + +/** Inline macro **/ +#ifdef CLI11_COMPILE +#define CLI11_INLINE +#else +#define CLI11_INLINE inline +#endif + + + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +#include // NOLINT(build/include) +#else +#include +#include +#endif + + + + +#ifdef CLI11_CPP17 +#include +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +#include +#include // NOLINT(build/include) +#endif // CLI11_HAS_FILESYSTEM + + + +#if defined(_WIN32) +#if !(defined(_AMD64_) || defined(_X86_) || defined(_ARM_)) +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || \ + defined(_M_AMD64) +#define _AMD64_ +#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(__i386__) || defined(_M_IX86) +#define _X86_ +#elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARMT) +#define _ARM_ +#elif defined(__aarch64__) || defined(_M_ARM64) +#define _ARM64_ +#elif defined(_M_ARM64EC) +#define _ARM64EC_ +#endif +#endif + +// first +#ifndef NOMINMAX +// if NOMINMAX is already defined we don't want to mess with that either way +#define NOMINMAX +#include +#undef NOMINMAX +#else +#include +#endif + +// second +#include +// third +#include +#include +#endif + + +namespace CLI { + + +/// Convert a wide string to a narrow string. +CLI11_INLINE std::string narrow(const std::wstring &str); +CLI11_INLINE std::string narrow(const wchar_t *str); +CLI11_INLINE std::string narrow(const wchar_t *str, std::size_t size); + +/// Convert a narrow string to a wide string. +CLI11_INLINE std::wstring widen(const std::string &str); +CLI11_INLINE std::wstring widen(const char *str); +CLI11_INLINE std::wstring widen(const char *str, std::size_t size); + +#ifdef CLI11_CPP17 +CLI11_INLINE std::string narrow(std::wstring_view str); +CLI11_INLINE std::wstring widen(std::string_view str); +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +/// Convert a char-string to a native path correctly. +CLI11_INLINE std::filesystem::path to_path(std::string_view str); +#endif // CLI11_HAS_FILESYSTEM + + + + +namespace detail { + +#if !CLI11_HAS_CODECVT +/// Attempt to set one of the acceptable unicode locales for conversion +CLI11_INLINE void set_unicode_locale() { + static const std::array unicode_locales{{"C.UTF-8", "en_US.UTF-8", ".UTF-8"}}; + + for(const auto &locale_name : unicode_locales) { + if(std::setlocale(LC_ALL, locale_name) != nullptr) { + return; + } + } + throw std::runtime_error("CLI::narrow: could not set locale to C.UTF-8"); +} + +template struct scope_guard_t { + F closure; + + explicit scope_guard_t(F closure_) : closure(closure_) {} + ~scope_guard_t() { closure(); } +}; + +template CLI11_NODISCARD CLI11_INLINE scope_guard_t scope_guard(F &&closure) { + return scope_guard_t{std::forward(closure)}; +} + +#endif // !CLI11_HAS_CODECVT + +CLI11_DIAGNOSTIC_PUSH +CLI11_DIAGNOSTIC_IGNORE_DEPRECATED + +CLI11_INLINE std::string narrow_impl(const wchar_t *str, std::size_t str_size) { +#if CLI11_HAS_CODECVT +#ifdef _WIN32 + return std::wstring_convert>().to_bytes(str, str + str_size); + +#else + return std::wstring_convert>().to_bytes(str, str + str_size); + +#endif // _WIN32 +#else // CLI11_HAS_CODECVT + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const wchar_t *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); + set_unicode_locale(); + + std::size_t new_size = std::wcsrtombs(nullptr, &it, 0, &state); + if(new_size == static_cast(-1)) { + throw std::runtime_error("CLI::narrow: conversion error in std::wcsrtombs at offset " + + std::to_string(it - str)); + } + std::string result(new_size, '\0'); + std::wcsrtombs(const_cast(result.data()), &str, new_size, &state); + + return result; + +#endif // CLI11_HAS_CODECVT +} + +CLI11_INLINE std::wstring widen_impl(const char *str, std::size_t str_size) { +#if CLI11_HAS_CODECVT +#ifdef _WIN32 + return std::wstring_convert>().from_bytes(str, str + str_size); + +#else + return std::wstring_convert>().from_bytes(str, str + str_size); + +#endif // _WIN32 +#else // CLI11_HAS_CODECVT + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const char *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); + set_unicode_locale(); + + std::size_t new_size = std::mbsrtowcs(nullptr, &it, 0, &state); + if(new_size == static_cast(-1)) { + throw std::runtime_error("CLI::widen: conversion error in std::mbsrtowcs at offset " + + std::to_string(it - str)); + } + std::wstring result(new_size, L'\0'); + std::mbsrtowcs(const_cast(result.data()), &str, new_size, &state); + + return result; + +#endif // CLI11_HAS_CODECVT +} + +CLI11_DIAGNOSTIC_POP + +} // namespace detail + +CLI11_INLINE std::string narrow(const wchar_t *str, std::size_t str_size) { return detail::narrow_impl(str, str_size); } +CLI11_INLINE std::string narrow(const std::wstring &str) { return detail::narrow_impl(str.data(), str.size()); } +// Flawfinder: ignore +CLI11_INLINE std::string narrow(const wchar_t *str) { return detail::narrow_impl(str, std::wcslen(str)); } + +CLI11_INLINE std::wstring widen(const char *str, std::size_t str_size) { return detail::widen_impl(str, str_size); } +CLI11_INLINE std::wstring widen(const std::string &str) { return detail::widen_impl(str.data(), str.size()); } +// Flawfinder: ignore +CLI11_INLINE std::wstring widen(const char *str) { return detail::widen_impl(str, std::strlen(str)); } + +#ifdef CLI11_CPP17 +CLI11_INLINE std::string narrow(std::wstring_view str) { return detail::narrow_impl(str.data(), str.size()); } +CLI11_INLINE std::wstring widen(std::string_view str) { return detail::widen_impl(str.data(), str.size()); } +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +CLI11_INLINE std::filesystem::path to_path(std::string_view str) { + return std::filesystem::path{ +#ifdef _WIN32 + widen(str) +#else + str +#endif // _WIN32 + }; +} +#endif // CLI11_HAS_FILESYSTEM + + + + +namespace detail { +#ifdef _WIN32 +/// Decode and return UTF-8 argv from GetCommandLineW. +CLI11_INLINE std::vector compute_win32_argv(); +#endif +} // namespace detail + + + +namespace detail { + +#ifdef _WIN32 +CLI11_INLINE std::vector compute_win32_argv() { + std::vector result; + int argc = 0; + + auto deleter = [](wchar_t **ptr) { LocalFree(ptr); }; + // NOLINTBEGIN(*-avoid-c-arrays) + auto wargv = std::unique_ptr(CommandLineToArgvW(GetCommandLineW(), &argc), deleter); + // NOLINTEND(*-avoid-c-arrays) + + if(wargv == nullptr) { + throw std::runtime_error("CommandLineToArgvW failed with code " + std::to_string(GetLastError())); + } + + result.reserve(static_cast(argc)); + for(size_t i = 0; i < static_cast(argc); ++i) { + result.push_back(narrow(wargv[i])); + } + + return result; +} +#endif + +} // namespace detail + + + + +/// Include the items in this namespace to get free conversion of enums to/from streams. +/// (This is available inside CLI as well, so CLI11 will use this without a using statement). +namespace enums { + +/// output streaming for enumerations +template ::value>::type> +std::ostream &operator<<(std::ostream &in, const T &item) { + // make sure this is out of the detail namespace otherwise it won't be found when needed + return in << static_cast::type>(item); +} + +} // namespace enums + +/// Export to CLI namespace +using enums::operator<<; + +namespace detail { +/// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not +/// produce overflow for some expected uses +constexpr int expected_max_vector_size{1 << 29}; +// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c +/// Split a string by a delim +CLI11_INLINE std::vector split(const std::string &s, char delim); + +/// Simple function to join a string +template std::string join(const T &v, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + if(beg != end) + s << *beg++; + while(beg != end) { + s << delim << *beg++; + } + auto rval = s.str(); + if(!rval.empty() && delim.size() == 1 && rval.back() == delim[0]) { + // remove trailing delimiter if the last entry was empty + rval.pop_back(); + } + return rval; +} + +/// Simple function to join a string from processed elements +template ::value>::type> +std::string join(const T &v, Callable func, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + auto loc = s.tellp(); + while(beg != end) { + auto nloc = s.tellp(); + if(nloc > loc) { + s << delim; + loc = nloc; + } + s << func(*beg++); + } + return s.str(); +} + +/// Join a string in reverse order +template std::string rjoin(const T &v, std::string delim = ",") { + std::ostringstream s; + for(std::size_t start = 0; start < v.size(); start++) { + if(start > 0) + s << delim; + s << v[v.size() - start - 1]; + } + return s.str(); +} + +// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string + +/// Trim whitespace from left of string +CLI11_INLINE std::string <rim(std::string &str); + +/// Trim anything from left of string +CLI11_INLINE std::string <rim(std::string &str, const std::string &filter); + +/// Trim whitespace from right of string +CLI11_INLINE std::string &rtrim(std::string &str); + +/// Trim anything from right of string +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter); + +/// Trim whitespace from string +inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } + +/// Trim anything from string +inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); } + +/// Make a copy of the string and then trim it +inline std::string trim_copy(const std::string &str) { + std::string s = str; + return trim(s); +} + +/// remove quotes at the front and back of a string either '"' or '\'' +CLI11_INLINE std::string &remove_quotes(std::string &str); + +/// remove quotes from all elements of a string vector and process escaped components +CLI11_INLINE void remove_quotes(std::vector &args); + +/// Add a leader to the beginning of all new lines (nothing is added +/// at the start of the first line). `"; "` would be for ini files +/// +/// Can't use Regex, or this would be a subs. +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input); + +/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) +inline std::string trim_copy(const std::string &str, const std::string &filter) { + std::string s = str; + return trim(s, filter); +} + +/// Print subcommand aliases +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid); + +/// Verify the first character of an option +/// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with +template bool valid_first_char(T c) { + return ((c != '-') && (static_cast(c) > 33)); // space and '!' not allowed +} + +/// Verify following characters of an option +template bool valid_later_char(T c) { + // = and : are value separators, { has special meaning for option defaults, + // and control codes other than tab would just be annoying to deal with in many places allowing space here has too + // much potential for inadvertent entry errors and bugs + return ((c != '=') && (c != ':') && (c != '{') && ((static_cast(c) > 32) || c == '\t')); +} + +/// Verify an option/subcommand name +CLI11_INLINE bool valid_name_string(const std::string &str); + +/// Verify an app name +inline bool valid_alias_name_string(const std::string &str) { + static const std::string badChars(std::string("\n") + '\0'); + return (str.find_first_of(badChars) == std::string::npos); +} + +/// check if a string is a container segment separator (empty or "%%") +inline bool is_separator(const std::string &str) { + static const std::string sep("%%"); + return (str.empty() || str == sep); +} + +/// Verify that str consists of letters only +inline bool isalpha(const std::string &str) { + return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); }); +} + +/// Return a lower case version of a string +inline std::string to_lower(std::string str) { + std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) { + return std::tolower(x, std::locale()); + }); + return str; +} + +/// remove underscores from a string +inline std::string remove_underscore(std::string str) { + str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str)); + return str; +} + +/// Find and replace a substring with another substring +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to); + +/// check if the flag definitions has possible false flags +inline bool has_default_flag_values(const std::string &flags) { + return (flags.find_first_of("{!") != std::string::npos); +} + +CLI11_INLINE void remove_default_flag_values(std::string &flags); + +/// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores +CLI11_INLINE std::ptrdiff_t find_member(std::string name, + const std::vector names, + bool ignore_case = false, + bool ignore_underscore = false); + +/// Find a trigger string and call a modify callable function that takes the current string and starting position of the +/// trigger and returns the position in the string to search for the next trigger string +template inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) { + std::size_t start_pos = 0; + while((start_pos = str.find(trigger, start_pos)) != std::string::npos) { + start_pos = modify(str, start_pos); + } + return str; +} + +/// close a sequence of characters indicated by a closure character. Brackets allows sub sequences +/// recognized bracket sequences include "'`[(<{ other closure characters are assumed to be literal strings +CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char); + +/// Split a string '"one two" "three"' into 'one two', 'three' +/// Quote characters can be ` ' or " or bracket characters [{(< with matching to the matching bracket +CLI11_INLINE std::vector split_up(std::string str, char delimiter = '\0'); + +/// get the value of an environmental variable or empty string if empty +CLI11_INLINE std::string get_environment_value(const std::string &env_name); + +/// This function detects an equal or colon followed by an escaped quote after an argument +/// then modifies the string to replace the equality with a space. This is needed +/// to allow the split up function to work properly and is intended to be used with the find_and_modify function +/// the return value is the offset+1 which is required by the find_and_modify function. +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset); + +/// @brief detect if a string has escapable characters +/// @param str the string to do the detection on +/// @return true if the string has escapable characters +CLI11_INLINE bool has_escapable_character(const std::string &str); + +/// @brief escape all escapable characters +/// @param str the string to escape +/// @return a string with the escapable characters escaped with '\' +CLI11_INLINE std::string add_escaped_characters(const std::string &str); + +/// @brief replace the escaped characters with their equivalent +CLI11_INLINE std::string remove_escaped_characters(const std::string &str); + +/// generate a string with all non printable characters escaped to hex codes +CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape); + +CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string); + +/// extract an escaped binary_string +CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string); + +/// process a quoted string, remove the quotes and if appropriate handle escaped characters +CLI11_INLINE bool process_quoted_string(std::string &str, char string_char = '\"', char literal_char = '\''); + +/// This function formats the given text as a paragraph with fixed width and applies correct line wrapping +/// with a custom line prefix. The paragraph will get streamed to the given ostream. +CLI11_INLINE std::ostream &streamOutAsParagraph(std::ostream &out, + const std::string &text, + std::size_t paragraphWidth, + const std::string &linePrefix = "", + bool skipPrefixOnFirstLine = false); + +} // namespace detail + + + + +namespace detail { +CLI11_INLINE std::vector split(const std::string &s, char delim) { + std::vector elems; + // Check to see if empty string, give consistent result + if(s.empty()) { + elems.emplace_back(); + } else { + std::stringstream ss; + ss.str(s); + std::string item; + while(std::getline(ss, item, delim)) { + elems.push_back(item); + } + } + return elems; +} + +CLI11_INLINE std::string <rim(std::string &str) { + auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(str.begin(), it); + return str; +} + +CLI11_INLINE std::string <rim(std::string &str, const std::string &filter) { + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(str.begin(), it); + return str; +} + +CLI11_INLINE std::string &rtrim(std::string &str) { + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(it.base(), str.end()); + return str; +} + +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) { + auto it = + std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(it.base(), str.end()); + return str; +} + +CLI11_INLINE std::string &remove_quotes(std::string &str) { + if(str.length() > 1 && (str.front() == '"' || str.front() == '\'' || str.front() == '`')) { + if(str.front() == str.back()) { + str.pop_back(); + str.erase(str.begin(), str.begin() + 1); + } + } + return str; +} + +CLI11_INLINE std::string &remove_outer(std::string &str, char key) { + if(str.length() > 1 && (str.front() == key)) { + if(str.front() == str.back()) { + str.pop_back(); + str.erase(str.begin(), str.begin() + 1); + } + } + return str; +} + +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input) { + std::string::size_type n = 0; + while(n != std::string::npos && n < input.size()) { + n = input.find('\n', n); + if(n != std::string::npos) { + input = input.substr(0, n + 1) + leader + input.substr(n + 1); + n += leader.size(); + } + } + return input; +} + +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid) { + if(!aliases.empty()) { + out << std::setw(static_cast(wid)) << " aliases: "; + bool front = true; + for(const auto &alias : aliases) { + if(!front) { + out << ", "; + } else { + front = false; + } + out << detail::fix_newlines(" ", alias); + } + out << "\n"; + } + return out; +} + +CLI11_INLINE bool valid_name_string(const std::string &str) { + if(str.empty() || !valid_first_char(str[0])) { + return false; + } + auto e = str.end(); + for(auto c = str.begin() + 1; c != e; ++c) + if(!valid_later_char(*c)) + return false; + return true; +} + +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to) { + + std::size_t start_pos = 0; + + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; +} + +CLI11_INLINE void remove_default_flag_values(std::string &flags) { + auto loc = flags.find_first_of('{', 2); + while(loc != std::string::npos) { + auto finish = flags.find_first_of("},", loc + 1); + if((finish != std::string::npos) && (flags[finish] == '}')) { + flags.erase(flags.begin() + static_cast(loc), + flags.begin() + static_cast(finish) + 1); + } + loc = flags.find_first_of('{', loc + 1); + } + flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end()); +} + +CLI11_INLINE std::ptrdiff_t +find_member(std::string name, const std::vector names, bool ignore_case, bool ignore_underscore) { + auto it = std::end(names); + if(ignore_case) { + if(ignore_underscore) { + name = detail::to_lower(detail::remove_underscore(name)); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(detail::remove_underscore(local_name)) == name; + }); + } else { + name = detail::to_lower(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(local_name) == name; + }); + } + + } else if(ignore_underscore) { + name = detail::remove_underscore(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::remove_underscore(local_name) == name; + }); + } else { + it = std::find(std::begin(names), std::end(names), name); + } + + return (it != std::end(names)) ? (it - std::begin(names)) : (-1); +} + +static const std::string escapedChars("\b\t\n\f\r\"\\"); +static const std::string escapedCharsCode("btnfr\"\\"); +static const std::string bracketChars{"\"'`[(<{"}; +static const std::string matchBracketChars("\"'`])>}"); + +CLI11_INLINE bool has_escapable_character(const std::string &str) { + return (str.find_first_of(escapedChars) != std::string::npos); +} + +CLI11_INLINE std::string add_escaped_characters(const std::string &str) { + std::string out; + out.reserve(str.size() + 4); + for(char s : str) { + auto sloc = escapedChars.find_first_of(s); + if(sloc != std::string::npos) { + out.push_back('\\'); + out.push_back(escapedCharsCode[sloc]); + } else { + out.push_back(s); + } + } + return out; +} + +CLI11_INLINE std::uint32_t hexConvert(char hc) { + int hcode{0}; + if(hc >= '0' && hc <= '9') { + hcode = (hc - '0'); + } else if(hc >= 'A' && hc <= 'F') { + hcode = (hc - 'A' + 10); + } else if(hc >= 'a' && hc <= 'f') { + hcode = (hc - 'a' + 10); + } else { + hcode = -1; + } + return static_cast(hcode); +} + +CLI11_INLINE char make_char(std::uint32_t code) { return static_cast(static_cast(code)); } + +CLI11_INLINE void append_codepoint(std::string &str, std::uint32_t code) { + if(code < 0x80) { // ascii code equivalent + str.push_back(static_cast(code)); + } else if(code < 0x800) { // \u0080 to \u07FF + // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111 + str.push_back(make_char(0xC0 | code >> 6)); + str.push_back(make_char(0x80 | (code & 0x3F))); + } else if(code < 0x10000) { // U+0800...U+FFFF + if(0xD800 <= code && code <= 0xDFFF) { + throw std::invalid_argument("[0xD800, 0xDFFF] are not valid UTF-8."); + } + // 1110yyyy 10yxxxxx 10xxxxxx + str.push_back(make_char(0xE0 | code >> 12)); + str.push_back(make_char(0x80 | (code >> 6 & 0x3F))); + str.push_back(make_char(0x80 | (code & 0x3F))); + } else if(code < 0x110000) { // U+010000 ... U+10FFFF + // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx + str.push_back(make_char(0xF0 | code >> 18)); + str.push_back(make_char(0x80 | (code >> 12 & 0x3F))); + str.push_back(make_char(0x80 | (code >> 6 & 0x3F))); + str.push_back(make_char(0x80 | (code & 0x3F))); + } +} + +CLI11_INLINE std::string remove_escaped_characters(const std::string &str) { + + std::string out; + out.reserve(str.size()); + for(auto loc = str.begin(); loc < str.end(); ++loc) { + if(*loc == '\\') { + if(str.end() - loc < 2) { + throw std::invalid_argument("invalid escape sequence " + str); + } + auto ecloc = escapedCharsCode.find_first_of(*(loc + 1)); + if(ecloc != std::string::npos) { + out.push_back(escapedChars[ecloc]); + ++loc; + } else if(*(loc + 1) == 'u') { + // must have 4 hex characters + if(str.end() - loc < 6) { + throw std::invalid_argument("unicode sequence must have 4 hex codes " + str); + } + std::uint32_t code{0}; + std::uint32_t mplier{16 * 16 * 16}; + for(int ii = 2; ii < 6; ++ii) { + std::uint32_t res = hexConvert(*(loc + ii)); + if(res > 0x0F) { + throw std::invalid_argument("unicode sequence must have 4 hex codes " + str); + } + code += res * mplier; + mplier = mplier / 16; + } + append_codepoint(out, code); + loc += 5; + } else if(*(loc + 1) == 'U') { + // must have 8 hex characters + if(str.end() - loc < 10) { + throw std::invalid_argument("unicode sequence must have 8 hex codes " + str); + } + std::uint32_t code{0}; + std::uint32_t mplier{16 * 16 * 16 * 16 * 16 * 16 * 16}; + for(int ii = 2; ii < 10; ++ii) { + std::uint32_t res = hexConvert(*(loc + ii)); + if(res > 0x0F) { + throw std::invalid_argument("unicode sequence must have 8 hex codes " + str); + } + code += res * mplier; + mplier = mplier / 16; + } + append_codepoint(out, code); + loc += 9; + } else if(*(loc + 1) == '0') { + out.push_back('\0'); + ++loc; + } else { + throw std::invalid_argument(std::string("unrecognized escape sequence \\") + *(loc + 1) + " in " + str); + } + } else { + out.push_back(*loc); + } + } + return out; +} + +CLI11_INLINE std::size_t close_string_quote(const std::string &str, std::size_t start, char closure_char) { + std::size_t loc{0}; + for(loc = start + 1; loc < str.size(); ++loc) { + if(str[loc] == closure_char) { + break; + } + if(str[loc] == '\\') { + // skip the next character for escaped sequences + ++loc; + } + } + return loc; +} + +CLI11_INLINE std::size_t close_literal_quote(const std::string &str, std::size_t start, char closure_char) { + auto loc = str.find_first_of(closure_char, start + 1); + return (loc != std::string::npos ? loc : str.size()); +} + +CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char) { + + auto bracket_loc = matchBracketChars.find(closure_char); + switch(bracket_loc) { + case 0: + return close_string_quote(str, start, closure_char); + case 1: + case 2: + case std::string::npos: + return close_literal_quote(str, start, closure_char); + default: + break; + } + + std::string closures(1, closure_char); + auto loc = start + 1; + + while(loc < str.size()) { + if(str[loc] == closures.back()) { + closures.pop_back(); + if(closures.empty()) { + return loc; + } + } + bracket_loc = bracketChars.find(str[loc]); + if(bracket_loc != std::string::npos) { + switch(bracket_loc) { + case 0: + loc = close_string_quote(str, loc, str[loc]); + break; + case 1: + case 2: + loc = close_literal_quote(str, loc, str[loc]); + break; + default: + closures.push_back(matchBracketChars[bracket_loc]); + break; + } + } + ++loc; + } + if(loc > str.size()) { + loc = str.size(); + } + return loc; +} + +CLI11_INLINE std::vector split_up(std::string str, char delimiter) { + + auto find_ws = [delimiter](char ch) { + return (delimiter == '\0') ? std::isspace(ch, std::locale()) : (ch == delimiter); + }; + trim(str); + + std::vector output; + while(!str.empty()) { + if(bracketChars.find_first_of(str[0]) != std::string::npos) { + auto bracketLoc = bracketChars.find_first_of(str[0]); + auto end = close_sequence(str, 0, matchBracketChars[bracketLoc]); + if(end >= str.size()) { + output.push_back(std::move(str)); + str.clear(); + } else { + output.push_back(str.substr(0, end + 1)); + if(end + 2 < str.size()) { + str = str.substr(end + 2); + } else { + str.clear(); + } + } + + } else { + auto it = std::find_if(std::begin(str), std::end(str), find_ws); + if(it != std::end(str)) { + std::string value = std::string(str.begin(), it); + output.push_back(value); + str = std::string(it + 1, str.end()); + } else { + output.push_back(str); + str.clear(); + } + } + trim(str); + } + return output; +} + +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) { + auto next = str[offset + 1]; + if((next == '\"') || (next == '\'') || (next == '`')) { + auto astart = str.find_last_of("-/ \"\'`", offset - 1); + if(astart != std::string::npos) { + if(str[astart] == ((str[offset] == '=') ? '-' : '/')) + str[offset] = ' '; // interpret this as a space so the split_up works properly + } + } + return offset + 1; +} + +CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape) { + // s is our escaped output string + std::string escaped_string{}; + // loop through all characters + for(char c : string_to_escape) { + // check if a given character is printable + // the cast is necessary to avoid undefined behaviour + if(isprint(static_cast(c)) == 0) { + std::stringstream stream; + // if the character is not printable + // we'll convert it to a hex string using a stringstream + // note that since char is signed we have to cast it to unsigned first + stream << std::hex << static_cast(static_cast(c)); + std::string code = stream.str(); + escaped_string += std::string("\\x") + (code.size() < 2 ? "0" : "") + code; + } else if(c == 'x' || c == 'X') { + // need to check for inadvertent binary sequences + if(!escaped_string.empty() && escaped_string.back() == '\\') { + escaped_string += std::string("\\x") + (c == 'x' ? "78" : "58"); + } else { + escaped_string.push_back(c); + } + + } else { + escaped_string.push_back(c); + } + } + if(escaped_string != string_to_escape) { + auto sqLoc = escaped_string.find('\''); + while(sqLoc != std::string::npos) { + escaped_string[sqLoc] = '\\'; + escaped_string.insert(sqLoc + 1, "x27"); + sqLoc = escaped_string.find('\''); + } + escaped_string.insert(0, "'B\"("); + escaped_string.push_back(')'); + escaped_string.push_back('"'); + escaped_string.push_back('\''); + } + return escaped_string; +} + +CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string) { + size_t ssize = escaped_string.size(); + if(escaped_string.compare(0, 3, "B\"(") == 0 && escaped_string.compare(ssize - 2, 2, ")\"") == 0) { + return true; + } + return (escaped_string.compare(0, 4, "'B\"(") == 0 && escaped_string.compare(ssize - 3, 3, ")\"'") == 0); +} + +CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string) { + std::size_t start{0}; + std::size_t tail{0}; + size_t ssize = escaped_string.size(); + if(escaped_string.compare(0, 3, "B\"(") == 0 && escaped_string.compare(ssize - 2, 2, ")\"") == 0) { + start = 3; + tail = 2; + } else if(escaped_string.compare(0, 4, "'B\"(") == 0 && escaped_string.compare(ssize - 3, 3, ")\"'") == 0) { + start = 4; + tail = 3; + } + + if(start == 0) { + return escaped_string; + } + std::string outstring; + + outstring.reserve(ssize - start - tail); + std::size_t loc = start; + while(loc < ssize - tail) { + // ssize-2 to skip )" at the end + if(escaped_string[loc] == '\\' && (escaped_string[loc + 1] == 'x' || escaped_string[loc + 1] == 'X')) { + auto c1 = escaped_string[loc + 2]; + auto c2 = escaped_string[loc + 3]; + + std::uint32_t res1 = hexConvert(c1); + std::uint32_t res2 = hexConvert(c2); + if(res1 <= 0x0F && res2 <= 0x0F) { + loc += 4; + outstring.push_back(static_cast(res1 * 16 + res2)); + continue; + } + } + outstring.push_back(escaped_string[loc]); + ++loc; + } + return outstring; +} + +CLI11_INLINE void remove_quotes(std::vector &args) { + for(auto &arg : args) { + if(arg.front() == '\"' && arg.back() == '\"') { + remove_quotes(arg); + // only remove escaped for string arguments not literal strings + arg = remove_escaped_characters(arg); + } else { + remove_quotes(arg); + } + } +} + +CLI11_INLINE void handle_secondary_array(std::string &str) { + if(str.size() >= 2 && str.front() == '[' && str.back() == ']') { + // handle some special array processing for arguments if it might be interpreted as a secondary array + std::string tstr{"[["}; + for(std::size_t ii = 1; ii < str.size(); ++ii) { + tstr.push_back(str[ii]); + tstr.push_back(str[ii]); + } + str = std::move(tstr); + } +} + +CLI11_INLINE bool process_quoted_string(std::string &str, char string_char, char literal_char) { + if(str.size() <= 1) { + return false; + } + if(detail::is_binary_escaped_string(str)) { + str = detail::extract_binary_string(str); + handle_secondary_array(str); + return true; + } + if(str.front() == string_char && str.back() == string_char) { + detail::remove_outer(str, string_char); + if(str.find_first_of('\\') != std::string::npos) { + str = detail::remove_escaped_characters(str); + } + handle_secondary_array(str); + return true; + } + if((str.front() == literal_char || str.front() == '`') && str.back() == str.front()) { + detail::remove_outer(str, str.front()); + handle_secondary_array(str); + return true; + } + return false; +} + +std::string get_environment_value(const std::string &env_name) { + char *buffer = nullptr; + std::string ename_string; + +#ifdef _MSC_VER + // Windows version + std::size_t sz = 0; + if(_dupenv_s(&buffer, &sz, env_name.c_str()) == 0 && buffer != nullptr) { + ename_string = std::string(buffer); + free(buffer); + } +#else + // This also works on Windows, but gives a warning + buffer = std::getenv(env_name.c_str()); + if(buffer != nullptr) { + ename_string = std::string(buffer); + } +#endif + return ename_string; +} + +CLI11_INLINE std::ostream &streamOutAsParagraph(std::ostream &out, + const std::string &text, + std::size_t paragraphWidth, + const std::string &linePrefix, + bool skipPrefixOnFirstLine) { + if(!skipPrefixOnFirstLine) + out << linePrefix; // First line prefix + + std::istringstream lss(text); + std::string line = ""; + while(std::getline(lss, line)) { + std::istringstream iss(line); + std::string word = ""; + std::size_t charsWritten = 0; + + while(iss >> word) { + if(word.length() + charsWritten > paragraphWidth) { + out << '\n' << linePrefix; + charsWritten = 0; + } + + out << word << " "; + charsWritten += word.length() + 1; + } + + if(!lss.eof()) + out << '\n' << linePrefix; + } + return out; +} + +} // namespace detail + + + +// Use one of these on all error classes. +// These are temporary and are undef'd at the end of this file. +#define CLI11_ERROR_DEF(parent, name) \ + protected: \ + name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \ + name(std::string ename, std::string msg, ExitCodes exit_code) \ + : parent(std::move(ename), std::move(msg), exit_code) {} \ + \ + public: \ + name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \ + name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {} + +// This is added after the one above if a class is used directly and builds its own message +#define CLI11_ERROR_SIMPLE(name) \ + explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {} + +/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, +/// int values from e.get_error_code(). +enum class ExitCodes { + Success = 0, + IncorrectConstruction = 100, + BadNameString, + OptionAlreadyAdded, + FileError, + ConversionError, + ValidationError, + RequiredError, + RequiresError, + ExcludesError, + ExtrasError, + ConfigError, + InvalidError, + HorribleError, + OptionNotFound, + ArgumentMismatch, + BaseClass = 127 +}; + +// Error definitions + +/// @defgroup error_group Errors +/// @brief Errors thrown by CLI11 +/// +/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors. +/// @{ + +/// All errors derive from this one +class Error : public std::runtime_error { + int actual_exit_code; + std::string error_name{"Error"}; + + public: + CLI11_NODISCARD int get_exit_code() const { return actual_exit_code; } + + CLI11_NODISCARD std::string get_name() const { return error_name; } + + Error(std::string name, std::string msg, int exit_code = static_cast(ExitCodes::BaseClass)) + : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {} + + Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast(exit_code)) {} +}; + +// Note: Using Error::Error constructors does not work on GCC 4.7 + +/// Construction errors (not in parsing) +class ConstructionError : public Error { + CLI11_ERROR_DEF(Error, ConstructionError) +}; + +/// Thrown when an option is set to conflicting values (non-vector and multi args, for example) +class IncorrectConstruction : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) + CLI11_ERROR_SIMPLE(IncorrectConstruction) + static IncorrectConstruction PositionalFlag(std::string name) { + return IncorrectConstruction(name + ": Flags cannot be positional"); + } + static IncorrectConstruction Set0Opt(std::string name) { + return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead"); + } + static IncorrectConstruction SetFlag(std::string name) { + return IncorrectConstruction(name + ": Cannot set an expected number for flags"); + } + static IncorrectConstruction ChangeNotVector(std::string name) { + return IncorrectConstruction(name + ": You can only change the expected arguments for vectors"); + } + static IncorrectConstruction AfterMultiOpt(std::string name) { + return IncorrectConstruction( + name + ": You can't change expected arguments after you've changed the multi option policy!"); + } + static IncorrectConstruction MissingOption(std::string name) { + return IncorrectConstruction("Option " + name + " is not defined"); + } + static IncorrectConstruction MultiOptionPolicy(std::string name) { + return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options"); + } +}; + +/// Thrown on construction of a bad name +class BadNameString : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, BadNameString) + CLI11_ERROR_SIMPLE(BadNameString) + static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); } + static BadNameString MissingDash(std::string name) { + return BadNameString("Long names strings require 2 dashes " + name); + } + static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); } + static BadNameString BadPositionalName(std::string name) { + return BadNameString("Invalid positional Name: " + name); + } + static BadNameString ReservedName(std::string name) { + return BadNameString("Names '-','--','++' are reserved and not allowed as option names " + name); + } + static BadNameString MultiPositionalNames(std::string name) { + return BadNameString("Only one positional name allowed, remove: " + name); + } +}; + +/// Thrown when an option already exists +class OptionAlreadyAdded : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) + explicit OptionAlreadyAdded(std::string name) + : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {} + static OptionAlreadyAdded Requires(std::string name, std::string other) { + return {name + " requires " + other, ExitCodes::OptionAlreadyAdded}; + } + static OptionAlreadyAdded Excludes(std::string name, std::string other) { + return {name + " excludes " + other, ExitCodes::OptionAlreadyAdded}; + } +}; + +// Parsing errors + +/// Anything that can error in Parse +class ParseError : public Error { + CLI11_ERROR_DEF(Error, ParseError) +}; + +// Not really "errors" + +/// This is a successful completion on parsing, supposed to exit +class Success : public ParseError { + CLI11_ERROR_DEF(ParseError, Success) + Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {} +}; + +/// -h or --help on command line +class CallForHelp : public Success { + CLI11_ERROR_DEF(Success, CallForHelp) + CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Usually something like --help-all on command line +class CallForAllHelp : public Success { + CLI11_ERROR_DEF(Success, CallForAllHelp) + CallForAllHelp() + : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// -v or --version on command line +class CallForVersion : public Success { + CLI11_ERROR_DEF(Success, CallForVersion) + CallForVersion() + : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code. +class RuntimeError : public ParseError { + CLI11_ERROR_DEF(ParseError, RuntimeError) + explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} +}; + +/// Thrown when parsing an INI file and it is missing +class FileError : public ParseError { + CLI11_ERROR_DEF(ParseError, FileError) + CLI11_ERROR_SIMPLE(FileError) + static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); } +}; + +/// Thrown when conversion call back fails, such as when an int fails to coerce to a string +class ConversionError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConversionError) + CLI11_ERROR_SIMPLE(ConversionError) + ConversionError(std::string member, std::string name) + : ConversionError("The value " + member + " is not an allowed value for " + name) {} + ConversionError(std::string name, std::vector results) + : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {} + static ConversionError TooManyInputsFlag(std::string name) { + return ConversionError(name + ": too many inputs for a flag"); + } + static ConversionError TrueFalse(std::string name) { + return ConversionError(name + ": Should be true/false or a number"); + } +}; + +/// Thrown when validation of results fails +class ValidationError : public ParseError { + CLI11_ERROR_DEF(ParseError, ValidationError) + CLI11_ERROR_SIMPLE(ValidationError) + explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {} +}; + +/// Thrown when a required option is missing +class RequiredError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiredError) + explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {} + static RequiredError Subcommand(std::size_t min_subcom) { + if(min_subcom == 1) { + return RequiredError("A subcommand"); + } + return {"Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError}; + } + static RequiredError + Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) { + if((min_option == 1) && (max_option == 1) && (used == 0)) + return RequiredError("Exactly 1 option from [" + option_list + "]"); + if((min_option == 1) && (max_option == 1) && (used > 1)) { + return {"Exactly 1 option from [" + option_list + "] is required but " + std::to_string(used) + + " were given", + ExitCodes::RequiredError}; + } + if((min_option == 1) && (used == 0)) + return RequiredError("At least 1 option from [" + option_list + "]"); + if(used < min_option) { + return {"Requires at least " + std::to_string(min_option) + " options used but only " + + std::to_string(used) + " were given from [" + option_list + "]", + ExitCodes::RequiredError}; + } + if(max_option == 1) + return {"Requires at most 1 options be given from [" + option_list + "]", ExitCodes::RequiredError}; + + return {"Requires at most " + std::to_string(max_option) + " options be used but " + std::to_string(used) + + " were given from [" + option_list + "]", + ExitCodes::RequiredError}; + } +}; + +/// Thrown when the wrong number of arguments has been received +class ArgumentMismatch : public ParseError { + CLI11_ERROR_DEF(ParseError, ArgumentMismatch) + CLI11_ERROR_SIMPLE(ArgumentMismatch) + ArgumentMismatch(std::string name, int expected, std::size_t received) + : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name + + ", got " + std::to_string(received)) + : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + + ", got " + std::to_string(received)), + ExitCodes::ArgumentMismatch) {} + + static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) { + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing"); + } + static ArgumentMismatch FlagOverride(std::string name) { + return ArgumentMismatch(name + " was given a disallowed flag override"); + } + static ArgumentMismatch PartialType(std::string name, int num, std::string type) { + return ArgumentMismatch(name + ": " + type + " only partially specified: " + std::to_string(num) + + " required for each element"); + } +}; + +/// Thrown when a requires option is missing +class RequiresError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiresError) + RequiresError(std::string curname, std::string subname) + : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {} +}; + +/// Thrown when an excludes option is present +class ExcludesError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExcludesError) + ExcludesError(std::string curname, std::string subname) + : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {} +}; + +/// Thrown when too many positionals or options are found +class ExtrasError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExtrasError) + explicit ExtrasError(std::vector args) + : ExtrasError((args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} + ExtrasError(const std::string &name, std::vector args) + : ExtrasError(name, + (args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} +}; + +/// Thrown when extra values are found in an INI file +class ConfigError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConfigError) + CLI11_ERROR_SIMPLE(ConfigError) + static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); } + static ConfigError NotConfigurable(std::string item) { + return ConfigError(item + ": This option is not allowed in a configuration file"); + } +}; + +/// Thrown when validation fails before parsing +class InvalidError : public ParseError { + CLI11_ERROR_DEF(ParseError, InvalidError) + explicit InvalidError(std::string name) + : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) { + } +}; + +/// This is just a safety check to verify selection and parsing match - you should not ever see it +/// Strings are directly added to this error, but again, it should never be seen. +class HorribleError : public ParseError { + CLI11_ERROR_DEF(ParseError, HorribleError) + CLI11_ERROR_SIMPLE(HorribleError) +}; + +// After parsing + +/// Thrown when counting a nonexistent option +class OptionNotFound : public Error { + CLI11_ERROR_DEF(Error, OptionNotFound) + explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} +}; + +#undef CLI11_ERROR_DEF +#undef CLI11_ERROR_SIMPLE + +/// @} + + + + +// Type tools + +// Utilities for type enabling +namespace detail { +// Based generally on https://rmf.io/cxx11/almost-static-if +/// Simple empty scoped class +enum class enabler {}; + +/// An instance to use in EnableIf +constexpr enabler dummy = {}; +} // namespace detail + +/// A copy of enable_if_t from C++14, compatible with C++11. +/// +/// We could check to see if C++14 is being used, but it does not hurt to redefine this +/// (even Google does this: https://github.com/google/skia/blob/main/include/private/SkTLogic.h) +/// It is not in the std namespace anyway, so no harm done. +template using enable_if_t = typename std::enable_if::type; + +/// A copy of std::void_t from C++17 (helper for C++11 and C++14) +template struct make_void { + using type = void; +}; + +/// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine +template using void_t = typename make_void::type; + +/// A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine +template using conditional_t = typename std::conditional::type; + +/// Check to see if something is bool (fail check by default) +template struct is_bool : std::false_type {}; + +/// Check to see if something is bool (true if actually a bool) +template <> struct is_bool : std::true_type {}; + +/// Check to see if something is a shared pointer +template struct is_shared_ptr : std::false_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is copyable pointer +template struct is_copyable_ptr { + static bool const value = is_shared_ptr::value || std::is_pointer::value; +}; + +/// This can be specialized to override the type deduction for IsMember. +template struct IsMemberType { + using type = T; +}; + +/// The main custom type needed here is const char * should be a string. +template <> struct IsMemberType { + using type = std::string; +}; + +namespace adl_detail { +/// Check for existence of user-supplied lexical_cast. +/// +/// This struct has to be in a separate namespace so that it doesn't see our lexical_cast overloads in CLI::detail. +/// Standard says it shouldn't see them if it's defined before the corresponding lexical_cast declarations, but this +/// requires a working implementation of two-phase lookup, and not all compilers can boast that (msvc, ahem). +template class is_lexical_castable { + template + static auto test(int) -> decltype(lexical_cast(std::declval(), std::declval()), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; +} // namespace adl_detail + +namespace detail { + +// These are utilities for IsMember and other transforming objects + +/// Handy helper to access the element_type generically. This is not part of is_copyable_ptr because it requires that +/// pointer_traits be valid. + +/// not a pointer +template struct element_type { + using type = T; +}; + +template struct element_type::value>::type> { + using type = typename std::pointer_traits::element_type; +}; + +/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of +/// the container +template struct element_value_type { + using type = typename element_type::type::value_type; +}; + +/// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing. +template struct pair_adaptor : std::false_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } +}; + +/// Adaptor for map-like structure (true version, must have key_type and mapped_type). +/// This wraps a mapped container in a few utilities access it in a general way. +template +struct pair_adaptor< + T, + conditional_t, void>> + : std::true_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::get<0>(std::forward(pair_value))) { + return std::get<0>(std::forward(pair_value)); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::get<1>(std::forward(pair_value))) { + return std::get<1>(std::forward(pair_value)); + } +}; + +// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a -Wnarrowing warning +// in the unevaluated context even if the function that was using this wasn't used. The standard says narrowing in +// brace initialization shouldn't be allowed but for backwards compatibility gcc allows it in some contexts. It is a +// little fuzzy what happens in template constructs and I think that was something GCC took a little while to work out. +// But regardless some versions of gcc generate a warning when they shouldn't from the following code so that should be +// suppressed +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" +#endif +// check for constructibility from a specific type and copy assignable used in the parse detection +template class is_direct_constructible { + template + static auto test(int, std::true_type) -> decltype( +// NVCC warns about narrowing conversions here +#ifdef __CUDACC__ +#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +#pragma nv_diag_suppress 2361 +#else +#pragma diag_suppress 2361 +#endif +#endif + TT{std::declval()} +#ifdef __CUDACC__ +#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +#pragma nv_diag_default 2361 +#else +#pragma diag_default 2361 +#endif +#endif + , + std::is_move_assignable()); + + template static auto test(int, std::false_type) -> std::false_type; + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0, typename std::is_constructible::type()))::value; +}; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// Check for output streamability +// Based on https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream + +template class is_ostreamable { + template + static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Check for input streamability +template class is_istreamable { + template + static auto test(int) -> decltype(std::declval() >> std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Check for complex +template class is_complex { + template + static auto test(int) -> decltype(std::declval().real(), std::declval().imag(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Templated operation to get a value from a stream +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string &istring, T &obj) { + std::istringstream is; + is.str(istring); + is >> obj; + return !is.fail() && !is.rdbuf()->in_avail(); +} + +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string & /*istring*/, T & /*obj*/) { + return false; +} + +// check to see if an object is a mutable container (fail by default) +template struct is_mutable_container : std::false_type {}; + +/// type trait to test if a type is a mutable container meaning it has a value_type, it has an iterator, a clear, and +/// end methods and an insert function. And for our purposes we exclude std::string and types that can be constructed +/// from a std::string +template +struct is_mutable_container< + T, + conditional_t().end()), + decltype(std::declval().clear()), + decltype(std::declval().insert(std::declval().end())>(), + std::declval()))>, + void>> : public conditional_t::value || + std::is_constructible::value, + std::false_type, + std::true_type> {}; + +// check to see if an object is a mutable container (fail by default) +template struct is_readable_container : std::false_type {}; + +/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, and an end +/// method. +template +struct is_readable_container< + T, + conditional_t().end()), decltype(std::declval().begin())>, void>> + : public std::true_type {}; + +// check to see if an object is a wrapper (fail by default) +template struct is_wrapper : std::false_type {}; + +// check if an object is a wrapper (it has a value_type defined) +template +struct is_wrapper, void>> : public std::true_type {}; + +// Check for tuple like types, as in classes with a tuple_size type trait +// Even though in C++26 std::complex gains a std::tuple interface, for our purposes we treat is as NOT a tuple +template class is_tuple_like { + template ::value, detail::enabler> = detail::dummy> + // static auto test(int) + // -> decltype(std::conditional<(std::tuple_size::value > 0), std::true_type, std::false_type>::type()); + static auto test(int) -> decltype(std::tuple_size::type>::value, std::true_type{}); + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// This will only trigger for actual void type +template struct type_count_base { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count_base::value && !is_mutable_container::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// the base tuple size +template +struct type_count_base::value && !is_mutable_container::value>::type> { + static constexpr int value{// cppcheck-suppress unusedStructMember + std::tuple_size::type>::value}; +}; + +/// Type count base for containers is the type_count_base of the individual element +template struct type_count_base::value>::type> { + static constexpr int value{type_count_base::value}; +}; + +/// Convert an object to a string (directly forward if this can become a string) +template ::value, detail::enabler> = detail::dummy> +auto to_string(T &&value) -> decltype(std::forward(value)) { + return std::forward(value); +} + +/// Construct a string from the object +template ::value && !std::is_convertible::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&value) { + return std::string(value); // NOLINT(google-readability-casting) +} + +/// Convert an object to a string (streaming must be supported for that type) +template ::value && !std::is_constructible::value && + is_ostreamable::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&value) { + std::stringstream stream; + stream << value; + return stream.str(); +} + +// additional forward declarations + +/// Print tuple value string for tuples of size ==1 +template ::value && !std::is_constructible::value && + !is_ostreamable::value && is_tuple_like::value && type_count_base::value == 1, + detail::enabler> = detail::dummy> +inline std::string to_string(T &&value); + +/// Print tuple value string for tuples of size > 1 +template ::value && !std::is_constructible::value && + !is_ostreamable::value && is_tuple_like::value && type_count_base::value >= 2, + detail::enabler> = detail::dummy> +inline std::string to_string(T &&value); + +/// If conversion is not supported, return an empty string (streaming is not supported for that type) +template < + typename T, + enable_if_t::value && !std::is_constructible::value && + !is_ostreamable::value && !is_readable_container::type>::value && + !is_tuple_like::value, + detail::enabler> = detail::dummy> +inline std::string to_string(T &&) { + return {}; +} + +/// convert a readable container to a string +template ::value && !std::is_constructible::value && + !is_ostreamable::value && is_readable_container::value, + detail::enabler> = detail::dummy> +inline std::string to_string(T &&variable) { + auto cval = variable.begin(); + auto end = variable.end(); + if(cval == end) { + return {"{}"}; + } + std::vector defaults; + while(cval != end) { + defaults.emplace_back(CLI::detail::to_string(*cval)); + ++cval; + } + return {"[" + detail::join(defaults) + "]"}; +} + +/// Convert a tuple like object to a string + +/// forward declarations for tuple_value_strings +template +inline typename std::enable_if::value, std::string>::type tuple_value_string(T && /*value*/); + +/// Recursively generate the tuple value string +template +inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_value_string(T &&value); + +/// Print tuple value string for tuples of size ==1 +template ::value && !std::is_constructible::value && + !is_ostreamable::value && is_tuple_like::value && type_count_base::value == 1, + detail::enabler>> +inline std::string to_string(T &&value) { + return to_string(std::get<0>(value)); +} + +/// Print tuple value string for tuples of size > 1 +template ::value && !std::is_constructible::value && + !is_ostreamable::value && is_tuple_like::value && type_count_base::value >= 2, + detail::enabler>> +inline std::string to_string(T &&value) { + auto tname = std::string(1, '[') + tuple_value_string(value); + tname.push_back(']'); + return tname; +} + +/// Empty string if the index > tuple size +template +inline typename std::enable_if::value, std::string>::type tuple_value_string(T && /*value*/) { + return std::string{}; +} + +/// Recursively generate the tuple value string +template +inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_value_string(T &&value) { + auto str = std::string{to_string(std::get(value))} + ',' + tuple_value_string(value); + if(str.back() == ',') + str.pop_back(); + return str; +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +auto checked_to_string(T &&value) -> decltype(to_string(std::forward(value))) { + return to_string(std::forward(value)); +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +std::string checked_to_string(T &&) { + return std::string{}; +} +/// get a string as a convertible value for arithmetic types +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(value); +} +/// get a string as a convertible value for enumerations +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(static_cast::type>(value)); +} +/// for other types just use the regular to_string function +template ::value && !std::is_arithmetic::value, detail::enabler> = detail::dummy> +auto value_string(const T &value) -> decltype(to_string(value)) { + return to_string(value); +} + +/// template to get the underlying value type if it exists or use a default +template struct wrapped_type { + using type = def; +}; + +/// Type size for regular object types that do not look like a tuple +template struct wrapped_type::value>::type> { + using type = typename T::value_type; +}; + +/// Set of overloads to get the type size of an object + +/// forward declare the subtype_count structure +template struct subtype_count; + +/// forward declare the subtype_count_min structure +template struct subtype_count_min; + +/// This will only trigger for actual void type +template struct type_count { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count::value && !is_tuple_like::value && !is_complex::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count::value>::type> { + static constexpr int value{2}; +}; + +/// Type size of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template struct type_count::value>::type> { + static constexpr int value{subtype_count::value}; +}; + +/// Type size of types that are wrappers,except containers complex and tuples(which can also be wrappers sometimes) +template +struct type_count::value && !is_complex::value && !is_tuple_like::value && + !is_mutable_container::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size() { + return subtype_count::type>::value + tuple_type_size(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count::value>::type> { + static constexpr int value{tuple_type_size()}; +}; + +/// definition of subtype count +template struct subtype_count { + static constexpr int value{is_mutable_container::value ? expected_max_vector_size : type_count::value}; +}; + +/// This will only trigger for actual void type +template struct type_count_min { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count_min< + T, + typename std::enable_if::value && !is_tuple_like::value && !is_wrapper::value && + !is_complex::value && !std::is_void::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count_min::value>::type> { + static constexpr int value{1}; +}; + +/// Type size min of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template +struct type_count_min< + T, + typename std::enable_if::value && !is_complex::value && !is_tuple_like::value>::type> { + static constexpr int value{subtype_count_min::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size_min() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size_min() { + return subtype_count_min::type>::value + tuple_type_size_min(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count_min::value>::type> { + static constexpr int value{tuple_type_size_min()}; +}; + +/// definition of subtype count +template struct subtype_count_min { + static constexpr int value{is_mutable_container::value + ? ((type_count::value < expected_max_vector_size) ? type_count::value : 0) + : type_count_min::value}; +}; + +/// This will only trigger for actual void type +template struct expected_count { + static const int value{0}; +}; + +/// For most types the number of expected items is 1 +template +struct expected_count::value && !is_wrapper::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; +/// number of expected items in a vector +template struct expected_count::value>::type> { + static constexpr int value{expected_max_vector_size}; +}; + +/// number of expected items in a vector +template +struct expected_count::value && is_wrapper::value>::type> { + static constexpr int value{expected_count::value}; +}; + +// Enumeration of the different supported categorizations of objects +enum class object_category : int { + char_value = 1, + integral_value = 2, + unsigned_integral = 4, + enumeration = 6, + boolean_value = 8, + floating_point = 10, + number_constructible = 12, + double_constructible = 14, + integer_constructible = 16, + // string like types + string_assignable = 23, + string_constructible = 24, + wstring_assignable = 25, + wstring_constructible = 26, + other = 45, + // special wrapper or container types + wrapper_value = 50, + complex_number = 60, + tuple_value = 70, + container_value = 80, + +}; + +/// Set of overloads to classify an object according to type + +/// some type that is not otherwise recognized +template struct classify_object { + static constexpr object_category value{object_category::other}; +}; + +/// Signed integers +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_same::value && std::is_signed::value && + !is_bool::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::integral_value}; +}; + +/// Unsigned integers +template +struct classify_object::value && std::is_unsigned::value && + !std::is_same::value && !is_bool::value>::type> { + static constexpr object_category value{object_category::unsigned_integral}; +}; + +/// single character values +template +struct classify_object::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::char_value}; +}; + +/// Boolean values +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::boolean_value}; +}; + +/// Floats +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::floating_point}; +}; +#if defined _MSC_VER +// in MSVC wstring should take precedence if available this isn't as useful on other compilers due to the broader use of +// utf-8 encoding +#define WIDE_STRING_CHECK \ + !std::is_assignable::value && !std::is_constructible::value +#define STRING_CHECK true +#else +#define WIDE_STRING_CHECK true +#define STRING_CHECK !std::is_assignable::value && !std::is_constructible::value +#endif + +/// String and similar direct assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && WIDE_STRING_CHECK && + std::is_assignable::value>::type> { + static constexpr object_category value{object_category::string_assignable}; +}; + +/// String and similar constructible and copy assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + !std::is_assignable::value && (type_count::value == 1) && + WIDE_STRING_CHECK && std::is_constructible::value>::type> { + static constexpr object_category value{object_category::string_constructible}; +}; + +/// Wide strings +template +struct classify_object::value && !std::is_integral::value && + STRING_CHECK && std::is_assignable::value>::type> { + static constexpr object_category value{object_category::wstring_assignable}; +}; + +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + !std::is_assignable::value && (type_count::value == 1) && + STRING_CHECK && std::is_constructible::value>::type> { + static constexpr object_category value{object_category::wstring_constructible}; +}; + +/// Enumerations +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::enumeration}; +}; + +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::complex_number}; +}; + +/// Handy helper to contain a bunch of checks that rule out many common types (integers, string like, floating point, +/// vectors, and enumerations +template struct uncommon_type { + using type = typename std::conditional< + !std::is_floating_point::value && !std::is_integral::value && + !std::is_assignable::value && !std::is_constructible::value && + !std::is_assignable::value && !std::is_constructible::value && + !is_complex::value && !is_mutable_container::value && !std::is_enum::value, + std::true_type, + std::false_type>::type; + static constexpr bool value = type::value; +}; + +/// wrapper type +template +struct classify_object::value && is_wrapper::value && + !is_tuple_like::value && uncommon_type::value)>::type> { + static constexpr object_category value{object_category::wrapper_value}; +}; + +/// Assignable from double or int +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::number_constructible}; +}; + +/// Assignable from int +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && !is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::integer_constructible}; +}; + +/// Assignable from double +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && is_direct_constructible::value && + !is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::double_constructible}; +}; + +/// Tuple type +template +struct classify_object< + T, + typename std::enable_if::value && + ((type_count::value >= 2 && !is_wrapper::value) || + (uncommon_type::value && !is_direct_constructible::value && + !is_direct_constructible::value) || + (uncommon_type::value && type_count::value >= 2))>::type> { + static constexpr object_category value{object_category::tuple_value}; + // the condition on this class requires it be like a tuple, but on some compilers (like Xcode) tuples can be + // constructed from just the first element so tuples of can be constructed from a string, which + // could lead to issues so there are two variants of the condition, the first isolates things with a type size >=2 + // mainly to get tuples on Xcode with the exception of wrappers, the second is the main one and just separating out + // those cases that are caught by other object classifications +}; + +/// container type +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::container_value}; +}; + +// Type name print + +/// Was going to be based on +/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template +/// But this is cleaner and works better in this case + +template ::value == object_category::char_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "CHAR"; +} + +template ::value == object_category::integral_value || + classify_object::value == object_category::integer_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "INT"; +} + +template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "UINT"; +} + +template ::value == object_category::floating_point || + classify_object::value == object_category::number_constructible || + classify_object::value == object_category::double_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "FLOAT"; +} + +/// Print name for enumeration types +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "ENUM"; +} + +/// Print name for enumeration types +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "BOOLEAN"; +} + +/// Print name for enumeration types +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "COMPLEX"; +} + +/// Print for all other types +template ::value >= object_category::string_assignable && + classify_object::value <= object_category::other, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "TEXT"; +} +/// typename for tuple value +template ::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration + +/// Generate type name for a wrapper or container value +template ::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration + +/// Print name for single element tuple types +template ::value == object_category::tuple_value && type_count_base::value == 1, + detail::enabler> = detail::dummy> +inline std::string type_name() { + return type_name::type>::type>(); +} + +/// Empty string if the index > tuple size +template +inline typename std::enable_if::value, std::string>::type tuple_name() { + return std::string{}; +} + +/// Recursively generate the tuple type name +template +inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_name() { + auto str = std::string{type_name::type>::type>()} + ',' + + tuple_name(); + if(str.back() == ',') + str.pop_back(); + return str; +} + +/// Print type name for tuples with 2 or more elements +template ::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler>> +inline std::string type_name() { + auto tname = std::string(1, '[') + tuple_name(); + tname.push_back(']'); + return tname; +} + +/// get the type name for a type that has a value_type member +template ::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler>> +inline std::string type_name() { + return type_name(); +} + +// Lexical cast + +/// Convert to an unsigned integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty() || input.front() == '-') { + return false; + } + char *val{nullptr}; + errno = 0; + std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { + return true; + } + val = nullptr; + std::int64_t output_sll = std::strtoll(input.c_str(), &val, 0); + if(val == (input.c_str() + input.size())) { + output = (output_sll < 0) ? static_cast(0) : static_cast(output_sll); + return (static_cast(output) == output_sll); + } + // remove separators + if(input.find_first_of("_'") != std::string::npos) { + std::string nstring = input; + nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end()); + nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end()); + return integral_conversion(nstring, output); + } + if(std::isspace(static_cast(input.back()))) { + return integral_conversion(trim_copy(input), output); + } + if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) { + val = nullptr; + errno = 0; + output_ll = std::strtoull(input.c_str() + 2, &val, 8); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + return (val == (input.c_str() + input.size()) && static_cast(output) == output_ll); + } + if(input.compare(0, 2, "0b") == 0 || input.compare(0, 2, "0B") == 0) { + // LCOV_EXCL_START + // In some new compilers including the coverage testing one binary strings are handled properly in strtoull + // automatically so this coverage is missing but is well tested in other compilers + val = nullptr; + errno = 0; + output_ll = std::strtoull(input.c_str() + 2, &val, 2); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + return (val == (input.c_str() + input.size()) && static_cast(output) == output_ll); + // LCOV_EXCL_STOP + } + return false; +} + +/// Convert to a signed integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty()) { + return false; + } + char *val = nullptr; + errno = 0; + std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { + return true; + } + if(input == "true") { + // this is to deal with a few oddities with flags and wrapper int types + output = static_cast(1); + return true; + } + // remove separators and trailing spaces + if(input.find_first_of("_'") != std::string::npos) { + std::string nstring = input; + nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end()); + nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end()); + return integral_conversion(nstring, output); + } + if(std::isspace(static_cast(input.back()))) { + return integral_conversion(trim_copy(input), output); + } + if(input.compare(0, 2, "0o") == 0 || input.compare(0, 2, "0O") == 0) { + val = nullptr; + errno = 0; + output_ll = std::strtoll(input.c_str() + 2, &val, 8); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + return (val == (input.c_str() + input.size()) && static_cast(output) == output_ll); + } + if(input.compare(0, 2, "0b") == 0 || input.compare(0, 2, "0B") == 0) { + // LCOV_EXCL_START + // In some new compilers including the coverage testing one binary strings are handled properly in strtoll + // automatically so this coverage is missing but is well tested in other compilers + val = nullptr; + errno = 0; + output_ll = std::strtoll(input.c_str() + 2, &val, 2); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + return (val == (input.c_str() + input.size()) && static_cast(output) == output_ll); + // LCOV_EXCL_STOP + } + return false; +} + +/// Convert a flag into an integer value typically binary flags sets errno to nonzero if conversion failed +inline std::int64_t to_flag_value(std::string val) noexcept { + static const std::string trueString("true"); + static const std::string falseString("false"); + if(val == trueString) { + return 1; + } + if(val == falseString) { + return -1; + } + val = detail::to_lower(val); + std::int64_t ret = 0; + if(val.size() == 1) { + if(val[0] >= '1' && val[0] <= '9') { + return (static_cast(val[0]) - '0'); + } + switch(val[0]) { + case '0': + case 'f': + case 'n': + case '-': + ret = -1; + break; + case 't': + case 'y': + case '+': + ret = 1; + break; + default: + errno = EINVAL; + return -1; + } + return ret; + } + if(val == trueString || val == "on" || val == "yes" || val == "enable") { + ret = 1; + } else if(val == falseString || val == "off" || val == "no" || val == "disable") { + ret = -1; + } else { + char *loc_ptr{nullptr}; + ret = std::strtoll(val.c_str(), &loc_ptr, 0); + if(loc_ptr != (val.c_str() + val.size()) && errno == 0) { + errno = EINVAL; + } + } + return ret; +} + +/// Integer conversion +template ::value == object_category::integral_value || + classify_object::value == object_category::unsigned_integral, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + return integral_conversion(input, output); +} + +/// char values +template ::value == object_category::char_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + if(input.size() == 1) { + output = static_cast(input[0]); + return true; + } + return integral_conversion(input, output); +} + +/// Boolean values +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + errno = 0; + auto out = to_flag_value(input); + if(errno == 0) { + output = (out > 0); + } else if(errno == ERANGE) { + output = (input[0] != '-'); + } else { + return false; + } + return true; +} + +/// Floats +template ::value == object_category::floating_point, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + if(input.empty()) { + return false; + } + char *val = nullptr; + auto output_ld = std::strtold(input.c_str(), &val); + output = static_cast(output_ld); + if(val == (input.c_str() + input.size())) { + return true; + } + while(std::isspace(static_cast(*val))) { + ++val; + if(val == (input.c_str() + input.size())) { + return true; + } + } + + // remove separators + if(input.find_first_of("_'") != std::string::npos) { + std::string nstring = input; + nstring.erase(std::remove(nstring.begin(), nstring.end(), '_'), nstring.end()); + nstring.erase(std::remove(nstring.begin(), nstring.end(), '\''), nstring.end()); + return lexical_cast(nstring, output); + } + return false; +} + +/// complex +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + using XC = typename wrapped_type::type; + XC x{0.0}, y{0.0}; + auto str1 = input; + bool worked = false; + auto nloc = str1.find_last_of("+-"); + if(nloc != std::string::npos && nloc > 0) { + worked = lexical_cast(str1.substr(0, nloc), x); + str1 = str1.substr(nloc); + if(str1.back() == 'i' || str1.back() == 'j') + str1.pop_back(); + worked = worked && lexical_cast(str1, y); + } else { + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + worked = lexical_cast(str1, y); + x = XC{0}; + } else { + worked = lexical_cast(str1, x); + y = XC{0}; + } + } + if(worked) { + output = T{x, y}; + return worked; + } + return from_stream(input, output); +} + +/// String and similar direct assignment +template ::value == object_category::string_assignable, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = input; + return true; +} + +/// String and similar constructible and copy assignment +template < + typename T, + enable_if_t::value == object_category::string_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = T(input); + return true; +} + +/// Wide strings +template < + typename T, + enable_if_t::value == object_category::wstring_assignable, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = widen(input); + return true; +} + +template < + typename T, + enable_if_t::value == object_category::wstring_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = T{widen(input)}; + return true; +} + +/// Enumerations +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename std::underlying_type::type val; + if(!integral_conversion(input, val)) { + return false; + } + output = static_cast(val); + return true; +} + +/// wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = val; + return true; + } + return from_stream(input, output); +} + +template ::value == object_category::wrapper_value && + !std::is_assignable::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + +/// Assignable from double or int +template < + typename T, + enable_if_t::value == object_category::number_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { + output = T(val); + return true; + } + + double dval = 0.0; + if(lexical_cast(input, dval)) { + output = T{dval}; + return true; + } + + return from_stream(input, output); +} + +/// Assignable from int +template < + typename T, + enable_if_t::value == object_category::integer_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { + output = T(val); + return true; + } + return from_stream(input, output); +} + +/// Assignable from double +template < + typename T, + enable_if_t::value == object_category::double_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + double val = 0.0; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + +/// Non-string convertible from an int +template ::value == object_category::other && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4800) +#endif + // with Atomic this could produce a warning due to the conversion but if atomic gets here it is an old style + // so will most likely still work + output = val; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + return true; + } + // LCOV_EXCL_START + // This version of cast is only used for odd cases in an older compilers the fail over + // from_stream is tested elsewhere an not relevant for coverage here + return from_stream(input, output); + // LCOV_EXCL_STOP +} + +/// Non-string parsable by a stream +template ::value == object_category::other && !std::is_assignable::value && + is_istreamable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + return from_stream(input, output); +} + +/// Fallback overload that prints a human-readable error for types that we don't recognize and that don't have a +/// user-supplied lexical_cast overload. +template ::value == object_category::other && !std::is_assignable::value && + !is_istreamable::value && !adl_detail::is_lexical_castable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string & /*input*/, T & /*output*/) { + static_assert(!std::is_same::value, // Can't just write false here. + "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it " + "is convertible from another type use the add_option(...) with XC being the known type"); + return false; +} + +/// Assign a value through lexical cast operations +/// Strings can be empty so we need to do a little different +template ::value && + (classify_object::value == object_category::string_assignable || + classify_object::value == object_category::string_constructible || + classify_object::value == object_category::wstring_assignable || + classify_object::value == object_category::wstring_constructible), + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations +template ::value && std::is_assignable::value && + classify_object::value != object_category::string_assignable && + classify_object::value != object_category::string_constructible && + classify_object::value != object_category::wstring_assignable && + classify_object::value != object_category::wstring_constructible, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + output = AssignTo{}; + return true; + } + + return lexical_cast(input, output); +} // LCOV_EXCL_LINE + +/// Assign a value through lexical cast operations +template ::value && !std::is_assignable::value && + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + typename AssignTo::value_type emptyVal{}; + output = emptyVal; + return true; + } + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations for int compatible values +/// mainly for atomic operations on some compilers +template ::value && !std::is_assignable::value && + classify_object::value != object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + output = 0; + return true; + } + int val{0}; + if(lexical_cast(input, val)) { +#if defined(__clang__) +/* on some older clang compilers */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#endif + output = val; +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + return true; + } + return false; +} + +/// Assign a value converted from a string in lexical cast to the output value directly +template ::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; + if(parse_result) { + output = val; + } + return parse_result; +} + +/// Assign a value from a lexical cast through constructing a value and move assigning it +template < + typename AssignTo, + typename ConvertTo, + enable_if_t::value && !std::is_assignable::value && + std::is_move_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = input.empty() ? true : lexical_cast(input, val); + if(parse_result) { + output = AssignTo(val); // use () form of constructor to allow some implicit conversions + } + return parse_result; +} + +/// primary lexical conversion operation, 1 string to 1 type of some kind +template ::value <= object_category::other && + classify_object::value <= object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + return lexical_assign(strings[0], output); +} + +/// Lexical conversion if there is only one element but the conversion type is for two, then call a two element +/// constructor +template ::value <= 2) && expected_count::value == 1 && + is_tuple_like::value && type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + // the remove const is to handle pair types coming from a container + using FirstType = typename std::remove_const::type>::type; + using SecondType = typename std::tuple_element<1, ConvertTo>::type; + FirstType v1; + SecondType v2; + bool retval = lexical_assign(strings[0], v1); + retval = retval && lexical_assign((strings.size() > 1) ? strings[1] : std::string{}, v2); + if(retval) { + output = AssignTo{v1, v2}; + } + return retval; +} + +/// Lexical conversion of a container types of single elements +template ::value && is_mutable_container::value && + type_count::value == 1, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + output.erase(output.begin(), output.end()); + if(strings.empty()) { + return true; + } + if(strings.size() == 1 && strings[0] == "{}") { + return true; + } + bool skip_remaining = false; + if(strings.size() == 2 && strings[0] == "{}" && is_separator(strings[1])) { + skip_remaining = true; + } + for(const auto &elem : strings) { + typename AssignTo::value_type out; + bool retval = lexical_assign(elem, out); + if(!retval) { + return false; + } + output.insert(output.end(), std::move(out)); + if(skip_remaining) { + break; + } + } + return (!output.empty()); +} + +/// Lexical conversion for complex types +template ::value, detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() >= 2 && !strings[1].empty()) { + using XC2 = typename wrapped_type::type; + XC2 x{0.0}, y{0.0}; + auto str1 = strings[1]; + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + } + auto worked = lexical_cast(strings[0], x) && lexical_cast(str1, y); + if(worked) { + output = ConvertTo{x, y}; + } + return worked; + } + return lexical_assign(strings[0], output); +} + +/// Conversion to a vector type using a particular single type as the conversion type +template ::value && (expected_count::value == 1) && + (type_count::value == 1), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + bool retval = true; + output.clear(); + output.reserve(strings.size()); + for(const auto &elem : strings) { + + output.emplace_back(); + retval = retval && lexical_assign(elem, output.back()); + } + return (!output.empty()) && retval; +} + +// forward declaration + +/// Lexical conversion of a container types with conversion type of two elements +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(std::vector strings, AssignTo &output); + +/// Lexical conversion of a vector types with type_size >2 forward declaration +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); + +/// Conversion for tuples +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); // forward declaration + +/// Conversion for operations where the assigned type is some class but the conversion is a mutable container or large +/// tuple +template ::value && !is_mutable_container::value && + classify_object::value != object_category::wrapper_value && + (is_mutable_container::value || type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { + ConvertTo val; + auto retval = lexical_conversion(strings, val); + output = AssignTo{val}; + return retval; + } + output = AssignTo{}; + return true; +} + +/// function template for converting tuples if the static Index is greater than the tuple size +template +inline typename std::enable_if<(I >= type_count_base::value), bool>::type +tuple_conversion(const std::vector &, AssignTo &) { + return true; +} + +/// Conversion of a tuple element where the type size ==1 and not a mutable container +template +inline typename std::enable_if::value && type_count::value == 1, bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_assign(strings[0], output); + strings.erase(strings.begin()); + return retval; +} + +/// Conversion of a tuple element where the type size !=1 but the size is fixed and not a mutable container +template +inline typename std::enable_if::value && (type_count::value > 1) && + type_count::value == type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_conversion(strings, output); + strings.erase(strings.begin(), strings.begin() + type_count::value); + return retval; +} + +/// Conversion of a tuple element where the type is a mutable container or a type with different min and max type sizes +template +inline typename std::enable_if::value || + type_count::value != type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + + std::size_t index{subtype_count_min::value}; + const std::size_t mx_count{subtype_count::value}; + const std::size_t mx{(std::min)(mx_count, strings.size() - 1)}; + + while(index < mx) { + if(is_separator(strings[index])) { + break; + } + ++index; + } + bool retval = lexical_conversion( + std::vector(strings.begin(), strings.begin() + static_cast(index)), output); + if(strings.size() > index) { + strings.erase(strings.begin(), strings.begin() + static_cast(index) + 1); + } else { + strings.clear(); + } + return retval; +} + +/// Tuple conversion operation +template +inline typename std::enable_if<(I < type_count_base::value), bool>::type +tuple_conversion(std::vector strings, AssignTo &output) { + bool retval = true; + using ConvertToElement = typename std:: + conditional::value, typename std::tuple_element::type, ConvertTo>::type; + if(!strings.empty()) { + retval = retval && tuple_type_conversion::type, ConvertToElement>( + strings, std::get(output)); + } + retval = retval && tuple_conversion(std::move(strings), output); + return retval; +} + +/// Lexical conversion of a container types with tuple elements of size 2 +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler>> +bool lexical_conversion(std::vector strings, AssignTo &output) { + output.clear(); + while(!strings.empty()) { + + typename std::remove_const::type>::type v1; + typename std::tuple_element<1, typename ConvertTo::value_type>::type v2; + bool retval = tuple_type_conversion(strings, v1); + if(!strings.empty()) { + retval = retval && tuple_type_conversion(strings, v2); + } + if(retval) { + output.insert(output.end(), typename AssignTo::value_type{v1, v2}); + } else { + return false; + } + } + return (!output.empty()); +} + +/// lexical conversion of tuples with type count>2 or tuples of types of some element with a type size>=2 +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + static_assert( + !is_tuple_like::value || type_count_base::value == type_count_base::value, + "if the conversion type is defined as a tuple it must be the same size as the type you are converting to"); + return tuple_conversion(strings, output); +} + +/// Lexical conversion of a vector types for everything but tuples of two elements and types of size 1 +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + bool retval = true; + output.clear(); + std::vector temp; + std::size_t ii{0}; + std::size_t icount{0}; + std::size_t xcm{type_count::value}; + auto ii_max = strings.size(); + while(ii < ii_max) { + temp.push_back(strings[ii]); + ++ii; + ++icount; + if(icount == xcm || is_separator(temp.back()) || ii == ii_max) { + if(static_cast(xcm) > type_count_min::value && is_separator(temp.back())) { + temp.pop_back(); + } + typename AssignTo::value_type temp_out; + retval = retval && + lexical_conversion(temp, temp_out); + temp.clear(); + if(!retval) { + return false; + } + output.insert(output.end(), std::move(temp_out)); + icount = 0; + } + } + return retval; +} + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + if(strings.empty() || strings.front().empty()) { + output = ConvertTo{}; + return true; + } + typename ConvertTo::value_type val; + if(lexical_conversion(strings, val)) { + output = ConvertTo{val}; + return true; + } + return false; +} + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + !std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + using ConvertType = typename ConvertTo::value_type; + if(strings.empty() || strings.front().empty()) { + output = ConvertType{}; + return true; + } + ConvertType val; + if(lexical_conversion(strings, val)) { + output = val; + return true; + } + return false; +} + +/// Sum a vector of strings +inline std::string sum_string_vector(const std::vector &values) { + double val{0.0}; + bool fail{false}; + std::string output; + for(const auto &arg : values) { + double tv{0.0}; + auto comp = lexical_cast(arg, tv); + if(!comp) { + errno = 0; + auto fv = detail::to_flag_value(arg); + fail = (errno != 0); + if(fail) { + break; + } + tv = static_cast(fv); + } + val += tv; + } + if(fail) { + for(const auto &arg : values) { + output.append(arg); + } + } else { + std::ostringstream out; + out.precision(16); + out << val; + output = out.str(); + } + return output; +} + +} // namespace detail + + + +namespace detail { + +// Returns false if not a short option. Otherwise, sets opt name and rest and returns true +CLI11_INLINE bool split_short(const std::string ¤t, std::string &name, std::string &rest); + +// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true +CLI11_INLINE bool split_long(const std::string ¤t, std::string &name, std::string &value); + +// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true +CLI11_INLINE bool split_windows_style(const std::string ¤t, std::string &name, std::string &value); + +// Splits a string into multiple long and short names +CLI11_INLINE std::vector split_names(std::string current); + +/// extract default flag values either {def} or starting with a ! +CLI11_INLINE std::vector> get_default_flag_values(const std::string &str); + +/// Get a vector of short names, one of long names, and a single name +CLI11_INLINE std::tuple, std::vector, std::string> +get_names(const std::vector &input, bool allow_non_standard = false); + +} // namespace detail + + + +namespace detail { + +CLI11_INLINE bool split_short(const std::string ¤t, std::string &name, std::string &rest) { + if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { + name = current.substr(1, 1); + rest = current.substr(2); + return true; + } + return false; +} + +CLI11_INLINE bool split_long(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 2 && current.compare(0, 2, "--") == 0 && valid_first_char(current[2])) { + auto loc = current.find_first_of('='); + if(loc != std::string::npos) { + name = current.substr(2, loc - 2); + value = current.substr(loc + 1); + } else { + name = current.substr(2); + value = ""; + } + return true; + } + return false; +} + +CLI11_INLINE bool split_windows_style(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) { + auto loc = current.find_first_of(':'); + if(loc != std::string::npos) { + name = current.substr(1, loc - 1); + value = current.substr(loc + 1); + } else { + name = current.substr(1); + value = ""; + } + return true; + } + return false; +} + +CLI11_INLINE std::vector split_names(std::string current) { + std::vector output; + std::size_t val = 0; + while((val = current.find(',')) != std::string::npos) { + output.push_back(trim_copy(current.substr(0, val))); + current = current.substr(val + 1); + } + output.push_back(trim_copy(current)); + return output; +} + +CLI11_INLINE std::vector> get_default_flag_values(const std::string &str) { + std::vector flags = split_names(str); + flags.erase(std::remove_if(flags.begin(), + flags.end(), + [](const std::string &name) { + return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) && + (name.back() == '}')) || + (name[0] == '!')))); + }), + flags.end()); + std::vector> output; + output.reserve(flags.size()); + for(auto &flag : flags) { + auto def_start = flag.find_first_of('{'); + std::string defval = "false"; + if((def_start != std::string::npos) && (flag.back() == '}')) { + defval = flag.substr(def_start + 1); + defval.pop_back(); + flag.erase(def_start, std::string::npos); // NOLINT(readability-suspicious-call-argument) + } + flag.erase(0, flag.find_first_not_of("-!")); + output.emplace_back(flag, defval); + } + return output; +} + +CLI11_INLINE std::tuple, std::vector, std::string> +get_names(const std::vector &input, bool allow_non_standard) { + + std::vector short_names; + std::vector long_names; + std::string pos_name; + for(std::string name : input) { + if(name.length() == 0) { + continue; + } + if(name.length() > 1 && name[0] == '-' && name[1] != '-') { + if(name.length() == 2 && valid_first_char(name[1])) { + short_names.emplace_back(1, name[1]); + } else if(name.length() > 2) { + if(allow_non_standard) { + name = name.substr(1); + if(valid_name_string(name)) { + short_names.push_back(name); + } else { + throw BadNameString::BadLongName(name); + } + } else { + throw BadNameString::MissingDash(name); + } + } else { + throw BadNameString::OneCharName(name); + } + } else if(name.length() > 2 && name.substr(0, 2) == "--") { + name = name.substr(2); + if(valid_name_string(name)) { + long_names.push_back(name); + } else { + throw BadNameString::BadLongName(name); + } + } else if(name == "-" || name == "--" || name == "++") { + throw BadNameString::ReservedName(name); + } else { + if(!pos_name.empty()) { + throw BadNameString::MultiPositionalNames(name); + } + if(valid_name_string(name)) { + pos_name = name; + } else { + throw BadNameString::BadPositionalName(name); + } + } + } + return std::make_tuple(short_names, long_names, pos_name); +} + +} // namespace detail + + + +class App; + +/// Holds values to load into Options +struct ConfigItem { + /// This is the list of parents + std::vector parents{}; + + /// This is the name + std::string name{}; + /// Listing of inputs + std::vector inputs{}; + /// @brief indicator if a multiline vector separator was inserted + bool multiline{false}; + /// The list of parents and name joined by "." + CLI11_NODISCARD std::string fullname() const { + std::vector tmp = parents; + tmp.emplace_back(name); + return detail::join(tmp, "."); + (void)multiline; // suppression for cppcheck false positive + } +}; + +/// This class provides a converter for configuration files. +class Config { + protected: + std::vector items{}; + + public: + /// Convert an app into a configuration + virtual std::string to_config(const App *, bool, bool, std::string) const = 0; + + /// Convert a configuration into an app + virtual std::vector from_config(std::istream &) const = 0; + + /// Get a flag value + CLI11_NODISCARD virtual std::string to_flag(const ConfigItem &item) const { + if(item.inputs.size() == 1) { + return item.inputs.at(0); + } + if(item.inputs.empty()) { + return "{}"; + } + throw ConversionError::TooManyInputsFlag(item.fullname()); // LCOV_EXCL_LINE + } + + /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure + CLI11_NODISCARD std::vector from_file(const std::string &name) const { + std::ifstream input{name}; + if(!input.good()) + throw FileError::Missing(name); + + return from_config(input); + } + + /// Virtual destructor + virtual ~Config() = default; +}; + +/// This converter works with INI/TOML files; to write INI files use ConfigINI +class ConfigBase : public Config { + protected: + /// the character used for comments + char commentChar = '#'; + /// the character used to start an array '\0' is a default to not use + char arrayStart = '['; + /// the character used to end an array '\0' is a default to not use + char arrayEnd = ']'; + /// the character used to separate elements in an array + char arraySeparator = ','; + /// the character used separate the name from the value + char valueDelimiter = '='; + /// the character to use around strings + char stringQuote = '"'; + /// the character to use around single characters and literal strings + char literalQuote = '\''; + /// the maximum number of layers to allow + uint8_t maximumLayers{255}; + /// the separator used to separator parent layers + char parentSeparatorChar{'.'}; + /// comment default values + bool commentDefaultsBool = false; + /// specify the config reader should collapse repeated field names to a single vector + bool allowMultipleDuplicateFields{false}; + /// Specify the configuration index to use for arrayed sections + int16_t configIndex{-1}; + /// Specify the configuration section that should be used + std::string configSection{}; + + public: + std::string + to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override; + + std::vector from_config(std::istream &input) const override; + /// Specify the configuration for comment characters + ConfigBase *comment(char cchar) { + commentChar = cchar; + return this; + } + /// Specify the start and end characters for an array + ConfigBase *arrayBounds(char aStart, char aEnd) { + arrayStart = aStart; + arrayEnd = aEnd; + return this; + } + /// Specify the delimiter character for an array + ConfigBase *arrayDelimiter(char aSep) { + arraySeparator = aSep; + return this; + } + /// Specify the delimiter between a name and value + ConfigBase *valueSeparator(char vSep) { + valueDelimiter = vSep; + return this; + } + /// Specify the quote characters used around strings and literal strings + ConfigBase *quoteCharacter(char qString, char literalChar) { + stringQuote = qString; + literalQuote = literalChar; + return this; + } + /// Specify the maximum number of parents + ConfigBase *maxLayers(uint8_t layers) { + maximumLayers = layers; + return this; + } + /// Specify the separator to use for parent layers + ConfigBase *parentSeparator(char sep) { + parentSeparatorChar = sep; + return this; + } + /// comment default value options + ConfigBase *commentDefaults(bool comDef = true) { + commentDefaultsBool = comDef; + return this; + } + /// get a reference to the configuration section + std::string §ionRef() { return configSection; } + /// get the section + CLI11_NODISCARD const std::string §ion() const { return configSection; } + /// specify a particular section of the configuration file to use + ConfigBase *section(const std::string §ionName) { + configSection = sectionName; + return this; + } + + /// get a reference to the configuration index + int16_t &indexRef() { return configIndex; } + /// get the section index + CLI11_NODISCARD int16_t index() const { return configIndex; } + /// specify a particular index in the section to use (-1) for all sections to use + ConfigBase *index(int16_t sectionIndex) { + configIndex = sectionIndex; + return this; + } + /// specify that multiple duplicate arguments should be merged even if not sequential + ConfigBase *allowDuplicateFields(bool value = true) { + allowMultipleDuplicateFields = value; + return this; + } +}; + +/// the default Config is the TOML file format +using ConfigTOML = ConfigBase; + +/// ConfigINI generates a "standard" INI compliant output +class ConfigINI : public ConfigTOML { + + public: + ConfigINI() { + commentChar = ';'; + arrayStart = '\0'; + arrayEnd = '\0'; + arraySeparator = ' '; + valueDelimiter = '='; + } +}; + + + +class Option; + +/// @defgroup validator_group Validators + +/// @brief Some validators that are provided +/// +/// These are simple `std::string(const std::string&)` validators that are useful. They return +/// a string if the validation fails. A custom struct is provided, as well, with the same user +/// semantics, but with the ability to provide a new type name. +/// @{ + +/// +class Validator { + protected: + /// This is the description function, if empty the description_ will be used + std::function desc_function_{[]() { return std::string{}; }}; + + /// This is the base function that is to be called. + /// Returns a string error message if validation fails. + std::function func_{[](std::string &) { return std::string{}; }}; + /// The name for search purposes of the Validator + std::string name_{}; + /// A Validator will only apply to an indexed value (-1 is all elements) + int application_index_ = -1; + /// Enable for Validator to allow it to be disabled if need be + bool active_{true}; + /// specify that a validator should not modify the input + bool non_modifying_{false}; + + Validator(std::string validator_desc, std::function func) + : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {} + + public: + Validator() = default; + /// Construct a Validator with just the description string + explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {} + /// Construct Validator from basic information + Validator(std::function op, std::string validator_desc, std::string validator_name = "") + : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)), + name_(std::move(validator_name)) {} + /// Set the Validator operation function + Validator &operation(std::function op) { + func_ = std::move(op); + return *this; + } + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(std::string &str) const; + + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(const std::string &str) const { + std::string value = str; + return (active_) ? func_(value) : std::string{}; + } + + /// Specify the type string + Validator &description(std::string validator_desc) { + desc_function_ = [validator_desc]() { return validator_desc; }; + return *this; + } + /// Specify the type string + CLI11_NODISCARD Validator description(std::string validator_desc) const; + + /// Generate type description information for the Validator + CLI11_NODISCARD std::string get_description() const { + if(active_) { + return desc_function_(); + } + return std::string{}; + } + /// Specify the type string + Validator &name(std::string validator_name) { + name_ = std::move(validator_name); + return *this; + } + /// Specify the type string + CLI11_NODISCARD Validator name(std::string validator_name) const { + Validator newval(*this); + newval.name_ = std::move(validator_name); + return newval; + } + /// Get the name of the Validator + CLI11_NODISCARD const std::string &get_name() const { return name_; } + /// Specify whether the Validator is active or not + Validator &active(bool active_val = true) { + active_ = active_val; + return *this; + } + /// Specify whether the Validator is active or not + CLI11_NODISCARD Validator active(bool active_val = true) const { + Validator newval(*this); + newval.active_ = active_val; + return newval; + } + + /// Specify whether the Validator can be modifying or not + Validator &non_modifying(bool no_modify = true) { + non_modifying_ = no_modify; + return *this; + } + /// Specify the application index of a validator + Validator &application_index(int app_index) { + application_index_ = app_index; + return *this; + } + /// Specify the application index of a validator + CLI11_NODISCARD Validator application_index(int app_index) const { + Validator newval(*this); + newval.application_index_ = app_index; + return newval; + } + /// Get the current value of the application index + CLI11_NODISCARD int get_application_index() const { return application_index_; } + /// Get a boolean if the validator is active + CLI11_NODISCARD bool get_active() const { return active_; } + + /// Get a boolean if the validator is allowed to modify the input returns true if it can modify the input + CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; } + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator&(const Validator &other) const; + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator|(const Validator &other) const; + + /// Create a validator that fails when a given validator succeeds + Validator operator!() const; + + private: + void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger); +}; + +/// Class wrapping some of the accessors of Validator +class CustomValidator : public Validator { + public: +}; +// The implementation of the built in validators is using the Validator class; +// the user is only expected to use the const (static) versions (since there's no setup). +// Therefore, this is in detail. +namespace detail { + +/// CLI enumeration of different file types +enum class path_type { nonexistent, file, directory }; + +/// get the type of the path from a file name +CLI11_INLINE path_type check_path(const char *file) noexcept; + +/// Check for an existing file (returns error message if check fails) +class ExistingFileValidator : public Validator { + public: + ExistingFileValidator(); +}; + +/// Check for an existing directory (returns error message if check fails) +class ExistingDirectoryValidator : public Validator { + public: + ExistingDirectoryValidator(); +}; + +/// Check for an existing path +class ExistingPathValidator : public Validator { + public: + ExistingPathValidator(); +}; + +/// Check for an non-existing path +class NonexistentPathValidator : public Validator { + public: + NonexistentPathValidator(); +}; + +/// Validate the given string is a legal ipv4 address +class IPV4Validator : public Validator { + public: + IPV4Validator(); +}; + +class EscapedStringTransformer : public Validator { + public: + EscapedStringTransformer(); +}; + +} // namespace detail + +// Static is not needed here, because global const implies static. + +/// Check for existing file (returns error message if check fails) +const detail::ExistingFileValidator ExistingFile; + +/// Check for an existing directory (returns error message if check fails) +const detail::ExistingDirectoryValidator ExistingDirectory; + +/// Check for an existing path +const detail::ExistingPathValidator ExistingPath; + +/// Check for an non-existing path +const detail::NonexistentPathValidator NonexistentPath; + +/// Check for an IP4 address +const detail::IPV4Validator ValidIPV4; + +/// convert escaped characters into their associated values +const detail::EscapedStringTransformer EscapedString; + +/// Validate the input as a particular type +template class TypeValidator : public Validator { + public: + explicit TypeValidator(const std::string &validator_name) + : Validator(validator_name, [](std::string &input_string) { + using CLI::detail::lexical_cast; + auto val = DesiredType(); + if(!lexical_cast(input_string, val)) { + return std::string("Failed parsing ") + input_string + " as a " + detail::type_name(); + } + return std::string(); + }) {} + TypeValidator() : TypeValidator(detail::type_name()) {} +}; + +/// Check for a number +const TypeValidator Number("NUMBER"); + +/// Modify a path if the file is a particular default location, can be used as Check or transform +/// with the error return optionally disabled +class FileOnDefaultPath : public Validator { + public: + explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true); +}; + +/// Produce a range (factory). Min and max are inclusive. +class Range : public Validator { + public: + /// This produces a range with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template + Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) { + if(validator_name.empty()) { + std::stringstream out; + out << detail::type_name() << " in [" << min_val << " - " << max_val << "]"; + description(out.str()); + } + + func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; + T val; + bool converted = lexical_cast(input, val); + if((!converted) || (val < min_val || val > max_val)) { + std::stringstream out; + out << "Value " << input << " not in range ["; + out << min_val << " - " << max_val << "]"; + return out.str(); + } + return std::string{}; + }; + } + + /// Range of one value is 0 to value + template + explicit Range(T max_val, const std::string &validator_name = std::string{}) + : Range(static_cast(0), max_val, validator_name) {} +}; + +/// Check for a non negative number +const Range NonNegativeNumber((std::numeric_limits::max)(), "NONNEGATIVE"); + +/// Check for a positive valued number (val>0.0), ::min here is the smallest positive number +const Range PositiveNumber((std::numeric_limits::min)(), (std::numeric_limits::max)(), "POSITIVE"); + +/// Produce a bounded range (factory). Min and max are inclusive. +class Bound : public Validator { + public: + /// This bounds a value with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template Bound(T min_val, T max_val) { + std::stringstream out; + out << detail::type_name() << " bounded to [" << min_val << " - " << max_val << "]"; + description(out.str()); + + func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; + T val; + bool converted = lexical_cast(input, val); + if(!converted) { + return std::string("Value ") + input + " could not be converted"; + } + if(val < min_val) + input = detail::to_string(min_val); + else if(val > max_val) + input = detail::to_string(max_val); + + return std::string{}; + }; + } + + /// Range of one value is 0 to value + template explicit Bound(T max_val) : Bound(static_cast(0), max_val) {} +}; + +namespace detail { +template ::type>::value, detail::enabler> = detail::dummy> +auto smart_deref(T value) -> decltype(*value) { + return *value; +} + +template < + typename T, + enable_if_t::type>::value, detail::enabler> = detail::dummy> +typename std::remove_reference::type &smart_deref(T &value) { + return value; +} +/// Generate a string representation of a set +template std::string generate_set(const T &set) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(set), + [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, + ",")); + out.push_back('}'); + return out; +} + +/// Generate a string representation of a map +template std::string generate_map(const T &map, bool key_only = false) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(map), + [key_only](const iteration_type_t &v) { + std::string res{detail::to_string(detail::pair_adaptor::first(v))}; + + if(!key_only) { + res.append("->"); + res += detail::to_string(detail::pair_adaptor::second(v)); + } + return res; + }, + ",")); + out.push_back('}'); + return out; +} + +template struct has_find { + template + static auto test(int) -> decltype(std::declval().find(std::declval()), std::true_type()); + template static auto test(...) -> decltype(std::false_type()); + + static const auto value = decltype(test(0))::value; + using type = std::integral_constant; +}; + +/// A search function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + using element_t = typename detail::element_type::type; + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) { + return (detail::pair_adaptor::first(v) == val); + }); + return {(it != std::end(setref)), it}; +} + +/// A search function that uses the built in find function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + auto &setref = detail::smart_deref(set); + auto it = setref.find(val); + return {(it != std::end(setref)), it}; +} + +/// A search function with a filter function +template +auto search(const T &set, const V &val, const std::function &filter_function) + -> std::pair { + using element_t = typename detail::element_type::type; + // do the potentially faster first search + auto res = search(set, val); + if((res.first) || (!(filter_function))) { + return res; + } + // if we haven't found it do the longer linear search with all the element translations + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) { + V a{detail::pair_adaptor::first(v)}; + a = filter_function(a); + return (a == val); + }); + return {(it != std::end(setref)), it}; +} + +// the following suggestion was made by Nikita Ofitserov(@himikof) +// done in templates to prevent compiler warnings on negation of unsigned numbers + +/// Do a check for overflow on signed numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + if((a > 0) == (b > 0)) { + return ((std::numeric_limits::max)() / (std::abs)(a) < (std::abs)(b)); + } + return ((std::numeric_limits::min)() / (std::abs)(a) > -(std::abs)(b)); +} +/// Do a check for overflow on unsigned numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + return ((std::numeric_limits::max)() / a < b); +} + +/// Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise. +template typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + if(a == 0 || b == 0 || a == 1 || b == 1) { + a *= b; + return true; + } + if(a == (std::numeric_limits::min)() || b == (std::numeric_limits::min)()) { + return false; + } + if(overflowCheck(a, b)) { + return false; + } + a *= b; + return true; +} + +/// Performs a *= b; if it doesn't equal infinity. Returns false otherwise. +template +typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + T c = a * b; + if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) { + return false; + } + a = c; + return true; +} + +} // namespace detail +/// Verify items are in a set +class IsMember : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction using an initializer list + template + IsMember(std::initializer_list values, Args &&...args) + : IsMember(std::vector(values), std::forward(args)...) {} + + /// This checks to see if an item is in a set (empty function) + template explicit IsMember(T &&set) : IsMember(std::forward(set), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit IsMember(T set, F filter_function) { + + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + + using local_item_t = typename IsMemberType::type; // This will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); }; + + // This is the function that validates + // It stores a copy of the set pointer-like, so shared_ptr will stay alive + func_ = [set, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + if(!lexical_cast(input, b)) { + throw ValidationError(input); // name is added later + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(set, b, filter_fn); + if(res.first) { + // Make sure the version in the input string is identical to the one in the set + if(filter_fn) { + input = detail::value_string(detail::pair_adaptor::first(*(res.second))); + } + + // Return empty error string (success) + return std::string{}; + } + + // If you reach this point, the result was not found + return input + " not in " + detail::generate_set(detail::smart_deref(set)); + }; + } + + /// You can pass in as many filter functions as you like, they nest (string only currently) + template + IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : IsMember( + std::forward(set), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// definition of the default transformation object +template using TransformPairs = std::vector>; + +/// Translate named items to other or a value set +class Transformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + Transformer(std::initializer_list> values, Args &&...args) + : Transformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit Transformer(T &&mapping) : Transformer(std::forward(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit Transformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); }; + + func_ = [mapping, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + if(!lexical_cast(input, b)) { + return std::string(); + // there is no possible way we can match anything in the mapping if we can't convert so just return + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + } + return std::string{}; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : Transformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// translate named items to other or a value set +class CheckedTransformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + CheckedTransformer(std::initializer_list> values, Args &&...args) + : CheckedTransformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit CheckedTransformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + auto tfunc = [mapping]() { + std::string out("value in "); + out += detail::generate_map(detail::smart_deref(mapping)) + " OR {"; + out += detail::join( + detail::smart_deref(mapping), + [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor::second(v)); }, + ","); + out.push_back('}'); + return out; + }; + + desc_function_ = tfunc; + + func_ = [mapping, tfunc, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + bool converted = lexical_cast(input, b); + if(converted) { + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + return std::string{}; + } + } + for(const auto &v : detail::smart_deref(mapping)) { + auto output_string = detail::value_string(detail::pair_adaptor::second(v)); + if(output_string == input) { + return std::string(); + } + } + + return "Check " + input + " " + tfunc() + " FAILED"; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : CheckedTransformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// Helper function to allow ignore_case to be passed to IsMember or Transform +inline std::string ignore_case(std::string item) { return detail::to_lower(item); } + +/// Helper function to allow ignore_underscore to be passed to IsMember or Transform +inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); } + +/// Helper function to allow checks to ignore spaces to be passed to IsMember or Transform +inline std::string ignore_space(std::string item) { + item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item)); + item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item)); + return item; +} + +/// Multiply a number by a factor using given mapping. +/// Can be used to write transforms for SIZE or DURATION inputs. +/// +/// Example: +/// With mapping = `{"b"->1, "kb"->1024, "mb"->1024*1024}` +/// one can recognize inputs like "100", "12kb", "100 MB", +/// that will be automatically transformed to 100, 14448, 104857600. +/// +/// Output number type matches the type in the provided mapping. +/// Therefore, if it is required to interpret real inputs like "0.42 s", +/// the mapping should be of a type or . +class AsNumberWithUnit : public Validator { + public: + /// Adjust AsNumberWithUnit behavior. + /// CASE_SENSITIVE/CASE_INSENSITIVE controls how units are matched. + /// UNIT_OPTIONAL/UNIT_REQUIRED throws ValidationError + /// if UNIT_REQUIRED is set and unit literal is not found. + enum Options { + CASE_SENSITIVE = 0, + CASE_INSENSITIVE = 1, + UNIT_OPTIONAL = 0, + UNIT_REQUIRED = 2, + DEFAULT = CASE_INSENSITIVE | UNIT_OPTIONAL + }; + + template + explicit AsNumberWithUnit(std::map mapping, + Options opts = DEFAULT, + const std::string &unit_name = "UNIT") { + description(generate_description(unit_name, opts)); + validate_mapping(mapping, opts); + + // transform function + func_ = [mapping, opts](std::string &input) -> std::string { + Number num{}; + + detail::rtrim(input); + if(input.empty()) { + throw ValidationError("Input is empty"); + } + + // Find split position between number and prefix + auto unit_begin = input.end(); + while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) { + --unit_begin; + } + + std::string unit{unit_begin, input.end()}; + input.resize(static_cast(std::distance(input.begin(), unit_begin))); + detail::trim(input); + + if(opts & UNIT_REQUIRED && unit.empty()) { + throw ValidationError("Missing mandatory unit"); + } + if(opts & CASE_INSENSITIVE) { + unit = detail::to_lower(unit); + } + if(unit.empty()) { + using CLI::detail::lexical_cast; + if(!lexical_cast(input, num)) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + // No need to modify input if no unit passed + return {}; + } + + // find corresponding factor + auto it = mapping.find(unit); + if(it == mapping.end()) { + throw ValidationError(unit + + " unit not recognized. " + "Allowed values: " + + detail::generate_map(mapping, true)); + } + + if(!input.empty()) { + using CLI::detail::lexical_cast; + bool converted = lexical_cast(input, num); + if(!converted) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + // perform safe multiplication + bool ok = detail::checked_multiply(num, it->second); + if(!ok) { + throw ValidationError(detail::to_string(num) + " multiplied by " + unit + + " factor would cause number overflow. Use smaller value."); + } + } else { + num = static_cast(it->second); + } + + input = detail::to_string(num); + + return {}; + }; + } + + private: + /// Check that mapping contains valid units. + /// Update mapping for CASE_INSENSITIVE mode. + template static void validate_mapping(std::map &mapping, Options opts) { + for(auto &kv : mapping) { + if(kv.first.empty()) { + throw ValidationError("Unit must not be empty."); + } + if(!detail::isalpha(kv.first)) { + throw ValidationError("Unit must contain only letters."); + } + } + + // make all units lowercase if CASE_INSENSITIVE + if(opts & CASE_INSENSITIVE) { + std::map lower_mapping; + for(auto &kv : mapping) { + auto s = detail::to_lower(kv.first); + if(lower_mapping.count(s)) { + throw ValidationError(std::string("Several matching lowercase unit representations are found: ") + + s); + } + lower_mapping[detail::to_lower(kv.first)] = kv.second; + } + mapping = std::move(lower_mapping); + } + } + + /// Generate description like this: NUMBER [UNIT] + template static std::string generate_description(const std::string &name, Options opts) { + std::stringstream out; + out << detail::type_name() << ' '; + if(opts & UNIT_REQUIRED) { + out << name; + } else { + out << '[' << name << ']'; + } + return out.str(); + } +}; + +inline AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, const AsNumberWithUnit::Options &b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +/// Converts a human-readable size string (with unit literal) to uin64_t size. +/// Example: +/// "100" => 100 +/// "1 b" => 100 +/// "10Kb" => 10240 // you can configure this to be interpreted as kilobyte (*1000) or kibibyte (*1024) +/// "10 KB" => 10240 +/// "10 kb" => 10240 +/// "10 kib" => 10240 // *i, *ib are always interpreted as *bibyte (*1024) +/// "10kb" => 10240 +/// "2 MB" => 2097152 +/// "2 EiB" => 2^61 // Units up to exibyte are supported +class AsSizeValue : public AsNumberWithUnit { + public: + using result_t = std::uint64_t; + + /// If kb_is_1000 is true, + /// interpret 'kb', 'k' as 1000 and 'kib', 'ki' as 1024 + /// (same applies to higher order units as well). + /// Otherwise, interpret all literals as factors of 1024. + /// The first option is formally correct, but + /// the second interpretation is more wide-spread + /// (see https://en.wikipedia.org/wiki/Binary_prefix). + explicit AsSizeValue(bool kb_is_1000); + + private: + /// Get mapping + static std::map init_mapping(bool kb_is_1000); + + /// Cache calculated mapping + static std::map get_mapping(bool kb_is_1000); +}; + +namespace detail { +/// Split a string into a program name and command line arguments +/// the string is assumed to contain a file name followed by other arguments +/// the return value contains is a pair with the first argument containing the program name and the second +/// everything else. +CLI11_INLINE std::pair split_program_name(std::string commandline); + +} // namespace detail +/// @} + + + + +CLI11_INLINE std::string Validator::operator()(std::string &str) const { + std::string retstring; + if(active_) { + if(non_modifying_) { + std::string value = str; + retstring = func_(value); + } else { + retstring = func_(str); + } + } + return retstring; +} + +CLI11_NODISCARD CLI11_INLINE Validator Validator::description(std::string validator_desc) const { + Validator newval(*this); + newval.desc_function_ = [validator_desc]() { return validator_desc; }; + return newval; +} + +CLI11_INLINE Validator Validator::operator&(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " AND "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(!s1.empty() && !s2.empty()) + return std::string("(") + s1 + ") AND (" + s2 + ")"; + return s1 + s2; + }; + + newval.active_ = active_ && other.active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE Validator Validator::operator|(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " OR "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(s1.empty() || s2.empty()) + return std::string(); + + return std::string("(") + s1 + ") OR (" + s2 + ")"; + }; + newval.active_ = active_ && other.active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE Validator Validator::operator!() const { + Validator newval; + const std::function &dfunc1 = desc_function_; + newval.desc_function_ = [dfunc1]() { + auto str = dfunc1(); + return (!str.empty()) ? std::string("NOT ") + str : std::string{}; + }; + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + + newval.func_ = [f1, dfunc1](std::string &test) -> std::string { + std::string s1 = f1(test); + if(s1.empty()) { + return std::string("check ") + dfunc1() + " succeeded improperly"; + } + return std::string{}; + }; + newval.active_ = active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE void +Validator::_merge_description(const Validator &val1, const Validator &val2, const std::string &merger) { + + const std::function &dfunc1 = val1.desc_function_; + const std::function &dfunc2 = val2.desc_function_; + + desc_function_ = [=]() { + std::string f1 = dfunc1(); + std::string f2 = dfunc2(); + if((f1.empty()) || (f2.empty())) { + return f1 + f2; + } + return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')'; + }; +} + +namespace detail { + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +CLI11_INLINE path_type check_path(const char *file) noexcept { + std::error_code ec; + auto stat = std::filesystem::status(to_path(file), ec); + if(ec) { + return path_type::nonexistent; + } + switch(stat.type()) { + case std::filesystem::file_type::none: // LCOV_EXCL_LINE + case std::filesystem::file_type::not_found: + return path_type::nonexistent; // LCOV_EXCL_LINE + case std::filesystem::file_type::directory: + return path_type::directory; + case std::filesystem::file_type::symlink: + case std::filesystem::file_type::block: + case std::filesystem::file_type::character: + case std::filesystem::file_type::fifo: + case std::filesystem::file_type::socket: + case std::filesystem::file_type::regular: + case std::filesystem::file_type::unknown: + default: + return path_type::file; + } +} +#else +CLI11_INLINE path_type check_path(const char *file) noexcept { +#if defined(_MSC_VER) + struct __stat64 buffer; + if(_stat64(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#else + struct stat buffer; + if(stat(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#endif + return path_type::nonexistent; +} +#endif + +CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator("FILE") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "File does not exist: " + filename; + } + if(path_result == path_type::directory) { + return "File is actually a directory: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() : Validator("DIR") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Directory does not exist: " + filename; + } + if(path_result == path_type::file) { + return "Directory is actually a file: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE ExistingPathValidator::ExistingPathValidator() : Validator("PATH(existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Path does not exist: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() : Validator("PATH(non-existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result != path_type::nonexistent) { + return "Path already exists: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") { + func_ = [](std::string &ip_addr) { + auto result = CLI::detail::split(ip_addr, '.'); + if(result.size() != 4) { + return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')'; + } + int num = 0; + for(const auto &var : result) { + using CLI::detail::lexical_cast; + bool retval = lexical_cast(var, num); + if(!retval) { + return std::string("Failed parsing number (") + var + ')'; + } + if(num < 0 || num > 255) { + return std::string("Each IP number must be between 0 and 255 ") + var; + } + } + return std::string{}; + }; +} + +CLI11_INLINE EscapedStringTransformer::EscapedStringTransformer() { + func_ = [](std::string &str) { + try { + if(str.size() > 1 && (str.front() == '\"' || str.front() == '\'' || str.front() == '`') && + str.front() == str.back()) { + process_quoted_string(str); + } else if(str.find_first_of('\\') != std::string::npos) { + if(detail::is_binary_escaped_string(str)) { + str = detail::extract_binary_string(str); + } else { + str = remove_escaped_characters(str); + } + } + return std::string{}; + } catch(const std::invalid_argument &ia) { + return std::string(ia.what()); + } + }; +} +} // namespace detail + +CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool enableErrorReturn) + : Validator("FILE") { + func_ = [default_path, enableErrorReturn](std::string &filename) { + auto path_result = detail::check_path(filename.c_str()); + if(path_result == detail::path_type::nonexistent) { + std::string test_file_path = default_path; + if(default_path.back() != '/' && default_path.back() != '\\') { + // Add folder separator + test_file_path += '/'; + } + test_file_path.append(filename); + path_result = detail::check_path(test_file_path.c_str()); + if(path_result == detail::path_type::file) { + filename = test_file_path; + } else { + if(enableErrorReturn) { + return "File does not exist: " + filename; + } + } + } + return std::string{}; + }; +} + +CLI11_INLINE AsSizeValue::AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) { + if(kb_is_1000) { + description("SIZE [b, kb(=1000b), kib(=1024b), ...]"); + } else { + description("SIZE [b, kb(=1024b), ...]"); + } +} + +CLI11_INLINE std::map AsSizeValue::init_mapping(bool kb_is_1000) { + std::map m; + result_t k_factor = kb_is_1000 ? 1000 : 1024; + result_t ki_factor = 1024; + result_t k = 1; + result_t ki = 1; + m["b"] = 1; + for(std::string p : {"k", "m", "g", "t", "p", "e"}) { + k *= k_factor; + ki *= ki_factor; + m[p] = k; + m[p + "b"] = k; + m[p + "i"] = ki; + m[p + "ib"] = ki; + } + return m; +} + +CLI11_INLINE std::map AsSizeValue::get_mapping(bool kb_is_1000) { + if(kb_is_1000) { + static auto m = init_mapping(true); + return m; + } + static auto m = init_mapping(false); + return m; +} + +namespace detail { + +CLI11_INLINE std::pair split_program_name(std::string commandline) { + // try to determine the programName + std::pair vals; + trim(commandline); + auto esp = commandline.find_first_of(' ', 1); + while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) { + esp = commandline.find_first_of(' ', esp + 1); + if(esp == std::string::npos) { + // if we have reached the end and haven't found a valid file just assume the first argument is the + // program name + if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') { + bool embeddedQuote = false; + auto keyChar = commandline[0]; + auto end = commandline.find_first_of(keyChar, 1); + while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes + end = commandline.find_first_of(keyChar, end + 1); + embeddedQuote = true; + } + if(end != std::string::npos) { + vals.first = commandline.substr(1, end - 1); + esp = end + 1; + if(embeddedQuote) { + vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar)); + } + } else { + esp = commandline.find_first_of(' ', 1); + } + } else { + esp = commandline.find_first_of(' ', 1); + } + + break; + } + } + if(vals.first.empty()) { + vals.first = commandline.substr(0, esp); + rtrim(vals.first); + } + + // strip the program name + vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{}; + ltrim(vals.second); + return vals; +} + +} // namespace detail +/// @} + + + + +class Option; +class App; + +/// This enum signifies the type of help requested +/// +/// This is passed in by App; all user classes must accept this as +/// the second argument. + +enum class AppFormatMode { + Normal, ///< The normal, detailed help + All, ///< A fully expanded help + Sub, ///< Used when printed as part of expanded subcommand +}; + +/// This is the minimum requirements to run a formatter. +/// +/// A user can subclass this is if they do not care at all +/// about the structure in CLI::Formatter. +class FormatterBase { + protected: + /// @name Options + ///@{ + + /// The width of the left column (options/flags/subcommands) + std::size_t column_width_{30}; + + /// The width of the right column (description of options/flags/subcommands) + std::size_t right_column_width_{65}; + + /// The width of the description paragraph at the top of help + std::size_t description_paragraph_width_{80}; + + /// The width of the footer paragraph + std::size_t footer_paragraph_width_{80}; + + /// @brief The required help printout labels (user changeable) + /// Values are Needs, Excludes, etc. + std::map labels_{}; + + ///@} + /// @name Basic + ///@{ + + public: + FormatterBase() = default; + FormatterBase(const FormatterBase &) = default; + FormatterBase(FormatterBase &&) = default; + FormatterBase &operator=(const FormatterBase &) = default; + FormatterBase &operator=(FormatterBase &&) = default; + + /// Adding a destructor in this form to work around bug in GCC 4.7 + virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default) + + /// This is the key method that puts together help + virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0; + + ///@} + /// @name Setters + ///@{ + + /// Set the "REQUIRED" label + void label(std::string key, std::string val) { labels_[key] = val; } + + /// Set the left column width (options/flags/subcommands) + void column_width(std::size_t val) { column_width_ = val; } + + /// Set the right column width (description of options/flags/subcommands) + void right_column_width(std::size_t val) { right_column_width_ = val; } + + /// Set the description paragraph width at the top of help + void description_paragraph_width(std::size_t val) { description_paragraph_width_ = val; } + + /// Set the footer paragraph width + void footer_paragraph_width(std::size_t val) { footer_paragraph_width_ = val; } + + ///@} + /// @name Getters + ///@{ + + /// Get the current value of a name (REQUIRED, etc.) + CLI11_NODISCARD std::string get_label(std::string key) const { + if(labels_.find(key) == labels_.end()) + return key; + return labels_.at(key); + } + + /// Get the current left column width (options/flags/subcommands) + CLI11_NODISCARD std::size_t get_column_width() const { return column_width_; } + + /// Get the current right column width (description of options/flags/subcommands) + CLI11_NODISCARD std::size_t get_right_column_width() const { return right_column_width_; } + + /// Get the current description paragraph width at the top of help + CLI11_NODISCARD std::size_t get_description_paragraph_width() const { return description_paragraph_width_; } + + /// Get the current footer paragraph width + CLI11_NODISCARD std::size_t get_footer_paragraph_width() const { return footer_paragraph_width_; } + + ///@} +}; + +/// This is a specialty override for lambda functions +class FormatterLambda final : public FormatterBase { + using funct_t = std::function; + + /// The lambda to hold and run + funct_t lambda_; + + public: + /// Create a FormatterLambda with a lambda function + explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {} + + /// Adding a destructor (mostly to make GCC 4.7 happy) + ~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default) + + /// This will simply call the lambda function + std::string make_help(const App *app, std::string name, AppFormatMode mode) const override { + return lambda_(app, name, mode); + } +}; + +/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few +/// overridable methods, to be highly customizable with minimal effort. +class Formatter : public FormatterBase { + public: + Formatter() = default; + Formatter(const Formatter &) = default; + Formatter(Formatter &&) = default; + Formatter &operator=(const Formatter &) = default; + Formatter &operator=(Formatter &&) = default; + + /// @name Overridables + ///@{ + + /// This prints out a group of options with title + /// + CLI11_NODISCARD virtual std::string + make_group(std::string group, bool is_positional, std::vector opts) const; + + /// This prints out just the positionals "group" + virtual std::string make_positionals(const App *app) const; + + /// This prints out all the groups of options + std::string make_groups(const App *app, AppFormatMode mode) const; + + /// This prints out all the subcommands + virtual std::string make_subcommands(const App *app, AppFormatMode mode) const; + + /// This prints out a subcommand + virtual std::string make_subcommand(const App *sub) const; + + /// This prints out a subcommand in help-all + virtual std::string make_expanded(const App *sub, AppFormatMode mode) const; + + /// This prints out all the groups of options + virtual std::string make_footer(const App *app) const; + + /// This displays the description line + virtual std::string make_description(const App *app) const; + + /// This displays the usage line + virtual std::string make_usage(const App *app, std::string name) const; + + /// This puts everything together + std::string make_help(const App *app, std::string, AppFormatMode mode) const override; + + ///@} + /// @name Options + ///@{ + + /// This prints out an option help line, either positional or optional form + virtual std::string make_option(const Option *, bool) const; + + /// @brief This is the name part of an option, Default: left column + virtual std::string make_option_name(const Option *, bool) const; + + /// @brief This is the options part of the name, Default: combined into left column + virtual std::string make_option_opts(const Option *) const; + + /// @brief This is the description. Default: Right column, on new line if left column too large + virtual std::string make_option_desc(const Option *) const; + + /// @brief This is used to print the name on the USAGE line + virtual std::string make_option_usage(const Option *opt) const; + + ///@} +}; + + + + +using results_t = std::vector; +/// callback function definition +using callback_t = std::function; + +class Option; +class App; + +using Option_p = std::unique_ptr