Skip to content

feat: add config catalog query and client - #162

Merged
18202781743 merged 1 commit into
linuxdeepin:masterfrom
18202781743:master
Sep 17, 2026
Merged

18202781743 merged 1 commit into
linuxdeepin:masterfrom
18202781743:master

Conversation

@18202781743

@18202781743 18202781743 commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor
  1. Add ConfigInfo struct and D-Bus metatype registration for (appId,
    resourceId, subpath) triples
  2. Add DSGConfigCatalog on the daemon side to enumerate local
    configuration files across generic meta directories and per-app
    directories
  3. Add ResourceCatalogClient to query the daemon over the system bus and
    fall back to local directory scanning when the daemon is unreachable
  4. Add the Internal D-Bus interface XML exposing configurations() method
    and configurationsChanged signal
  5. Provide helper methods on the client for querying applications,
    resources per app, all-app resources, subpaths, and existence checks

Log: Added configuration catalog querying with D-Bus interface and local
fallback

Influence:

  1. Verify ConfigInfo serialization and deserialization over D-Bus
  2. Test DSGConfigCatalog enumeration with multiple app directories and
    nested subpaths
  3. Verify configurationsChanged signal triggers client cache refresh
  4. Test ResourceCatalogClient fallback to local directories when the
    daemon is unavailable
  5. Validate resource filtering for NoAppId and per-app queries
  6. Test subpath enumeration and exclusion of the root configuration
  7. Verify availableResourcesForApp merges per-app and all-app resources
    without duplicates

feat: 添加配置目录查询与客户端

  1. 新增 ConfigInfo 结构体及 D-Bus 元类型注册,用于 (appId, resourceId,
    subpath) 三元组
  2. 在守护进程侧新增 DSGConfigCatalog,用于遍历通用元目录及各应用目录下的
    本地配置文件
  3. 新增 ResourceCatalogClient,通过系统总线查询守护进程,在守护进程不可
    用时回退到本地目录扫描
  4. 新增 Internal D-Bus 接口 XML,暴露 configurations() 方法及
    configurationsChanged 信号
  5. 客户端提供查询应用列表、应用资源、全局资源、子路径及存在性检查的辅助
    方法

Log: 新增配置目录查询功能,含 D-Bus 接口与本地回退

Influence:

  1. 验证 ConfigInfo 在 D-Bus 上的序列化与反序列化
  2. 测试 DSGConfigCatalog 对多应用目录及嵌套子路径的遍历
  3. 验证 configurationsChanged 信号能触发客户端缓存刷新
  4. 测试守护进程不可用时 ResourceCatalogClient 回退到本地目录的逻辑
  5. 验证 NoAppId 与各应用查询的资源过滤
  6. 测试子路径遍历并确认根配置被排除
  7. 验证 availableResourcesForApp 合并各应用与全局资源且无重复

Summary by Sourcery

Add configuration catalog discovery with daemon-side enumeration, D-Bus access, and a local fallback.

New Features:

  • Add configuration catalog querying through a new D-Bus interface and client API.
  • Provide client helpers for applications, resources, subpaths, availability, and existence checks.

Bug Fixes:

  • Fall back to local configuration directory scanning when the daemon cannot be reached.

Enhancements:

  • Enumerate generic and per-application configuration files, including nested subpaths, with deduplication and change-driven cache invalidation.

1. Add ConfigInfo struct and D-Bus metatype registration for (appId,
resourceId, subpath) triples
2. Add DSGConfigCatalog on the daemon side to enumerate local
configuration files across generic meta directories and per-app
directories
3. Add ResourceCatalogClient to query the daemon over the system bus and
fall back to local directory scanning when the daemon is unreachable
4. Add the Internal D-Bus interface XML exposing configurations() method
and configurationsChanged signal
5. Provide helper methods on the client for querying applications,
resources per app, all-app resources, subpaths, and existence checks

Log: Added configuration catalog querying with D-Bus interface and local
fallback

Influence:
1. Verify ConfigInfo serialization and deserialization over D-Bus
2. Test DSGConfigCatalog enumeration with multiple app directories and
nested subpaths
3. Verify configurationsChanged signal triggers client cache refresh
4. Test ResourceCatalogClient fallback to local directories when the
daemon is unavailable
5. Validate resource filtering for NoAppId and per-app queries
6. Test subpath enumeration and exclusion of the root configuration
7. Verify availableResourcesForApp merges per-app and all-app resources
without duplicates

feat: 添加配置目录查询与客户端

1. 新增 ConfigInfo 结构体及 D-Bus 元类型注册,用于 (appId, resourceId,
subpath) 三元组
2. 在守护进程侧新增 DSGConfigCatalog,用于遍历通用元目录及各应用目录下的
本地配置文件
3. 新增 ResourceCatalogClient,通过系统总线查询守护进程,在守护进程不可
用时回退到本地目录扫描
4. 新增 Internal D-Bus 接口 XML,暴露 configurations() 方法及
configurationsChanged 信号
5. 客户端提供查询应用列表、应用资源、全局资源、子路径及存在性检查的辅助
方法

Log: 新增配置目录查询功能,含 D-Bus 接口与本地回退

Influence:
1. 验证 ConfigInfo 在 D-Bus 上的序列化与反序列化
2. 测试 DSGConfigCatalog 对多应用目录及嵌套子路径的遍历
3. 验证 configurationsChanged 信号能触发客户端缓存刷新
4. 测试守护进程不可用时 ResourceCatalogClient 回退到本地目录的逻辑
5. 验证 NoAppId 与各应用查询的资源过滤
6. 测试子路径遍历并确认根配置被排除
7. 验证 availableResourcesForApp 合并各应用与全局资源且无重复
@sourcery-ai

sourcery-ai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR adds an end-to-end configuration catalog: a shared D-Bus-serializable descriptor, daemon-side filesystem enumeration, an internally exposed D-Bus method and change signal, and a cached client API that falls back to local scanning when the daemon cannot be queried.

Sequence diagram for catalog queries and fallback

sequenceDiagram
    participant Client as ResourceCatalogClient
    participant DBus as DSGConfigInternal
    participant Daemon as DSGConfigCatalog
    participant FS as Configuration directories

    Client->>Client: configurations()
    alt daemon available
        Client->>DBus: configurations()
        DBus->>Daemon: configurations()
        Daemon->>FS: enumerate configuration files
        FS-->>Daemon: ConfigInfoList
        Daemon-->>DBus: ConfigInfoList
        DBus-->>Client: ConfigInfoList
        Client->>Client: cache configurations
    else daemon unavailable
        Client->>Client: localConfigurations()
        Client->>FS: applications()
        Client->>FS: resourcesForApp()
        Client->>FS: subpathsForResource()
        FS-->>Client: ConfigInfoList
    end

    Daemon-->>DBus: configurationsChanged()
    DBus-->>Client: configurationsChanged()
    Client->>Client: refresh()
Loading

File-Level Changes

Change Details Files
Introduces a shared configuration descriptor and registers its D-Bus representation for transport as an array of string triples.
  • Adds app ID, resource ID, and subpath fields with equality support.
  • Registers the descriptor and list types with Qt and Qt D-Bus metatype systems.
  • Defines structure serialization and deserialization operators.
dconfig-center/common/configinfo.h
Adds daemon-side catalog enumeration by scanning generic metadata roots, application directories, nested subpaths, and readable JSON resources.
  • Enumerates global and per-application configurations while excluding the overrides directory.
  • Uses DConfigFile loading to retain only valid configurations and de-duplicates entries.
  • Emits a change signal when the local prefix changes.
dconfig-center/dde-dconfig-daemon/dconfigcatalog.cpp
dconfig-center/dde-dconfig-daemon/dconfigcatalog.h
Adds a client-side D-Bus catalog API with caching, change-driven invalidation, and local scanning fallback.
  • Queries the daemon over the system bus and falls back to local configuration discovery on failed replies.
  • Provides application, per-app/global resource, subpath, availability, and existence queries.
  • Merges per-app and global resources and removes duplicates for application availability results.
dconfig-center/common/resourcecatalogclient.cpp
dconfig-center/common/resourcecatalogclient.h
Exposes configuration enumeration and invalidation through the daemon’s internal D-Bus contract.
  • Defines the configurations() method returning ConfigInfoList as a(sss).
  • Defines the configurationsChanged signal and Qt D-Bus type annotation.
dconfig-center/dde-dconfig-daemon/services/org.desktopspec.ConfigManager.Internal.xml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="dconfig-center/common/resourcecatalogclient.cpp" line_range="43-48" />
<code_context>
+{
+    ConfigInfoList result;
+    for (const QString &app : ::applications()) {
+        const QStringList resources = ::resourcesForApp(app);
+        for (const QString &resource : resources) {
+            result.append({app, resource, QString()});
+            const QStringList subpaths = ::subpathsForResource(app, resource);
+            for (const QString &subpath : subpaths)
+                result.append({app, resource, subpath});
+        }
+    }
</code_context>
<issue_to_address>
**issue (broader_impact):** The local fallback and daemon catalog disagree on generic directories containing nested subdirectories: the fallback's `applications()` helper treats each nested generic directory as an application and reports its files with that directory name as `appId`, while `appendConfigurations` deliberately does not recurse for `NoAppId`. The same generic nested configuration therefore receives a different identity, or disappears entirely, when the daemon is unavailable.

**Triggers:** When a generic configuration directory contains nested subpath directories and the daemon is unavailable.

**Suggested fix:** Use the same generic-directory traversal and `NoAppId`/subpath interpretation in the fallback as in `DSGConfigCatalog`, rather than deriving applications from generic directory children.
</issue_to_address>

### Comment 2
<location path="dconfig-center/common/resourcecatalogclient.cpp" line_range="85" />
<code_context>
+    if (m_configurationsValid)
+        return m_configurations;
+
+    auto reply = m_interface->configurations();
+    reply.waitForFinished();
+    if (reply.isError()) {
+        qWarning() << "Failed to query configurations from dde-dconfig-daemon:"
+                   << reply.error().message() << ", fallback to local directories.";
+        return localConfigurations();
+    }
+
</code_context>
<issue_to_address>
**issue (performance):** A failed D-Bus query returns `localConfigurations()` without setting `m_configurations` or `m_configurationsValid`, so every subsequent helper call synchronously retries the unavailable system-bus request and rescans all local directories. Calls such as `applications()`, `resourcesForApp()`, and `availableResourcesForApp()` consequently repeat the fallback work instead of using the catalog cache.

**Triggers:** When the daemon is unreachable and a caller performs multiple catalog queries.

**Suggested fix:** Cache the fallback result and mark it valid, while invalidating it when a later daemon/signal event indicates that a refresh is needed.

```suggestion
        m_configurations = localConfigurations();
        m_configurationsValid = true;
        return m_configurations;
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +43 to +48
const QStringList resources = ::resourcesForApp(app);
for (const QString &resource : resources) {
result.append({app, resource, QString()});
const QStringList subpaths = ::subpathsForResource(app, resource);
for (const QString &subpath : subpaths)
result.append({app, resource, subpath});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (broader_impact): The local fallback and daemon catalog disagree on generic directories containing nested subdirectories: the fallback's applications() helper treats each nested generic directory as an application and reports its files with that directory name as appId, while appendConfigurations deliberately does not recurse for NoAppId. The same generic nested configuration therefore receives a different identity, or disappears entirely, when the daemon is unavailable.

Triggers: When a generic configuration directory contains nested subpath directories and the daemon is unavailable.

Suggested fix: Use the same generic-directory traversal and NoAppId/subpath interpretation in the fallback as in DSGConfigCatalog, rather than deriving applications from generic directory children.

if (reply.isError()) {
qWarning() << "Failed to query configurations from dde-dconfig-daemon:"
<< reply.error().message() << ", fallback to local directories.";
return localConfigurations();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (performance): A failed D-Bus query returns localConfigurations() without setting m_configurations or m_configurationsValid, so every subsequent helper call synchronously retries the unavailable system-bus request and rescans all local directories. Calls such as applications(), resourcesForApp(), and availableResourcesForApp() consequently repeat the fallback work instead of using the catalog cache.

Triggers: When the daemon is unreachable and a caller performs multiple catalog queries.

Suggested fix: Cache the fallback result and mark it valid, while invalidating it when a later daemon/signal event indicates that a refresh is needed.

Suggested change
return localConfigurations();
m_configurations = localConfigurations();
m_configurationsValid = true;
return m_configurations;

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 95 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 95 分,大于 70 分通过阈值,代码质量优秀。本次提交新增配置目录查询功能和客户端,代码结构清晰,逻辑正确,未发现安全漏洞。存在少量代码质量和性能方面的改进建议。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰,边界处理完善。建议对registerMetaType()使用QMutex或Q_GLOBAL_STATIC保证线程安全;reply.waitForFinished()阻塞调用在当前客户端场景下可接受,但建议在UI线程使用时改用异步调用模式。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. dconfig-center/common/resourcecatalogclient.h:24 - ResourceCatalogClient类公开方法缺少文档注释
  2. dconfig-center/dde-dconfig-daemon/dconfigcatalog.h:14 - DSGConfigCatalog类公开方法缺少文档注释
  3. dconfig-center/common/configinfo.h:19 - ConfigInfo类缺少类级别文档注释

建议: 代码结构清晰,注释完整。建议为公开API方法添加Doxygen格式文档注释,说明参数含义、返回值和使用场景,提升代码可维护性。


3. 代码性能 ✅

评价: 良好 ✅ 通过

潜在问题:

  1. dconfig-center/common/resourcecatalogclient.cpp:80 - configurations()方法使用reply.waitForFinished()阻塞等待D-Bus响应
  2. dconfig-center/dde-dconfig-daemon/dconfigcatalog.cpp:87 - DSGConfigCatalog::configurations()无缓存机制,每次调用遍历文件系统
  3. dconfig-center/common/resourcecatalogclient.cpp:144 - existResource()存在冗余迭代,创建临时列表

建议: 性能良好,资源使用合理。建议DSGConfigCatalog::configurations()增加缓存机制,在configurationsChanged信号触发时刷新缓存;existResource()可优化为单次遍历直接判断,避免创建临时列表。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 安全合规,无安全风险。D-Bus通信使用系统总线标准接口,文件系统操作使用Qt安全API,无用户输入直接拼接路径的风险。建议保持当前安全编码实践。


💡 改进建议代码示例

// 建议为 DSGConfigCatalog::configurations() 添加缓存机制
class DSGConfigCatalog : public QObject
{
    Q_OBJECT
public:
    explicit DSGConfigCatalog(QObject *parent = nullptr);
    void setLocalPrefix(const QString &localPrefix);

public Q_SLOTS:
    ConfigInfoList configurations() const;

Q_SIGNALS:
    void configurationsChanged();

private:
    QString m_localPrefix;
    // 新增缓存成员
    mutable ConfigInfoList m_cachedConfigurations;
    mutable bool m_cacheValid = false;
};

ConfigInfoList DSGConfigCatalog::configurations() const
{
    if (m_cacheValid)
        return m_cachedConfigurations;

    ConfigInfoList result;
    QSet<QString> uniqueKeys;
    // ... 原有遍历逻辑 ...

    m_cachedConfigurations = result;
    m_cacheValid = true;
    return result;
}

void DSGConfigCatalog::setLocalPrefix(const QString &localPrefix)
{
    if (m_localPrefix == localPrefix)
        return;

    m_localPrefix = localPrefix;
    m_cacheValid = false;  // 失效缓存
    Q_EMIT configurationsChanged();
}

// 建议优化 existResource() 避免冗余迭代
bool ResourceCatalogClient::existResource(const QString &appid, const QString &resourceId)
{
    const auto configs = configurations();
    for (const auto &config : configs) {
        if (config.resourceId == resourceId &&
            (config.appId == appid || config.appId.isEmpty()))
            return true;
    }
    return false;
}

本报告由 AI 代码审查工具自动生成

@18202781743
18202781743 merged commit 4450f89 into linuxdeepin:master Sep 17, 2026
16 of 17 checks passed
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, mhduiy, MyLeeJiEun

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants