Files
BakNRet/BakNRet/BakNRet.psm1
T
Shuery 2ad7987ffe refactor: Common.psm1 拆成 BakNRet/{Public,Private},一函数一文件 + 薄加载器
3152 行、66 个函数的单文件模块拆成:
  BakNRet\BakNRet.psd1   模块清单:FunctionsToExport 是显式白名单(62 个名字)
  BakNRet\BakNRet.psm1   加载器:点源顺序的唯一一处声明
  BakNRet\Public\*.ps1   62 个对外函数,一函数一文件,文件名 = 函数名
  BakNRet\Private\*.ps1  4 个内部函数 + State.ps1(模块级状态集中一处)

为什么是一函数一文件:这是社区里脚本模块的主流形态(调研实测:winutil 79 个、
Terminal-Icons 24 个、ModuleBuilder 23 个,全部如此)。收益是改动落在小文件里、diff 按职责
可读、模块级状态有唯一去处。

为什么这不算"打散":模块内 dot-source 的文件共享同一个模块作用域(实测确认),所以
"按顺序点源 67 个文件"与"点源一个大文件"在语义上等价;顺序只在加载器里出现一次,
tools\Build-BakNRetModule.ps1 从那里读出顺序就能拼回单文件 —— 本次产物 dist\BakNRet.psm1
3240 行、两个版本都解析零错。

新增一条断言把这条承诺钉住:加载器点源的文件集合必须与磁盘一致、导出名单必须与
Public\ 一一对应。漏一个文件或漏一个名字就是静默少一个函数 —— 而那种错在运行时只表现为
"找不到命令"。

引用更新:11 个文件里的 Common.psm1 改成 BakNRet\BakNRet.psd1(走清单导入,
FunctionsToExport 才真的说了算);Common.psm1 直接删除,不留转发垫片。

验收:test.ps1 9/9 全绿(7 与 5.1),98 个文件两版解析零错,276 个断言原样通过 ——
这次搬家没有改变任何可观察行为。
2026-09-27 09:34:10 +08:00

201 lines
8.7 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
BakNRet —— 备份 / 恢复脚本的公共功能模块。
.DESCRIPTION
提供日志(控制台 + 落盘)、外部命令调用(可取得真实退出码)、
BackupList.txt 语法解析、归档命名与逆向解析、目录摘要、manifest 读写、
磁盘剩余空间查询等公共能力。
兼容 Windows PowerShell 5.1 与 PowerShell 7.x:
* 不使用 ?? / 三元运算符 / Join-String / -AsHashtable 等 6.0+ 语法;
* 不使用 ProcessStartInfo.ArgumentList(5.1 上不存在),改为自行构造命令行。
模块内出现的备份清单语法(BackupList.txt 每一行):
[+|-] <软件名 或 绝对路径> [修饰符...] [# 说明]
[:: <Absolute\Path>] [:- <模式>[,...]] [:+ <包含项>[,...]]
[:encrypt | :!encrypt] [@ <Key>='<Value>']
标记(必须是独立的空白分隔记号,前后都要有空格):
+ 仅备份,不恢复(Restore.ps1 跳过)
- 仅恢复,不备份(Backup.ps1 跳过)
:: 覆盖 Path,等价于 `@ Path='...'`
:- 排除模式,等价于 `@ Exclude='...'`
:+ 追加包含项(<归档内相对路径>:<宿主机绝对路径>),等价于 `@ Include='...'`
:encrypt 该条目加密(`@ Encrypt='$true'`)
:!encrypt 该条目不加密(`@ Encrypt='$false'`)
@ Key='值' 覆盖 SoftwareCatalog.psd1 里的同名默认字段
兼容的历史写法:`@encrypt` / `@!encrypt` / `@pathname` / `@root=<名>`,
以及用双引号包住路径或模式值。
归档内布局(SoftwareCatalog.psd1 的 Slot 是包内的一层目录):
软件名条目 -> <Slot>\<该 Path 的内容>(Path 是文件时就是名为 <Slot> 的文件)
手写路径 -> <路径末级名>\...(历史布局,不变)
#>
# ----------------------------------------------------------------------------
# 加载器:下面这份点源顺序是**唯一**一份顺序声明。
#
# 每个函数一个文件,文件名 = 函数名;要合回单个 .psm1(发布形态,或做代码签名时需要),
# 跑 tools\Build-BakNRetModule.ps1 —— 它从本文件里读出顺序,所以顺序不需要维护两遍。
# ----------------------------------------------------------------------------
. (Join-Path $PSScriptRoot 'Private\State.ps1')
# ---- 日志 ----
. (Join-Path $PSScriptRoot 'Public\Set-BaknretDebug.ps1')
. (Join-Path $PSScriptRoot 'Public\Start-BaknretLog.ps1')
. (Join-Path $PSScriptRoot 'Public\Stop-BaknretLog.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretLogPath.ps1')
. (Join-Path $PSScriptRoot 'Public\Write-Log.ps1')
# ---- 运行锁 ----
. (Join-Path $PSScriptRoot 'Public\Get-BaknretRunLockPath.ps1')
. (Join-Path $PSScriptRoot 'Public\Enter-BaknretRunLock.ps1')
. (Join-Path $PSScriptRoot 'Public\Exit-BaknretRunLock.ps1')
# ---- 环境 ----
. (Join-Path $PSScriptRoot 'Public\Test-Administrator.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretFreeSpaceGB.ps1')
# ---- 外部命令 ----
. (Join-Path $PSScriptRoot 'Public\ConvertTo-NativeArgumentString.ps1')
. (Join-Path $PSScriptRoot 'Public\Invoke-ExternalCommand.ps1')
. (Join-Path $PSScriptRoot 'Public\Resolve-CompressionTool.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-Optimized7zArgument.ps1')
# ---- BackupList.txt 解析 ----
. (Join-Path $PSScriptRoot 'Public\Split-BaknretToken.ps1')
. (Join-Path $PSScriptRoot 'Public\Remove-BaknretQuote.ps1')
. (Join-Path $PSScriptRoot 'Public\Test-BaknretMarker.ps1')
. (Join-Path $PSScriptRoot 'Public\ConvertFrom-BaknretPatternList.ps1')
. (Join-Path $PSScriptRoot 'Public\ConvertFrom-BackupListLine.ps1')
. (Join-Path $PSScriptRoot 'Public\Test-LiteralPath.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretRegexExclude.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretExcludeArgument.ps1')
. (Join-Path $PSScriptRoot 'Public\Split-BaknretPatternScope.ps1')
. (Join-Path $PSScriptRoot 'Public\Merge-BaknretExcludeArgument.ps1')
# ---- 软件名录(SoftwareCatalog.psd1) ----
. (Join-Path $PSScriptRoot 'Public\Resolve-CatalogPath.ps1')
. (Join-Path $PSScriptRoot 'Public\Format-CatalogName.ps1')
. (Join-Path $PSScriptRoot 'Private\Test-BaknretMapKey.ps1')
. (Join-Path $PSScriptRoot 'Private\Get-BaknretMapValue.ps1')
. (Join-Path $PSScriptRoot 'Private\Get-BaknretMapKeys.ps1')
. (Join-Path $PSScriptRoot 'Public\Expand-CatalogPathText.ps1')
. (Join-Path $PSScriptRoot 'Private\Import-BaknretDataFile.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-SoftwareCatalog.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-ArchiveTopLevelNames.ps1')
. (Join-Path $PSScriptRoot 'Public\Find-ChildDirectoryByName.ps1')
# ---- 归档命名与路径还原 ----
. (Join-Path $PSScriptRoot 'Public\Get-ItemArchiveName.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretArchiveTopName.ps1')
. (Join-Path $PSScriptRoot 'Public\New-BaknretArchiveItem.ps1')
. (Join-Path $PSScriptRoot 'Public\New-BaknretJunction.ps1')
. (Join-Path $PSScriptRoot 'Public\Remove-BaknretJunction.ps1')
. (Join-Path $PSScriptRoot 'Public\New-BaknretArchiveStaging.ps1')
. (Join-Path $PSScriptRoot 'Public\Remove-BaknretArchiveStaging.ps1')
. (Join-Path $PSScriptRoot 'Public\Resolve-BackupEntry.ps1')
. (Join-Path $PSScriptRoot 'Public\Write-BackupEntryPlan.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BackupBaseName.ps1')
. (Join-Path $PSScriptRoot 'Public\Convert-BackupFileNameToPath.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-FolderSummary.ps1')
# ---- manifest.json ----
. (Join-Path $PSScriptRoot 'Public\Read-BaknretManifest.ps1')
. (Join-Path $PSScriptRoot 'Public\Sync-BaknretManifestArchive.ps1')
. (Join-Path $PSScriptRoot 'Public\Write-BaknretManifest.ps1')
# ---- 归档原子替换 ----
. (Join-Path $PSScriptRoot 'Public\Move-BaknretArchiveIntoPlace.ps1')
# ---- 安全描述符(NTFS 属主 / ACL) ----
. (Join-Path $PSScriptRoot 'Public\Enable-BaknretPrivilege.ps1')
. (Join-Path $PSScriptRoot 'Public\ConvertTo-BaknretWildcardPattern.ps1')
. (Join-Path $PSScriptRoot 'Public\Test-BaknretPathExcluded.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretAceSignatureList.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretSecuritySddlWithStale.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretSecurityRecord.ps1')
. (Join-Path $PSScriptRoot 'Public\Test-BaknretSecurityRecordNeeded.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretSecurityRecords.ps1')
. (Join-Path $PSScriptRoot 'Public\Write-BaknretAtomicText.ps1')
. (Join-Path $PSScriptRoot 'Public\Save-BaknretSecuritySidecar.ps1')
. (Join-Path $PSScriptRoot 'Public\Read-BaknretSecuritySidecar.ps1')
. (Join-Path $PSScriptRoot 'Public\Convert-BaknretSidMap.ps1')
. (Join-Path $PSScriptRoot 'Public\Set-BaknretObjectSecurity.ps1')
. (Join-Path $PSScriptRoot 'Public\Restore-BaknretSecurity.ps1')
# ---- 配置 ----
. (Join-Path $PSScriptRoot 'Public\Get-BaknretConfig.ps1')
. (Join-Path $PSScriptRoot 'Public\Get-BaknretPassword.ps1')
Export-ModuleMember -Function @(
'Enter-BaknretRunLock',
'Exit-BaknretRunLock',
'Get-BaknretRunLockPath',
'Set-BaknretDebug',
'Start-BaknretLog',
'Stop-BaknretLog',
'Get-BaknretLogPath',
'Write-Log',
'Test-Administrator',
'Get-BaknretFreeSpaceGB',
'ConvertTo-NativeArgumentString',
'Invoke-ExternalCommand',
'Resolve-CompressionTool',
'Get-Optimized7zArgument',
'Split-BaknretToken',
'Remove-BaknretQuote',
'Test-BaknretMarker',
'ConvertFrom-BaknretPatternList',
'ConvertFrom-BackupListLine',
'Test-LiteralPath',
'Get-BaknretRegexExclude',
'Get-BaknretExcludeArgument',
'Split-BaknretPatternScope',
'Merge-BaknretExcludeArgument',
'Resolve-CatalogPath',
'Get-SoftwareCatalog',
'Find-ChildDirectoryByName',
'Format-CatalogName',
'Expand-CatalogPathText',
'Get-ArchiveTopLevelNames',
'Get-BaknretArchiveTopName',
'New-BaknretArchiveItem',
'New-BaknretJunction',
'Remove-BaknretJunction',
'New-BaknretArchiveStaging',
'Remove-BaknretArchiveStaging',
'Get-ItemArchiveName',
'Resolve-BackupEntry',
'Write-BackupEntryPlan',
'Get-BackupBaseName',
'Convert-BackupFileNameToPath',
'Get-FolderSummary',
'Read-BaknretManifest',
'Write-BaknretManifest',
'Sync-BaknretManifestArchive',
'Move-BaknretArchiveIntoPlace',
'Enable-BaknretPrivilege',
'ConvertTo-BaknretWildcardPattern',
'Test-BaknretPathExcluded',
'Get-BaknretAceSignatureList',
'Get-BaknretSecuritySddlWithStale',
'Get-BaknretSecurityRecord',
'Test-BaknretSecurityRecordNeeded',
'Get-BaknretSecurityRecords',
'Write-BaknretAtomicText',
'Save-BaknretSecuritySidecar',
'Read-BaknretSecuritySidecar',
'Convert-BaknretSidMap',
'Set-BaknretObjectSecurity',
'Restore-BaknretSecurity',
'Get-BaknretConfig',
'Get-BaknretPassword'
)