feat: 新增 disk usage 内置命令(跨平台 du 等价)

- 注册表新增 Variant.Builtin 内置动作,与 Argv 互斥并参与平台匹配
- disk.usage 支持位置参数与 --path/--path=,输出按大小降序并带合计
- Unix 用设备号实现 -x 不跨文件系统,Windows 降级为不跟随 reparse point
- list/help/explain 支持展示内置动作,补充单元与 CLI 测试、README
This commit is contained in:
2026-10-31 13:11:24 +08:00
parent 7d9852958f
commit 84f7361396
12 changed files with 672 additions and 9 deletions
+75
View File
@@ -3,6 +3,7 @@ package cli
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
@@ -241,6 +242,80 @@ func TestParseLeafArgs(t *testing.T) {
}
}
func TestDiskUsageCommandThroughCLI(t *testing.T) {
root := t.TempDir()
if err := os.WriteFile(filepath.Join(root, "a.bin"), bytes.Repeat([]byte("x"), 4096), 0o644); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(root, "sub"), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(root, "sub", "b.bin"), bytes.Repeat([]byte("x"), 1024), 0o644); err != nil {
t.Fatal(err)
}
app, stdout, stderr := testApp(centos("docker"))
if code := app.Execute([]string{"disk", "usage", root}); code != 0 {
t.Fatalf("exit code = %d, stderr=%s", code, stderr.String())
}
out := stdout.String()
for _, want := range []string{"4.0K", "1.0K", "a.bin", "sub", "总计 " + root} {
if !strings.Contains(out, want) {
t.Errorf("disk usage output missing %q:\n%s", want, out)
}
}
}
func TestDiskUsageAcceptsPathFlagThroughCLI(t *testing.T) {
root := t.TempDir()
app, stdout, stderr := testApp(centos("docker"))
if code := app.Execute([]string{"disk", "usage", "--path", root}); code != 0 {
t.Fatalf("exit code = %d, stderr=%s", code, stderr.String())
}
if !strings.Contains(stdout.String(), "总计 "+root) {
t.Errorf("unexpected output:\n%s", stdout.String())
}
}
func TestDiskUsageRequiresPathThroughCLI(t *testing.T) {
app, _, stderr := testApp(centos("docker"))
if code := app.Execute([]string{"disk", "usage"}); code != 1 {
t.Fatalf("exit code = %d, want 1", code)
}
if !strings.Contains(stderr.String(), "必须提供路径") {
t.Errorf("stderr = %s", stderr.String())
}
}
func TestDiskUsageDryRunDoesNotTouchPath(t *testing.T) {
app, stdout, _ := testApp(centos("docker"))
code := app.Execute([]string{"disk", "usage", "/path/that/does/not/exist", "--dry-run"})
if code != 0 {
t.Fatalf("exit code = %d", code)
}
out := stdout.String()
if !strings.Contains(out, "(内置) disk.usage /path/that/does/not/exist") {
t.Errorf("dry-run output missing builtin plan:\n%s", out)
}
if strings.Contains(out, "无法访问") {
t.Errorf("dry-run should not execute the builtin:\n%s", out)
}
}
func TestDiskUsageHelp(t *testing.T) {
app, stdout, _ := testApp(centos("docker"))
if code := app.Execute([]string{"disk", "usage", "-h"}); code != 0 {
t.Fatalf("exit code = %d", code)
}
if !strings.Contains(stdout.String(), "(内置) disk.usage") {
t.Errorf("help output missing builtin target:\n%s", stdout.String())
}
}
// TestCLIHelperProcess is re-executed as a child to verify exit-code passthrough.
func TestCLIHelperProcess(t *testing.T) {
if os.Getenv("KOPSC_CLI_HELPER") != "1" {