From f22945c506df199a6b43a2d505063213e8ddb65b Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 2 Jul 2024 15:36:47 +0800 Subject: [PATCH 1/5] chore: github workflows branch master to release github workflows branch master to release Log: --- .github/workflows/call-auto-tag.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/call-auto-tag.yml b/.github/workflows/call-auto-tag.yml index 5018e5beb..19c46034c 100644 --- a/.github/workflows/call-auto-tag.yml +++ b/.github/workflows/call-auto-tag.yml @@ -12,5 +12,6 @@ concurrency: jobs: auto_tag: - uses: linuxdeepin/.github/.github/workflows/auto-tag.yml@master - secrets: inherit + uses: deepin-community/.github/.github/workflows/auto-tag.yml@release + secrets: + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} From 9587cac5d24a0fdbe707ceb5ee00c883e04e6308 Mon Sep 17 00:00:00 2001 From: dengbo Date: Tue, 2 Jul 2024 13:33:48 +0800 Subject: [PATCH 2/5] chore: add github workflows add github workflows Log: --- .github/workflows/backup-to-gitlab.yml | 12 ++++++++ .github/workflows/call-auto-tag.yml | 17 ----------- .github/workflows/call-build-tag.yml | 14 +++++++++ .github/workflows/call-chatOps.yml | 9 ++++++ .github/workflows/call-commitlint.yml | 11 -------- .github/workflows/call-license-check.yml | 16 ----------- .github/workflows/cppcheck.yml | 26 ----------------- debian/deepin/workflows.yml | 36 ++++++++++++++++++++++++ 8 files changed, 71 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/backup-to-gitlab.yml delete mode 100644 .github/workflows/call-auto-tag.yml create mode 100644 .github/workflows/call-build-tag.yml create mode 100644 .github/workflows/call-chatOps.yml delete mode 100644 .github/workflows/call-commitlint.yml delete mode 100644 .github/workflows/call-license-check.yml delete mode 100644 .github/workflows/cppcheck.yml create mode 100644 debian/deepin/workflows.yml diff --git a/.github/workflows/backup-to-gitlab.yml b/.github/workflows/backup-to-gitlab.yml new file mode 100644 index 000000000..eb7461b6c --- /dev/null +++ b/.github/workflows/backup-to-gitlab.yml @@ -0,0 +1,12 @@ +name: backup to gitlab +on: [push] + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + backup-to-gitlabwh: + uses: deepin-community/.github/.github/workflows/backup-to-gitlabwh.yml@release + secrets: + BRIDGETOKEN: ${{ secrets.BRIDGETOKEN }} diff --git a/.github/workflows/call-auto-tag.yml b/.github/workflows/call-auto-tag.yml deleted file mode 100644 index 19c46034c..000000000 --- a/.github/workflows/call-auto-tag.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: auto tag - -on: - pull_request_target: - types: [opened, synchronize, closed] - paths: - - "debian/changelog" - -concurrency: - group: ${{ github.workflow }}-pull/${{ github.event.number }} - cancel-in-progress: true - -jobs: - auto_tag: - uses: deepin-community/.github/.github/workflows/auto-tag.yml@release - secrets: - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} diff --git a/.github/workflows/call-build-tag.yml b/.github/workflows/call-build-tag.yml new file mode 100644 index 000000000..d0a591ae3 --- /dev/null +++ b/.github/workflows/call-build-tag.yml @@ -0,0 +1,14 @@ +name: tag build +on: + push: + tags: "*" + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + build: + uses: deepin-community/.github/.github/workflows/build-tag.yml@master + secrets: + BridgeToken: ${{ secrets.BridgeToken }} diff --git a/.github/workflows/call-chatOps.yml b/.github/workflows/call-chatOps.yml new file mode 100644 index 000000000..83ef38cc2 --- /dev/null +++ b/.github/workflows/call-chatOps.yml @@ -0,0 +1,9 @@ +name: chatOps +on: + issue_comment: + types: [created] + +jobs: + chatopt: + uses: deepin-community/.github/.github/workflows/chatOps.yml@master + secrets: inherit diff --git a/.github/workflows/call-commitlint.yml b/.github/workflows/call-commitlint.yml deleted file mode 100644 index 69f5b2dc5..000000000 --- a/.github/workflows/call-commitlint.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Call commitlint -on: - pull_request_target: - -concurrency: - group: ${{ github.workflow }}-pull/${{ github.event.number }} - cancel-in-progress: true - -jobs: - check_job: - uses: linuxdeepin/.github/.github/workflows/commitlint.yml@master diff --git a/.github/workflows/call-license-check.yml b/.github/workflows/call-license-check.yml deleted file mode 100644 index 347d55602..000000000 --- a/.github/workflows/call-license-check.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Call License and README Check -on: - pull_request_target: - types: [opened, synchronize, reopened] - -permissions: - pull-requests: write - contents: read - -concurrency: - group: ${{ github.workflow }}-pull/${{ github.event.number }} - cancel-in-progress: true - -jobs: - license-check: - uses: linuxdeepin/.github/.github/workflows/license-check.yml@master diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml deleted file mode 100644 index e808a89b1..000000000 --- a/.github/workflows/cppcheck.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: cppcheck -on: - pull_request_target: - paths-ignore: - - ".github/workflows/**" - -concurrency: - group: ${{ github.workflow }}-pull/${{ github.event.number }} - cancel-in-progress: true - -jobs: - cppchceck: - name: cppcheck - runs-on: ubuntu-latest - steps: - - run: export - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - persist-credentials: false - - uses: linuxdeepin/action-cppcheck@main - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - repository: ${{ github.repository }} - pull_request_id: ${{ github.event.pull_request.number }} - allow_approve: false diff --git a/debian/deepin/workflows.yml b/debian/deepin/workflows.yml new file mode 100644 index 000000000..c6c2ebf8f --- /dev/null +++ b/debian/deepin/workflows.yml @@ -0,0 +1,36 @@ +test_build: + steps: + - link_package: + source_project: deepin:Develop:main + source_package: %{SCM_REPOSITORY_NAME} + target_project: deepin:CI + + - configure_repositories: + project: deepin:CI + repositories: + - name: deepin_develop + paths: + - target_project: deepin:CI + target_repository: deepin_develop + architectures: + - x86_64 + - aarch64 + + filters: + event: pull_request + +tag_build: + steps: + - trigger_services: + project: deepin:Unstable:main + package: %{SCM_REPOSITORY_NAME} + filters: + event: tag_push + +commit_build: + steps: + - trigger_services: + project: deepin:Develop:main + package: %{SCM_REPOSITORY_NAME} + filters: + event: push From dc1d464e80614cb9be91eec1349a6af5cf1987a2 Mon Sep 17 00:00:00 2001 From: dengbo11 Date: Wed, 25 Dec 2024 17:11:45 +0800 Subject: [PATCH 3/5] chore: bump version to 1.8.0-1 release 1.8.0 Log: bump version to 1.8.0-1 --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index cf95109f9..9ed8ff926 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linglong (1.8.0-1) unstable; urgency=medium + + * release 1.8.0 + + -- dengbo Wed, 25 Dec 2024 17:11:45 +0800 + linglong (1.5.6-1) unstable; urgency=medium * fix: layer size error when export layer repeatedly From 72487819aba0cd5fa588453aeb6c6cd879d444c0 Mon Sep 17 00:00:00 2001 From: myml Date: Wed, 25 Dec 2024 13:48:59 +0800 Subject: [PATCH 4/5] feat: adjust systemd/user priority MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XDG_DATA_DIRS下面的systemd优先级很高, 会影响系统systemd服务 将应用的systemd导出到其他地方, 再使用user-generator复制到优先级最低的generator.late目录 --- debian/linglong-bin.install | 1 + .../src/linglong/repo/ostree_repo.cpp | 301 +++++++++++------- libs/linglong/src/linglong/repo/ostree_repo.h | 10 +- libs/utils/src/linglong/utils/error/error.h | 51 +-- misc/CMakeLists.txt | 6 + .../linglong-user-systemd-generator | 9 + rpm/linglong.spec | 1 + 7 files changed, 242 insertions(+), 137 deletions(-) create mode 100755 misc/lib/systemd/user-generators/linglong-user-systemd-generator diff --git a/debian/linglong-bin.install b/debian/linglong-bin.install index b6adbc015..581c6572c 100644 --- a/debian/linglong-bin.install +++ b/debian/linglong-bin.install @@ -5,6 +5,7 @@ usr/bin/ll-cli usr/bin/llpkg usr/lib/linglong/* usr/lib/systemd/system-environment-generators/61-linglong +usr/lib/systemd/user-generators/linglong-user-systemd-generator usr/lib/systemd/system/org.deepin.linglong.PackageManager.service lib/systemd/system/ usr/lib/systemd/user/linglong-session-helper.service usr/lib/sysusers.d/linglong.conf diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index 4ffa93902..9ffea0ddb 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1505,7 +1506,7 @@ void OSTreeRepo::unexportReference(const package::Reference &ref) noexcept return; } - QDir entriesDir = this->repoDir.absoluteFilePath("entries/share"); + QDir entriesDir = this->repoDir.absoluteFilePath("entries"); QDirIterator it(entriesDir.absolutePath(), QDir::AllEntries | QDir::NoDot | QDir::NoDotDot | QDir::System, QDirIterator::Subdirectories); @@ -1538,7 +1539,7 @@ void OSTreeRepo::unexportReference(const package::Reference &ref) noexcept void OSTreeRepo::exportReference(const package::Reference &ref) noexcept { - auto entriesDir = QDir(this->repoDir.absoluteFilePath("entries/share")); + auto entriesDir = QDir(this->repoDir.absoluteFilePath("entries")); if (!entriesDir.exists()) { entriesDir.mkpath("."); } @@ -1549,7 +1550,7 @@ void OSTreeRepo::exportReference(const package::Reference &ref) noexcept Q_ASSERT(false); return; } - auto ret = exportEntries(entriesDir, *item); + auto ret = exportEntries(entriesDir.absolutePath().toStdString(), *item); if (!ret.has_value()) { qCritical() << QString("Failed to export %1:").arg(ref.toString()) << ret.error().message(); Q_ASSERT(false); @@ -1558,102 +1559,177 @@ void OSTreeRepo::exportReference(const package::Reference &ref) noexcept this->updateSharedInfo(); } -utils::error::Result OSTreeRepo::exportEntries( - const QDir &entriesDir, const api::types::v1::RepositoryCacheLayersItem &item) noexcept +// 递归源目录所有文件,并在目标目录创建软链接,max_depth 控制递归深度以避免环形链接导致的无限递归 +utils::error::Result OSTreeRepo::exportDir(const std::string &appID, + const std::filesystem::path &source, + const std::filesystem::path &destination, + const int &max_depth) { - LINGLONG_TRACE(QString("export %1").arg(item.info.id.c_str())); - auto layerDir = getMergedModuleDir(item); - if (!layerDir.has_value()) { - return LINGLONG_ERR("get layer dir", layerDir); - } - auto layerEntriesDir = QDir(layerDir->absoluteFilePath("entries/share")); - if (!layerEntriesDir.exists()) { - qCritical() << QString("Failed to export %1:").arg(item.info.id.c_str()) << layerEntriesDir - << "not exists."; + LINGLONG_TRACE(QString("export %1").arg(source.c_str())); + if (max_depth <= 0) { + qWarning() << "ttl reached, skipping export for" << source.c_str(); return LINGLONG_OK; } - const QStringList exportPaths = { - "applications", // Copy desktop files - "mime", // Copy MIME Type files - "icons", // Icons - "dbus-1", // D-Bus service files - "gnome-shell", // Search providers - "appdata", // Copy appdata/metainfo files (legacy path) - "metainfo", // Copy appdata/metainfo files - "plugins", // Copy plugins conf,The configuration files provided by some applications - // maybe used by the host dde-file-manager. - "systemd", // copy systemd service files - "deepin-manual", // copy deepin-manual files - "deepin-elf-verify" // for uab signature - }; - - for (const auto &path : exportPaths) { - QDir exportDir = layerEntriesDir.absoluteFilePath(path); - if (!exportDir.exists()) { + std::error_code ec; + // 检查源目录是否存在 + auto exists = std::filesystem::exists(source, ec); + if (ec) { + return LINGLONG_ERR("check source", ec); + } + if (!exists) { + return LINGLONG_ERR("source directory does not exist"); + } + auto is_directory = std::filesystem::is_directory(source, ec); + if (ec) { + return LINGLONG_ERR("check source", ec); + } + if (!is_directory) { + return LINGLONG_ERR("source is not a directory"); + } + // 检查目标目录是否存在,如果不存在则创建 + exists = std::filesystem::exists(destination, ec); + if (ec) { + return LINGLONG_ERR(QString("Failed to check file existence: ") + destination.c_str(), ec); + } + // 如果目标非目录,则删除它并重新创建 + if (exists && !std::filesystem::is_directory(destination, ec)) { + std::filesystem::remove(destination, ec); + if (ec) { + return LINGLONG_ERR(QString("Failed to remove file: ") + destination.c_str(), ec); + } + // 标记目标不存在 + exists = false; + } + if (!exists) { + std::filesystem::create_directories(destination, ec); + if (ec) { + 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); + } + // 遍历源目录中的所有文件和子目录 + for (const auto &entry : iterator) { + const auto &source_path = entry.path(); + const auto &target_path = destination / source_path.filename(); + // 跳过无效的软链接 + exists = std::filesystem::exists(source_path, ec); + if (ec) { + return LINGLONG_ERR("check source existence" + source_path.string(), ec); + } + if (!exists) { continue; } - QDirIterator it(exportDir.absolutePath(), - QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden, - QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); - while (it.hasNext()) { - it.next(); - const auto info = it.fileInfo(); - if (info.isDir()) { - continue; - } - // Check if the target file of the symbolic link exists. - if (info.isSymLink() && !std::filesystem::exists(info.symLinkTarget().toStdString())) { - qCritical() << "Invalid symlink: " << info.filePath(); - continue; + // 如果是文件,创建符号链接 + auto is_regular_file = std::filesystem::is_regular_file(source_path, ec); + if (ec) { + return LINGLONG_ERR("check file type: " + source_path.string(), ec); + } + if (is_regular_file) { + exists = std::filesystem::exists(target_path, ec); + if (ec) { + return LINGLONG_ERR("check file existence", ec); } - - auto ret = IniLikeFileRewrite(info, QString::fromStdString(item.info.id)); - if (!ret) { - qCritical() << ret.error().message(); + if (exists) { + std::filesystem::remove(target_path, ec); + if (ec) { + return LINGLONG_ERR("remove file failed", ec); + } } - - const auto parentDirForLinkPath = - layerEntriesDir.relativeFilePath(it.fileInfo().dir().absolutePath()); - - if (!entriesDir.mkpath(parentDirForLinkPath)) { - qCritical() << "Failed to mkpath" - << entriesDir.absoluteFilePath(parentDirForLinkPath); + auto ret = IniLikeFileRewrite(QFileInfo(source_path.c_str()), appID.c_str()); + if (!ret) { } + std::filesystem::create_symlink(source_path, target_path, ec); + if (ec) { + return LINGLONG_ERR("create symlink failed: " + target_path.string(), ec); } - auto from = std::filesystem::path{ - entriesDir.absoluteFilePath(parentDirForLinkPath).toStdString() - } / it.fileName().toStdString(); - - QDir parentDir(entriesDir.absoluteFilePath(parentDirForLinkPath)); - auto to = std::filesystem::path{ - parentDir.relativeFilePath(info.absoluteFilePath()).toStdString() - }; - - std::error_code ec; - auto status = std::filesystem::symlink_status(from, ec); - if (ec && ec.value() != static_cast(std::errc::no_such_file_or_directory)) { - qCritical() << "symlink_status" << from.c_str() - << "error:" << QString::fromStdString(ec.message()); - continue; + continue; + } + // 如果是目录,进行递归导出 + is_directory = std::filesystem::is_directory(source_path, ec); + if (ec) { + return LINGLONG_ERR("check file type", ec); + } + if (is_directory) { + auto ret = this->exportDir(appID, source_path, target_path, max_depth - 1); + if (!ret.has_value()) { + return ret; } + continue; + } + // 其他情况,报错 + qWarning() << "invalid file: " << source_path.c_str(); + } + return LINGLONG_OK; +} - if (std::filesystem::exists(status)) { - qInfo() << from.c_str() << "symlink already exists, try to remove it"; - if (!std::filesystem::remove(from, ec)) { - qCritical() << "remove" << from.c_str() - << "error:" << QString::fromStdString(ec.message()); - continue; - } - } +utils::error::Result +OSTreeRepo::exportEntries(const std::filesystem::path &rootEntriesDir, + const api::types::v1::RepositoryCacheLayersItem &item) noexcept +{ + LINGLONG_TRACE(QString("export %1").arg(item.info.id.c_str())); + auto layerDir = getMergedModuleDir(item); + if (!layerDir.has_value()) { + return LINGLONG_ERR("get layer dir", layerDir); + } + std::error_code ec; + // 检查目录是否存在 + std::filesystem::path appEntriesDir = layerDir->absoluteFilePath("entries").toStdString(); + auto exists = std::filesystem::exists(appEntriesDir, ec); + if (ec) { + return LINGLONG_ERR("check appEntriesDir exists", ec); + } + if (!exists) { + qCritical() << QString("Failed to export %1:").arg(item.info.id.c_str()) + << appEntriesDir.c_str() << "not exists."; + return LINGLONG_OK; + } + std::vector exportPaths = { + "share/applications", // Copy desktop files + "share/mime", // Copy MIME Type files + "share/icons", // Icons + "share/dbus-1", // D-Bus service files + "share/gnome-shell", // Search providers + "share/appdata", // Copy appdata/metainfo files (legacy path) + "share/metainfo", // Copy appdata/metainfo files + "share/plugins", // Copy plugins conf,The configuration files provided by some applications + // maybe used by the host dde-file-manager. + "share/deepin-manual", // copy deepin-manual files + "share/deepin-elf-verify", // for uab signature - std::filesystem::create_symlink(to, from, ec); - if (ec) { - qCritical().nospace() - << "Failed to create link " << from.c_str() << " -> " << to.c_str() << " : " - << QString::fromStdString(ec.message()); - continue; - } + }; + // 如果存在lib/systemd目录,则导出lib/systemd,否则导出share/systemd + exists = std::filesystem::exists(appEntriesDir / "lib/systemd", ec); + if (ec) { + return LINGLONG_ERR("Failed to check the existence of lib/systemd directory: {}", ec); + } + if (exists) { + exportPaths.push_back("lib/systemd"); + } else { + exportPaths.push_back("share/systemd"); + } + // 导出应用entries目录下的所有文件到玲珑仓库的entries目录下 + for (const auto &path : exportPaths) { + auto source = appEntriesDir / path; + auto destination = rootEntriesDir / path; + // 将 share/systemd 目录下的文件导出到 lib/systemd 目录下 + if (path == "share/systemd") { + destination = rootEntriesDir / "lib/systemd"; + } + // 检查源目录是否存在,跳过不存在的目录 + exists = std::filesystem::exists(source, ec); + if (ec) { + return LINGLONG_ERR(QString("Failed to check file existence: ") + source.c_str(), ec); + } + if (!exists) { + continue; + } + auto ret = this->exportDir(item.info.id, source, destination, 10); + if (!ret.has_value()) { + return ret; } } return LINGLONG_OK; @@ -1663,20 +1739,14 @@ utils::error::Result OSTreeRepo::exportAllEntries() noexcept { LINGLONG_TRACE("export all entries"); std::error_code ec; - // 创建新的share目录 + // 创建一个新的entries目录,使用UUID作为名称 auto id = QUuid::createUuid().toString(QUuid::Id128); - auto entriesDir = QDir(this->repoDir.absoluteFilePath("entries/share_new_" + id)); - if (entriesDir.exists()) { - std::filesystem::remove_all(entriesDir.absolutePath().toStdString(), ec); - if (ec) { - return LINGLONG_ERR("clean temp share directory", ec); - } - } - std::filesystem::create_directory(entriesDir.absolutePath().toStdString(), ec); + std::filesystem::path entriesDir = this->repoDir.filePath("entries_new_" + id).toStdString(); + std::filesystem::create_directory(entriesDir, ec); if (ec) { return LINGLONG_ERR("create temp share directory", ec); } - // 导出所有layer + // 导出所有layer到新entries目录 auto items = this->cache->queryExistingLayerItem(); for (const auto &item : items) { if (item.info.kind != "app") { @@ -1687,27 +1757,29 @@ utils::error::Result OSTreeRepo::exportAllEntries() noexcept return ret; } } - // 用新的share目录替换旧的 - std::filesystem::path workdir = repoDir.absoluteFilePath("entries").toStdString(); - - if (!std::filesystem::exists(workdir / "share")) { - std::filesystem::rename(entriesDir.dirName().toStdString(), workdir / "share", ec); + // 用新的entries目录替换旧的 + std::filesystem::path workdir = repoDir.absolutePath().toStdString(); + auto existsOldEntries = std::filesystem::exists(workdir / "entries", ec); + if (ec) { + return LINGLONG_ERR("check entries directory", ec); + } + if (!existsOldEntries) { + std::filesystem::rename(entriesDir, workdir / "entries", ec); if (ec) { - return LINGLONG_ERR("create new share symlink", ec); + return LINGLONG_ERR("rename new entries directory", ec); } } else { - auto oldshare = "share_old_" + QUuid::createUuid().toString(QUuid::Id128).toStdString(); - std::filesystem::rename(workdir / "share", workdir / oldshare, ec); + auto id = QUuid::createUuid().toString(QUuid::Id128).toStdString(); + auto oldEntriesDir = workdir / ("entries_old_" + id); + std::filesystem::rename(workdir / "entries", oldEntriesDir, ec); if (ec) { return LINGLONG_ERR("rename old share directory", ec); } - std::filesystem::rename(workdir / entriesDir.dirName().toStdString(), - workdir / "share", - ec); + std::filesystem::rename(entriesDir, workdir / "entries", ec); if (ec) { return LINGLONG_ERR("create new share symlink", ec); } - std::filesystem::remove_all(workdir / oldshare, ec); + std::filesystem::remove_all(oldEntriesDir, ec); if (ec) { return LINGLONG_ERR("remove old share directory", ec); } @@ -2219,7 +2291,7 @@ OSTreeRepo::listLocalBy(const linglong::repo::repoCacheQuery &query) const noexc QString getOriginRawExec(const QString &execArgs, const QString &id) { // Note: These strings have appeared in the app-conf-generator.sh of linglong-builder. - // We need to remove them. + // We need to remove them. const QString oldExec = "--exec "; const QString newExec = "-- "; @@ -2234,8 +2306,7 @@ QString getOriginRawExec(const QString &execArgs, const QString &id) return execArgs.mid(index + newExec.length()); } - qCritical() << "'-- ' or '--exec ' is not exist in" << execArgs - << ", return an empty string"; + qCritical() << "'-- ' or '--exec ' is not exist in" << execArgs << ", return an empty string"; return ""; } @@ -2243,7 +2314,7 @@ QString buildDesktopExec(QString origin, const QString &appID) noexcept { auto newExec = QString{ "%1 run %2 " }.arg(LINGLONG_CLIENT_PATH, appID); - if(origin.isEmpty()) { + if (origin.isEmpty()) { Q_ASSERT(false); return newExec; } @@ -2275,8 +2346,7 @@ QString buildDesktopExec(QString origin, const QString &appID) noexcept [[fallthrough]]; case 'F': { origin.insert(next - origin.begin(), '%'); - auto tmp = - QString{ "--file %%1 -- %2" }.arg(std::move(code), std::move(origin)); + auto tmp = QString{ "--file %%1 -- %2" }.arg(std::move(code), std::move(origin)); newExec.append(tmp); return newExec; } @@ -2284,8 +2354,7 @@ QString buildDesktopExec(QString origin, const QString &appID) noexcept [[fallthrough]]; case 'U': { origin.insert(next - origin.begin(), '%'); - auto tmp = - QString{ "--url %%1 -- %2" }.arg(std::move(code), std::move(origin)); + auto tmp = QString{ "--url %%1 -- %2" }.arg(std::move(code), std::move(origin)); newExec.append(tmp); return newExec; } diff --git a/libs/linglong/src/linglong/repo/ostree_repo.h b/libs/linglong/src/linglong/repo/ostree_repo.h index 35bb5b2aa..392198891 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.h +++ b/libs/linglong/src/linglong/repo/ostree_repo.h @@ -154,10 +154,16 @@ class OSTreeRepo : public QObject [[nodiscard]] utils::error::Result getMergedModuleDir(const api::types::v1::RepositoryCacheLayersItem &layer, bool fallbackLayerDir = true) const noexcept; - utils::error::Result exportEntries( - const QDir &entriesDir, const api::types::v1::RepositoryCacheLayersItem &item) noexcept; + utils::error::Result + exportEntries(const std::filesystem::path &rootEntriesDir, + const api::types::v1::RepositoryCacheLayersItem &item) noexcept; 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); }; } // namespace linglong::repo diff --git a/libs/utils/src/linglong/utils/error/error.h b/libs/utils/src/linglong/utils/error/error.h index 9b18c6124..f78347726 100644 --- a/libs/utils/src/linglong/utils/error/error.h +++ b/libs/utils/src/linglong/utils/error/error.h @@ -20,6 +20,7 @@ #include #include +#include #include namespace linglong::utils::error { @@ -38,11 +39,9 @@ class Error [[nodiscard]] auto message() const { return pImpl->message(); } - static auto Err(const char *file, - int line, - const QString &trace_msg, - const QString &msg, - int code = -1) -> Error + static auto + Err(const char *file, int line, const QString &trace_msg, const QString &msg, int code = -1) + -> Error { return Error(std::make_unique(file, line, @@ -67,8 +66,8 @@ class Error nullptr)); } - static auto - Err(const char *file, int line, const QString &trace_msg, const QFile &qfile) -> Error + static auto Err(const char *file, int line, const QString &trace_msg, const QFile &qfile) + -> Error { return Error(std::make_unique(file, line, @@ -79,11 +78,9 @@ class Error nullptr)); } - static auto Err(const char *file, - int line, - const QString &trace_msg, - std::exception_ptr err, - int code = -1) -> Error + static auto + Err(const char *file, int line, const QString &trace_msg, std::exception_ptr err, int code = -1) + -> Error { QString what = trace_msg + ": "; try { @@ -118,8 +115,8 @@ class Error std::make_unique(file, line, "default", code, what, nullptr)); } - static auto - Err(const char *file, int line, const QString &trace_msg, const std::exception &e) -> Error + static auto Err(const char *file, int line, const QString &trace_msg, const std::exception &e) + -> Error { return Error(std::make_unique(file, line, @@ -156,6 +153,15 @@ class Error return Err(file, line, trace_msg, new_msg); } + static auto Err(const char *file, + int line, + const QString &trace_msg, + const char *msg, + const std::system_error &e) -> Error + { + return Err(file, line, trace_msg, msg, e, e.code().value()); + } + static auto Err(const char *file, int line, const QString &trace_msg, @@ -165,6 +171,15 @@ class Error return Err(file, line, trace_msg, msg, e, e.code().value()); } + static auto Err(const char *file, + int line, + const QString &trace_msg, + const std::string &msg, + const std::system_error &e) -> Error + { + return Err(file, line, trace_msg, msg.c_str(), e, e.code().value()); + } + template static auto Err(const char *file, int line, @@ -198,11 +213,9 @@ class Error std::move(cause.error().pImpl))); } - static auto Err(const char *file, - int line, - const QString &trace_msg, - const QString &msg, - Error &&cause) -> Error + static auto + Err(const char *file, int line, const QString &trace_msg, const QString &msg, Error &&cause) + -> Error { return Error(std::make_unique(file, line, diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index 75c2ac35b..2caa5c196 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -38,6 +38,7 @@ configure_files( lib/linglong/container/README.md lib/linglong/generate-xdg-data-dirs.sh lib/systemd/system-environment-generators/61-linglong + lib/systemd/user-generators/linglong-user-systemd-generator lib/systemd/system/org.deepin.linglong.PackageManager.service lib/systemd/system-preset/91-linglong.preset lib/systemd/user/linglong-session-helper.service @@ -149,6 +150,11 @@ install( ${CMAKE_CURRENT_BINARY_DIR}/lib/systemd/system-environment-generators/61-linglong DESTINATION ${SYSTEMD_SYSTEM_GENERATOR_PATH}) +install( + PROGRAMS + ${CMAKE_CURRENT_BINARY_DIR}/lib/systemd/user-generators/linglong-user-systemd-generator + DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/systemd/user-generators) + # sysuser set(SYSTEMD_SYSUSERSDIR ${CMAKE_INSTALL_PREFIX}/lib/sysusers.d) diff --git a/misc/lib/systemd/user-generators/linglong-user-systemd-generator b/misc/lib/systemd/user-generators/linglong-user-systemd-generator new file mode 100755 index 000000000..f398a2216 --- /dev/null +++ b/misc/lib/systemd/user-generators/linglong-user-systemd-generator @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: LGPL-3.0-or-later + +# https://www.freedesktop.org/software/systemd/man/latest/systemd.generator.html +late="$3" +cp -rs @LINGLONG_ROOT@/entries/lib/systemd/user/* "$late/" diff --git a/rpm/linglong.spec b/rpm/linglong.spec index a8b59117c..1d964f22c 100644 --- a/rpm/linglong.spec +++ b/rpm/linglong.spec @@ -85,6 +85,7 @@ cd build %{_prefix}/lib/systemd/system-preset/*.preset %{_prefix}/lib/systemd/user/* %{_prefix}/lib/systemd/system-environment-generators/* +%{_prefix}/lib/systemd/user-generators/* %{_libexecdir}/%{name}/ll-package-manager %{_libexecdir}/%{name}/ll-session-helper %{_libexecdir}/%{name}/ld-cache-generator From adffe0be54f7ab822d24c3060629e57920ebc0cd Mon Sep 17 00:00:00 2001 From: kamiyadm Date: Wed, 25 Dec 2024 14:37:37 +0800 Subject: [PATCH 5/5] fix: no desktop in launcher after install app Bring updateAM() back and call another service which in system bus. Service name is org.desktopspec.ApplicationUpdateNotifier1. Log: --- libs/linglong/src/linglong/cli/cli.cpp | 26 ++++++++++++++++++++++++++ libs/linglong/src/linglong/cli/cli.h | 1 + 2 files changed, 27 insertions(+) diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 6df683929..f6dd05f8c 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 "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/PackageManager1InstallParameters.hpp" @@ -1032,6 +1033,7 @@ int Cli::installFromFile(const QFileInfo &fileInfo, const api::types::v1::Common return -1; } + updateAM(); return this->lastState == linglong::api::types::v1::State::Succeed ? 0 : -1; } @@ -1149,6 +1151,7 @@ int Cli::install() } loop.exec(); + updateAM(); return this->lastState == linglong::api::types::v1::State::Succeed ? 0 : -1; } @@ -1258,6 +1261,7 @@ int Cli::upgrade() } loop.exec(); + updateAM(); if (this->lastState != linglong::api::types::v1::State::Succeed) { return -1; } @@ -1536,6 +1540,7 @@ int Cli::uninstall() } loop.exec(); + updateAM(); return this->lastState == linglong::api::types::v1::State::Succeed ? 0 : -1; } @@ -2409,4 +2414,25 @@ Cli::ensureCache(const package::Reference &ref, return appCache; } + +void Cli::updateAM() noexcept +{ + // NOTE: make sure AM refresh the cache of desktop + if ((QSysInfo::productType() == "Deepin" || QSysInfo::productType() == "deepin") + && this->lastState == linglong::api::types::v1::State::Succeed) { + QDBusConnection conn = QDBusConnection::systemBus(); + if (!conn.isConnected()) { + qWarning() << "Failed to connect to the system bus"; + } + + auto peer = linglong::api::dbus::v1::DBusPeer("org.desktopspec.ApplicationUpdateNotifier1", + "/org/desktopspec/ApplicationUpdateNotifier1", + conn); + auto reply = peer.Ping(); + reply.waitForFinished(); + if (!reply.isValid()) { + qWarning() << "Failed to ping org.desktopspec.ApplicationUpdateNotifier1" << reply.error(); + } + } +} } // namespace linglong::cli diff --git a/libs/linglong/src/linglong/cli/cli.h b/libs/linglong/src/linglong/cli/cli.h index a721cec1a..c7ec7e438 100644 --- a/libs/linglong/src/linglong/cli/cli.h +++ b/libs/linglong/src/linglong/cli/cli.h @@ -99,6 +99,7 @@ class Cli : public QObject ensureCache(const package::Reference &ref, const api::types::v1::RepositoryCacheLayersItem &appLayerItem) noexcept; QDBusReply authorization(); + void updateAM() noexcept; private Q_SLOTS: // maybe use in the future