Skip to content

feat: normalize disk size only for specific devices.#179

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:release/1071from
itsXuSt:1071
Oct 23, 2025
Merged

feat: normalize disk size only for specific devices.#179
deepin-bot[bot] merged 1 commit intolinuxdeepin:release/1071from
itsXuSt:1071

Conversation

@itsXuSt
Copy link
Contributor

@itsXuSt itsXuSt commented Oct 21, 2025

Log: as above.

Bug: https://pms.uniontech.com/bug-view-329231.html
Task: https://pms.uniontech.com/task-view-368603.html

Summary by Sourcery

Add disk size normalization for hardware devices by parsing raw size strings and mapping them to standard capacity tiers, and restrict the updateForHWDevice logic to devices with a non-empty boot product name.

Enhancements:

  • Remove unused devicePath parameter and only run updateForHWDevice when /proc/bootdevice/product_name is present
  • Parse m_size strings (bytes, GB, TB) into bytes and round to standard tiers (256 GB, 512 GB, 1 TB, 2 TB), skipping sizes under 200 GB

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 21, 2025

Reviewer's Guide

This PR refactors the hardware device update flow to drop unused parameters, implements raw disk size parsing and normalization to standard presets, and integrates a centralized size formatting method for consistent output.

Class diagram for updated DeviceStorage class

classDiagram
class DeviceStorage {
  - QString m_model
  - QString m_vendor
  - QString m_size
  + void getDiskInfoInterface(QString devicePath, QString &interface, QString &type)
  + void updateForHWDevice()
  + void getMapInfoFromSmartctl(QMap<QString, QString> &mapInfo, QString info, QString ch)
}

DeviceStorage : updateForHWDevice() now normalizes m_size for specific devices
DeviceStorage : updateForHWDevice() signature changed (devicePath parameter removed)
Loading

Flow diagram for disk size normalization in updateForHWDevice

flowchart TD
    A["updateForHWDevice() called"] --> B["Check if product_name is empty"]
    B -- Yes --> C["Return"]
    B -- No --> D["Clear m_model and m_vendor"]
    D --> E["Check if m_size is not empty"]
    E -- Yes --> F["Parse m_size to bytes"]
    F --> G["Convert bytes to GB"]
    G --> H["Round GB to standard sizes"]
    H --> I["Set m_size to 256 GB, 512 GB, 1 TB, or 2 TB"]
    E -- No --> J["End"]
Loading

File-Level Changes

Change Details Files
Refactor updateForHWDevice signature and model check
  • Removed unused devicePath parameter
  • Replaced m_model comparison with an empty product_name check
service/diskoperation/DeviceStorage.cpp
Add disk size normalization logic
  • Convert m_size string to byte value
  • Round byte count to nearest GB
  • Map rounded GB to preset sizes (256 GB, 512 GB, 1 TB, 2 TB)
  • Assign normalized size back to m_size
service/diskoperation/DeviceStorage.cpp
Introduce and apply formatDeviceSize for consistent formatting
  • Implement formatDeviceSize() to standardize size strings
  • Invoke formatDeviceSize() in PartedCore after hardware info update
service/diskoperation/PartedCore.cpp

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Extract the magic thresholds (300, 600, 1200, 2200) into named constants or a configuration to improve readability and ease future adjustments.
  • The size parsing and normalization logic is split between updateForHWDevice and formatDeviceSize, which can lead to inconsistencies; consider centralizing all size conversion and formatting in a single utility method.
  • Disks larger than 2 TB (or values above 2200 GB) aren’t covered by the current logic—add a fallback or extend the threshold rules to handle higher capacities.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Extract the magic thresholds (300, 600, 1200, 2200) into named constants or a configuration to improve readability and ease future adjustments.
- The size parsing and normalization logic is split between updateForHWDevice and formatDeviceSize, which can lead to inconsistencies; consider centralizing all size conversion and formatting in a single utility method.
- Disks larger than 2 TB (or values above 2200 GB) aren’t covered by the current logic—add a fallback or extend the threshold rules to handle higher capacities.

## Individual Comments

### Comment 1
<location> `service/diskoperation/DeviceStorage.cpp:632-634` </location>
<code_context>
+        qint64 bytes = 0;
+        QString sizeStr = m_size.toLower();
+
+        if (sizeStr.contains("bytes")) {
+            sizeStr = sizeStr.split("bytes").first().trimmed();
+            bytes = sizeStr.toLongLong();
+        } else {
+            // Handle GB/TB directly
</code_context>

<issue_to_address>
**issue (bug_risk):** Potential parsing issue for non-numeric byte strings.

Add validation to handle cases where non-numeric characters precede 'bytes', as toLongLong() may not parse these correctly.
</issue_to_address>

### Comment 2
<location> `service/diskoperation/DeviceStorage.cpp:637` </location>
<code_context>
+            bytes = sizeStr.toLongLong();
+        } else {
+            // Handle GB/TB directly
+            double value = sizeStr.split(" ").first().toDouble();
+            if (sizeStr.contains("gb")) {
+                bytes = value * 1000 * 1000 * 1000;
</code_context>

<issue_to_address>
**suggestion:** No fallback for unrecognized units or malformed size strings.

Consider adding error handling or logging for unrecognized or malformed units to prevent silent failures.
</issue_to_address>

### Comment 3
<location> `service/diskoperation/DeviceStorage.cpp:664` </location>
<code_context>
+    }
+}
+
+void DeviceStorage::formatDeviceSize() 
+{
+    static QRegularExpression numRegex("(\\d+)(?:\\.\\d+)?\\s*(TB|GB|MB)");
</code_context>

<issue_to_address>
**suggestion:** Regular expression does not handle lowercase units or extra whitespace.

Make the regex case-insensitive and allow for extra whitespace to ensure all valid unit formats are matched.

```suggestion
    static QRegularExpression numRegex(R"((\d+)(?:\.\d+)?\s*(TB|GB|MB)\s*)", QRegularExpression::CaseInsensitiveOption);
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +632 to +634
if (sizeStr.contains("bytes")) {
sizeStr = sizeStr.split("bytes").first().trimmed();
bytes = sizeStr.toLongLong();
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): Potential parsing issue for non-numeric byte strings.

Add validation to handle cases where non-numeric characters precede 'bytes', as toLongLong() may not parse these correctly.

bytes = sizeStr.toLongLong();
} else {
// Handle GB/TB directly
double value = sizeStr.split(" ").first().toDouble();
Copy link

Choose a reason for hiding this comment

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

suggestion: No fallback for unrecognized units or malformed size strings.

Consider adding error handling or logging for unrecognized or malformed units to prevent silent failures.

max-lvs
max-lvs previously approved these changes Oct 21, 2025
@itsXuSt itsXuSt marked this pull request as ready for review October 23, 2025 05:53
@deepin-ci-robot
Copy link

deepin pr auto review

我来对这个diff进行代码审查:

  1. 语法逻辑:
  • 代码修改基本符合C++语法规范
  • 函数参数改为/*devicePath*/表示该参数未使用,这是合理的处理方式
  • 大小写转换和字符串分割等操作逻辑正确
  1. 代码质量:
  • 增加了对磁盘大小的标准化处理,提高了代码的可维护性
  • 使用了清晰的区间判断来标准化磁盘大小显示
  • 代码缩进和格式保持一致
  • 字符串处理使用了Qt的内置函数,如toLower(), trimmed()等
  1. 代码性能:
  • 字符串操作较多,可能会影响性能,建议优化:
    • 可以减少不必要的字符串分割操作
    • toLongLong()和toDouble()转换可以缓存结果
    • 可以使用正则表达式一次性提取数值和单位
  1. 代码安全:
  • 对输入的size字符串进行了isEmpty()检查,这是一个好的安全实践
  • 数值转换时没有异常处理,建议添加try-catch
  • 硬编码的数值(如200、300、600等)建议定义为常量

改进建议:

// 建议添加这些常量
static const int MIN_DISK_SIZE_GB = 200;
static const int SIZE_256GB_THRESHOLD = 300;
static const int SIZE_512GB_THRESHOLD = 600;
static const int SIZE_1TB_THRESHOLD = 1200;
static const int SIZE_2TB_THRESHOLD = 2200;

void DeviceStorage::updateForHWDevice(const QString &/*devicePath*/)
{
    if (Utils::readContent("/proc/bootdevice/product_name").trimmed().isEmpty())
        return;

    // ... 其他代码保持不变 ...

    // Normalize disk size
    if (!m_size.isEmpty()) {
        qint64 bytes = 0;
        bool ok = false;
        QString sizeStr = m_size.toLower().trimmed();

        try {
            if (sizeStr.contains("bytes")) {
                bytes = sizeStr.split("bytes").first().trimmed().toLongLong(&ok);
            } else {
                // Handle GB/TB directly
                double value = sizeStr.split(" ").first().toDouble(&ok);
                if (ok) {
                    if (sizeStr.contains("gb")) {
                        bytes = static_cast<qint64>(value * 1000 * 1000 * 1000);
                    } else if (sizeStr.contains("tb")) {
                        bytes = static_cast<qint64>(value * 1000 * 1000 * 1000 * 1000);
                    }
                }
            }

            // Convert to standardized format
            if (ok && bytes > 0) {
                // Convert to GB and round to standard sizes
                int gb = qRound(bytes / (1000.0 * 1000 * 1000));
                
                if (gb < MIN_DISK_SIZE_GB) {
                    return;
                } else if (gb <= SIZE_256GB_THRESHOLD) {
                    m_size = "256 GB";
                } else if (gb <= SIZE_512GB_THRESHOLD) {
                    m_size = "512 GB";
                } else if (gb <= SIZE_1TB_THRESHOLD) {
                    m_size = "1 TB";
                } else if (gb <= SIZE_2TB_THRESHOLD) {
                    m_size = "2 TB";
                }
            }
        } catch (...) {
            // 处理可能的转换异常
            return;
        }
    }
}

主要改进点:

  1. 添加了常量定义,提高代码可维护性
  2. 增加了数值转换的错误检查
  3. 添加了异常处理
  4. 使用static_cast确保类型转换安全
  5. 增加了更多的输入验证

这些改进将使代码更加健壮和安全,同时保持原有的功能不变。

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

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

## Individual Comments

### Comment 1
<location> `service/diskoperation/DeviceStorage.cpp:632-634` </location>
<code_context>
+        qint64 bytes = 0;
+        QString sizeStr = m_size.toLower();
+
+        if (sizeStr.contains("bytes")) {
+            sizeStr = sizeStr.split("bytes").first().trimmed();
+            bytes = sizeStr.toLongLong();
+        } else {
+            // Handle GB/TB directly
</code_context>

<issue_to_address>
**issue:** No error handling for non-numeric size strings.

If sizeStr is not a valid number, toLongLong() returns 0, which could cause incorrect results. Please add validation for the conversion.
</issue_to_address>

### Comment 2
<location> `service/diskoperation/DeviceStorage.cpp:636-642` </location>
<code_context>
+            bytes = sizeStr.toLongLong();
+        } else {
+            // Handle GB/TB directly
+            double value = sizeStr.split(" ").first().toDouble();
+            if (sizeStr.contains("gb")) {
+                bytes = value * 1000 * 1000 * 1000;
</code_context>

<issue_to_address>
**suggestion:** Potential locale issue with toDouble conversion.

If size strings may use different decimal separators, explicitly set the locale in toDouble() or validate the input format to avoid conversion errors.

```suggestion
            // Handle GB/TB directly
            QLocale locale(QLocale::C); // Use C locale for consistent decimal separator
            double value = locale.toDouble(sizeStr.split(" ").first());
            if (sizeStr.contains("gb")) {
                bytes = value * 1000 * 1000 * 1000;
            } else if (sizeStr.contains("tb")) {
                bytes = value * 1000 * 1000 * 1000 * 1000;
            }
```
</issue_to_address>

### Comment 3
<location> `service/diskoperation/DeviceStorage.cpp:635-642` </location>
<code_context>
+        } else {
+            // Handle GB/TB directly
+            double value = sizeStr.split(" ").first().toDouble();
+            if (sizeStr.contains("gb")) {
+                bytes = value * 1000 * 1000 * 1000;
+            } else if (sizeStr.contains("tb")) {
+                bytes = value * 1000 * 1000 * 1000 * 1000;
+            }
</code_context>

<issue_to_address>
**suggestion:** No handling for MB or other units.

Consider updating the logic to support MB and other units if they may be encountered.

```suggestion
        } else {
            // Handle KB/MB/GB/TB directly
            QStringList parts = sizeStr.split(" ");
            if (parts.size() == 2) {
                double value = parts[0].toDouble();
                QString unit = parts[1].trimmed();
                if (unit == "kb") {
                    bytes = value * 1000;
                } else if (unit == "mb") {
                    bytes = value * 1000 * 1000;
                } else if (unit == "gb") {
                    bytes = value * 1000 * 1000 * 1000;
                } else if (unit == "tb") {
                    bytes = value * 1000 * 1000 * 1000 * 1000;
                } else {
                    // Unknown unit, fallback to value as bytes
                    bytes = value;
                }
            }
```
</issue_to_address>

### Comment 4
<location> `service/diskoperation/DeviceStorage.cpp:646-659` </location>
<code_context>
+        if (bytes > 0) {
+            // Convert to GB and round to standard sizes
+            int gb = qRound(bytes / (1000.0 * 1000 * 1000));
+            if (gb < 200) {
+                return;
+            } else if (gb <= 300) {
+                m_size = "256 GB";
+            } else if (gb <= 600) {
+                m_size = "512 GB";
+            } else if (gb <= 1200){
+                m_size = "1 TB";
+            } else if (gb <= 2200) {
+                m_size = "2 TB";
+            }
</code_context>

<issue_to_address>
**suggestion:** No fallback for sizes above 2 TB.

For disk sizes over 2 TB, m_size remains unset. Please add a fallback for these cases or clearly document this behavior.

```suggestion
        if (bytes > 0) {
            // Convert to GB and round to standard sizes
            int gb = qRound(bytes / (1000.0 * 1000 * 1000));
            if (gb < 200) {
                return;
            } else if (gb <= 300) {
                m_size = "256 GB";
            } else if (gb <= 600) {
                m_size = "512 GB";
            } else if (gb <= 1200){
                m_size = "1 TB";
            } else if (gb <= 2200) {
                m_size = "2 TB";
            } else {
                m_size = "Over 2 TB";
            }
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +632 to +634
if (sizeStr.contains("bytes")) {
sizeStr = sizeStr.split("bytes").first().trimmed();
bytes = sizeStr.toLongLong();
Copy link

Choose a reason for hiding this comment

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

issue: No error handling for non-numeric size strings.

If sizeStr is not a valid number, toLongLong() returns 0, which could cause incorrect results. Please add validation for the conversion.

Comment on lines +636 to +642
// Handle GB/TB directly
double value = sizeStr.split(" ").first().toDouble();
if (sizeStr.contains("gb")) {
bytes = value * 1000 * 1000 * 1000;
} else if (sizeStr.contains("tb")) {
bytes = value * 1000 * 1000 * 1000 * 1000;
}
Copy link

Choose a reason for hiding this comment

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

suggestion: Potential locale issue with toDouble conversion.

If size strings may use different decimal separators, explicitly set the locale in toDouble() or validate the input format to avoid conversion errors.

Suggested change
// Handle GB/TB directly
double value = sizeStr.split(" ").first().toDouble();
if (sizeStr.contains("gb")) {
bytes = value * 1000 * 1000 * 1000;
} else if (sizeStr.contains("tb")) {
bytes = value * 1000 * 1000 * 1000 * 1000;
}
// Handle GB/TB directly
QLocale locale(QLocale::C); // Use C locale for consistent decimal separator
double value = locale.toDouble(sizeStr.split(" ").first());
if (sizeStr.contains("gb")) {
bytes = value * 1000 * 1000 * 1000;
} else if (sizeStr.contains("tb")) {
bytes = value * 1000 * 1000 * 1000 * 1000;
}

Comment on lines +635 to +642
} else {
// Handle GB/TB directly
double value = sizeStr.split(" ").first().toDouble();
if (sizeStr.contains("gb")) {
bytes = value * 1000 * 1000 * 1000;
} else if (sizeStr.contains("tb")) {
bytes = value * 1000 * 1000 * 1000 * 1000;
}
Copy link

Choose a reason for hiding this comment

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

suggestion: No handling for MB or other units.

Consider updating the logic to support MB and other units if they may be encountered.

Suggested change
} else {
// Handle GB/TB directly
double value = sizeStr.split(" ").first().toDouble();
if (sizeStr.contains("gb")) {
bytes = value * 1000 * 1000 * 1000;
} else if (sizeStr.contains("tb")) {
bytes = value * 1000 * 1000 * 1000 * 1000;
}
} else {
// Handle KB/MB/GB/TB directly
QStringList parts = sizeStr.split(" ");
if (parts.size() == 2) {
double value = parts[0].toDouble();
QString unit = parts[1].trimmed();
if (unit == "kb") {
bytes = value * 1000;
} else if (unit == "mb") {
bytes = value * 1000 * 1000;
} else if (unit == "gb") {
bytes = value * 1000 * 1000 * 1000;
} else if (unit == "tb") {
bytes = value * 1000 * 1000 * 1000 * 1000;
} else {
// Unknown unit, fallback to value as bytes
bytes = value;
}
}

Comment on lines +646 to +659
if (bytes > 0) {
// Convert to GB and round to standard sizes
int gb = qRound(bytes / (1000.0 * 1000 * 1000));
if (gb < 200) {
return;
} else if (gb <= 300) {
m_size = "256 GB";
} else if (gb <= 600) {
m_size = "512 GB";
} else if (gb <= 1200){
m_size = "1 TB";
} else if (gb <= 2200) {
m_size = "2 TB";
}
Copy link

Choose a reason for hiding this comment

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

suggestion: No fallback for sizes above 2 TB.

For disk sizes over 2 TB, m_size remains unset. Please add a fallback for these cases or clearly document this behavior.

Suggested change
if (bytes > 0) {
// Convert to GB and round to standard sizes
int gb = qRound(bytes / (1000.0 * 1000 * 1000));
if (gb < 200) {
return;
} else if (gb <= 300) {
m_size = "256 GB";
} else if (gb <= 600) {
m_size = "512 GB";
} else if (gb <= 1200){
m_size = "1 TB";
} else if (gb <= 2200) {
m_size = "2 TB";
}
if (bytes > 0) {
// Convert to GB and round to standard sizes
int gb = qRound(bytes / (1000.0 * 1000 * 1000));
if (gb < 200) {
return;
} else if (gb <= 300) {
m_size = "256 GB";
} else if (gb <= 600) {
m_size = "512 GB";
} else if (gb <= 1200){
m_size = "1 TB";
} else if (gb <= 2200) {
m_size = "2 TB";
} else {
m_size = "Over 2 TB";
}

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: itsXuSt, max-lvs

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

@itsXuSt
Copy link
Contributor Author

itsXuSt commented Oct 23, 2025

/merge

@deepin-bot deepin-bot bot merged commit d5ec332 into linuxdeepin:release/1071 Oct 23, 2025
18 checks passed
@itsXuSt itsXuSt deleted the 1071 branch November 24, 2025 03:13
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.

3 participants