Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9b35fb4
feat(gui): add all 6 filter dimensions and remove settings tab
airprofly Jul 15, 2026
0c18d5f
fix(gui): add decrypt option to restore tab
airprofly Jul 15, 2026
7e1df45
fix(gui): create timestamped subdir for backup/restore destinations
airprofly Jul 15, 2026
70649fb
fix(gui): remove premature create_directories in backup/restore
airprofly Jul 15, 2026
6d36a52
fix(gui): encrypt/decrypt algorithm name mapping and missing encrypt …
airprofly Jul 15, 2026
42d4931
fix(gui): add password validation to restore tab
airprofly Jul 15, 2026
6d620a5
refactor(gui): auto-detect decrypt algorithm in restore tab
airprofly Jul 15, 2026
9845dd7
refactor(gui): fully auto-detect restore options from filename
airprofly Jul 15, 2026
744a934
chore: add Zone.Identifier to gitignore
airprofly Jul 15, 2026
8629f0b
fix(gui): restore tab now properly reports decryption failure
airprofly Jul 15, 2026
77b81f6
fix(gui): restore failure stays on restore tab for retry
airprofly Jul 15, 2026
91f058d
fix(gui): auto-enable tar pack when encrypt is enabled
airprofly Jul 15, 2026
8298857
fix(gui): remove non-functional metadata/special file checkboxes
airprofly Jul 15, 2026
cafd414
fix(gui): auto-enable tar pack when compress is enabled
airprofly Jul 15, 2026
4406c51
fix(gui): auto-pack fires on checkbox toggle, not on start
airprofly Jul 15, 2026
f741da7
fix(gui): force Tar pack when compress/encrypt toggled, even if Zip w…
airprofly Jul 15, 2026
b128559
chore(gui): simplify auto-Tar log message
airprofly Jul 15, 2026
2daf9d7
fix(gui): prevent backup start when compress/encrypt checked without …
airprofly Jul 15, 2026
c4dedee
fix(gui): FilterDialog now pre-fills all 6 dimensions from inline con…
airprofly Jul 15, 2026
6a1b5e4
docs(gui): add tooltip explaining path glob semantics in filter
airprofly Jul 15, 2026
a1a2295
fix(gui): auto-expand plain path filters to include all children
airprofly Jul 15, 2026
6dac2c2
docs(gui): clarify type filter placeholders, distinguish from name fi…
airprofly Jul 15, 2026
77d5100
fix all gui filters
airprofly Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ ENV/
.env.bak/
.conda-env/

# =============== 静态分析缓存 ===============
.cppcheck-cache/

# =============== 日志文件 ===============
logs/
**/logs/
Expand Down Expand Up @@ -149,4 +152,4 @@ temp/
# =============== 其他 ===============
HELP.md
.mvn/wrapper/maven-wrapper.jar

*Zone.Identifier
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ if(BUILD_GUI AND HAVE_QT6)
src/gui/backup_tab.cpp
src/gui/restore_tab.cpp
src/gui/schedule_tab.cpp
src/gui/settings_tab.cpp
src/gui/backup_worker.cpp
src/gui/progress_widget.cpp
src/gui/log_widget.cpp
Expand All @@ -228,11 +227,11 @@ if(BUILD_GUI AND HAVE_QT6)
src/gui/backup_tab.h
src/gui/restore_tab.h
src/gui/schedule_tab.h
src/gui/settings_tab.h
src/gui/backup_worker.h
src/gui/progress_widget.h
src/gui/log_widget.h
src/gui/filter_dialog.h
src/gui/gui_utils.h
)
set(GUI_RESOURCES
src/gui/resources/app.qrc
Expand Down
245 changes: 245 additions & 0 deletions cppcheck-report.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
src/core/backup_engine.cpp:146:19: style: Variable 'content' can be declared as reference to const [constVariableReference]
auto& content = readResult.value();
^
src/core/restore_engine.cpp:148:19: style: Variable 'content' can be declared as reference to const [constVariableReference]
auto& content = readResult.value();
^
tests/core/backup_engine_test.cpp:68:1: error: syntax error [syntaxError]
TEST_F(BackupEngineTest, BackupBasic) {
^
tests/fs/metadata_test.cpp:44:1: error: syntax error [syntaxError]
TEST_F(MetadataTest, ReadMetadataRegular) {
^
tests/core/restore_engine_test.cpp:77:1: error: syntax error [syntaxError]
TEST_F(RestoreEngineTest, RestoreBasic) {
^
tests/fs/special_file_test.cpp:43:1: error: syntax error [syntaxError]
TEST_F(SpecialFileTest, DetectRegularFile) {
^
tests/pack/tar_packer_test.cpp:149:1: error: syntax error [syntaxError]
TEST_F(TarPackerTest, PackSingleRegularFile) {
^
tests/filter/criteria_filter_test.cpp:35:1: error: syntax error [syntaxError]
TEST(CriteriaFilterTest, IncludePathGlob)
^
tests/compress/compressor_test.cpp:17:1: error: syntax error [syntaxError]
TEST_P(CompressorTest, RoundTripEmpty) {
^
tests/compress/compressor_factory_test.cpp:19:1: error: syntax error [syntaxError]
TEST(BuildCompressorTest, CreateZstd) {
^
tests/pack/zip_packer_test.cpp:151:1: error: syntax error [syntaxError]
TEST_F(ZipPackerTest, FormatName) {
^
tests/crypto/openssl_encryptor_test.cpp:16:1: error: syntax error [syntaxError]
TEST_P(EncryptorTest, RoundTripEmpty) {
^
tests/crypto/encryptor_factory_test.cpp:16:1: error: syntax error [syntaxError]
TEST(BuildEncryptorTest, CreateAes256FullName) {
^
tests/scheduler/ccronexpr_test.cpp:30:1: error: syntax error [syntaxError]
TEST(CcronexprTest, DailyAt2am) {
^
tests/scheduler/retention_policy_test.cpp:31:1: error: syntax error [syntaxError]
TEST(RetentionTest, ParseTimestampInvalidFormat) {
^
build/backer-gui_autogen/MXUWEOXILK/moc_backup_tab.cpp:22:0: error: #error "The header file 'backup_tab.h' doesn't include <QObject>." [preprocessorErrorDirective]
#error "The header file 'backup_tab.h' doesn't include <QObject>."
^
src/gui/main_window.h:21:9: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
private slots:
^
tests/scheduler/backup_scheduler_test.cpp:21:1: error: syntax error [syntaxError]
TEST(SchedulerTest, AddAndListJobs) {
^
src/gui/schedule_tab.h:19:9: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
private slots:
^
src/gui/progress_widget.h:17:8: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
public slots:
^
src/gui/backup_tab.h:35:9: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
private slots:
^
src/gui/log_widget.h:17:8: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
public slots:
^
src/gui/restore_tab.h:28:9: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
private slots:
^
src/gui/backup_worker.h:60:8: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
public slots:
^
src/pack/tar_packer.cpp:67:22: warning: Opposite inner 'if' condition leads to a dead code block. [oppositeInnerCondition]
if (slashPos == 0) break;
^
src/pack/tar_packer.cpp:56:54: note: outer condition: slashPos>0
while (slashPos != std::string::npos && slashPos > 0) {
^
src/pack/tar_packer.cpp:67:22: note: opposite inner condition: slashPos==0
if (slashPos == 0) break;
^
src/gui/filter_dialog.h:52:9: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
private slots:
^
src/pack/tar_packer.cpp:255:14: style: Variable 'pad' can be declared as const array [constVariable]
char pad[kBlockSize] = {};
^
src/pack/tar_packer.cpp:345:10: style: Variable 'end' can be declared as const array [constVariable]
char end[kBlockSize * 2] = {};
^
src/crypto/openssl_encryptor.cpp:26:27: style: The scope of the variable 'buf' can be reduced. [variableScope]
std::array<char, 256> buf{};
^
src/filters/criteria_filter.cpp:202:74: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
&& matchGlob(pathStr, c.pathGlob.value(), true)) {
^
src/filters/criteria_filter.cpp:214:62: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
&& entry.type == c.fileType.value()) {
^
src/filters/criteria_filter.cpp:227:75: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
&& matchGlob(nameStr, c.nameGlob.value(), false)) {
^
src/filters/criteria_filter.cpp:275:73: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
&& entry.metadata.ownerId == c.ownerId.value()) {
^
src/scheduler/backup_scheduler.cpp:58:45: style: Consider using std::count_if algorithm instead of a raw loop. [useStlAlgorithm]
for (char c : cronExpr) { if (c == ' ') fieldCount++; }
^
src/main.cpp:30:0: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
if (v == val) return std::string{};
^
src/cli/commands.cpp:226:24: style: Condition 'resolveUser(options.owner,uid)' is always false [knownConditionTrueFalse]
if (resolveUser(options.owner, uid)) {
^
src/cli/commands.cpp:226:24: note: Calling function 'resolveUser' returns 0
if (resolveUser(options.owner, uid)) {
^
src/cli/commands.cpp:226:24: note: Condition 'resolveUser(options.owner,uid)' is always false
if (resolveUser(options.owner, uid)) {
^
src/cli/commands.cpp:108:57: style: Parameter 'uid' can be declared as reference to const [constParameterReference]
bool resolveUser(std::string const& userName, uint32_t& uid) {
^
src/cli/commands.cpp:728:34: warning: Either the condition 'args.size()<4' is redundant or size of 'args' can be 4. Expression 'args[4]' causes access out of bounds. [containerOutOfBounds]
job.destination = args[4];
^
src/cli/commands.cpp:717:25: note: Assuming that condition 'args.size()<4' is not redundant
if (args.size() < 4) {
^
src/cli/commands.cpp:728:34: note: Access out of bounds
job.destination = args[4];
^
src/cli/commands.cpp:770:29: style: Consider using std::replace_if algorithm instead of a raw loop. [useStlAlgorithm]
if (c == ' ') c = '_';
^
src/cli/commands.cpp:776:13: style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
for (auto const& j : jobs) if (j.id == id) return true;
^
src/cli/commands.cpp:838:34: style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
if (j.id == args[1]) {
^
src/scheduler/backup_scheduler.cpp:118:0: style: The function 'addJob' is never used. [unusedFunction]
BackupScheduler::addJob(ScheduleJob const& job) {
^
src/core/backup_engine.cpp:20:0: style: The function 'backup' is never used. [unusedFunction]
BackupResult BackupEngine::backup(
^
src/fs/path_mapper.cpp:22:0: style: The function 'backupToRelative' is never used. [unusedFunction]
std::filesystem::path PathMapper::backupToRelative(
^
src/compress/build_compressor.cpp:8:0: style: The function 'buildCompressor' is never used. [unusedFunction]
std::unique_ptr<Compressor> buildCompressor(std::string_view name, int level) {
^
src/crypto/build_encryptor.cpp:6:0: style: The function 'buildEncryptor' is never used. [unusedFunction]
std::unique_ptr<Encryptor> buildEncryptor(std::string_view name) {
^
src/compress/lzma_compressor.cpp:13:0: style: The function 'compress' is never used. [unusedFunction]
Expected<void, ErrorCode> LzmaCompressor::compress(
^
src/compress/lzma_compressor.cpp:56:0: style: The function 'decompress' is never used. [unusedFunction]
Expected<void, ErrorCode> LzmaCompressor::decompress(
^
src/crypto/openssl_encryptor.cpp:217:0: style: The function 'decrypt' is never used. [unusedFunction]
Expected<void, ErrorCode> OpenSslEncryptor::decrypt(
^
src/compress/lzma_compressor.cpp:19:0: style: The function 'defaultLevel' is never used. [unusedFunction]

^
src/fs/special_file.cpp:21:0: style: The function 'detectFileType' is never used. [unusedFunction]
Expected<FileType, ErrorCode> detectFileType(std::filesystem::path const& path)
^
src/scheduler/backup_scheduler.cpp:163:0: style: The function 'enableJob' is never used. [unusedFunction]
BackupScheduler::enableJob(std::string_view jobId, bool enabled) {
^
src/crypto/openssl_encryptor.cpp:109:0: style: The function 'encrypt' is never used. [unusedFunction]
Expected<void, ErrorCode> OpenSslEncryptor::encrypt(
^
src/scheduler/schedule_store.cpp:32:0: style: The function 'filePath' is never used. [unusedFunction]
default: out += c;
^
src/storage/local_storage.cpp:159:0: style: The function 'fileSize' is never used. [unusedFunction]
LocalStorage::fileSize(std::filesystem::path const& path)
^
src/scheduler/backup_scheduler.cpp:190:0: style: The function 'findJob' is never used. [unusedFunction]
ScheduleJob const* BackupScheduler::findJob(std::string_view jobId) const {
^
src/storage/local_storage.cpp:42:0: style: The function 'isDirectory' is never used. [unusedFunction]
Expected<bool, ErrorCode> LocalStorage::isDirectory(
^
src/main.cpp:104:0: style: The function 'isRunning' is never used. [unusedFunction]
->check([&](std::string const& /*val*/) { backupHasSizeMin = true; return std::string{}; });
^
src/compress/lzma_compressor.cpp:9:0: style: The function 'isValidLevel' is never used. [unusedFunction]
bool LzmaCompressor::isValidLevel(int level) const {
^
src/storage/local_storage.cpp:71:0: style: The function 'listDirectory' is never used. [unusedFunction]
LocalStorage::listDirectory(std::filesystem::path const& path)
^
src/scheduler/backup_scheduler.cpp:200:0: style: The function 'listJobs' is never used. [unusedFunction]
std::vector<JobInfo> BackupScheduler::listJobs() const {
^
src/scheduler/backup_scheduler.cpp:86:0: style: The function 'makeSnapshotPath' is never used. [unusedFunction]
BackupScheduler::makeSnapshotPath(std::filesystem::path const& base) {
^
src/fs/metadata.cpp:192:0: style: The function 'metadataFromJson' is never used. [unusedFunction]
std::optional<Metadata> metadataFromJson(std::string const& json)
^
src/fs/metadata.cpp:176:0: style: The function 'metadataToJson' is never used. [unusedFunction]
std::string metadataToJson(Metadata const& meta)
^
src/crypto/key_derivation.cpp:56:0: style: The function 'randomBytes' is never used. [unusedFunction]
Expected<std::vector<char>, ErrorCode> KeyDerivation::randomBytes(size_t length) {
^
src/storage/local_storage.cpp:96:0: style: The function 'readFile' is never used. [unusedFunction]
LocalStorage::readFile(std::filesystem::path const& path)
^
src/fs/special_file.cpp:61:0: style: The function 'readSymlink' is never used. [unusedFunction]
Expected<std::string, ErrorCode> readSymlink(std::filesystem::path const& path)
^
src/scheduler/backup_scheduler.cpp:146:0: style: The function 'removeJob' is never used. [unusedFunction]
BackupScheduler::removeJob(std::string_view jobId) {
^
src/core/restore_engine.cpp:19:0: style: The function 'restore' is never used. [unusedFunction]
BackupResult RestoreEngine::restore(
^
src/scheduler/backup_scheduler.cpp:290:0: style: The function 'run' is never used. [unusedFunction]
void BackupScheduler::run() {
^
src/scheduler/schedule_store.cpp:290:0: style: The function 'save' is never used. [unusedFunction]
ScheduleStore::save(std::vector<ScheduleJob> const& jobs) {
^
src/scheduler/retention_policy.cpp:61:0: style: The function 'scanSnapshots' is never used. [unusedFunction]
RetentionPolicy::scanSnapshots(std::filesystem::path const& directory) {
^
src/scheduler/retention_policy.cpp:90:0: style: The function 'selectForRemoval' is never used. [unusedFunction]
RetentionPolicy::selectForRemoval(
^
src/crypto/build_encryptor.cpp:34:0: style: The function 'suffix' is never used. [unusedFunction]

^
src/storage/local_storage.cpp:126:0: style: The function 'writeFile' is never used. [unusedFunction]
LocalStorage::writeFile(
^
nofile:0:0: information: Active checkers: There was critical errors (use --checkers-report=<filename> to see details) [checkersReport]

41 changes: 41 additions & 0 deletions cppcheck-suppressions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# ========== Backer Project cppcheck Suppressions ==========
# 格式:[error-id]:[file-pattern]:[line]
# file-pattern 中 * 通配任意字符

# ========== 第三方依赖(FetchContent 拉取),__deps 目录全部跳过 ==========
*:build/_deps/*

# ========== 第三方库已知风格问题 ==========
# ccronexpr — C 代码库,不动
*:src/scheduler/ccronexpr.c
*:src/scheduler/ccronexpr.h

# ========== GUI 相关 ==========
# Qt moc 生成的调用 cppcheck 看不见
unusedFunction:src/gui/*
# Qt 信号/槽参数风格
constParameter:src/gui/*
constVariable:src/gui/*
constParameterReference:src/gui/*
# Qt 元对象系统
noOperatorEq:src/gui/*
noCopyConstructor:src/gui/*
noDestructor:src/gui/*
uninitMemberVar:src/gui/*

# ========== 自研基础设施(设计意图明确) ==========
# Expected<T,E> 的隐式构造函数是故意设计,用于便捷返回 T 或 E
noExplicitConstructor:src/core/expected.h
# span 的隐式构造遵循 std::span 惯例
noExplicitConstructor:src/core/span.h

# ========== 已知误报 ==========
# criteria_filter.cpp: queryDims() 在初始化赋值后通过 FilterQuery 填充这些变量
# cppcheck 静态分析看不到过滤查询的运行时效果
knownConditionTrueFalse:src/filters/criteria_filter.cpp

# ========== informational(非告警,--enable=all 默认包含) ==========
normalCheckLevelMaxBranches:*

# ========== 系统头 ==========
missingIncludeSystem
Loading
Loading