diff --git a/rebase-420/dd05477.md b/rebase-420/dd05477.md new file mode 100644 index 000000000..c64ee0743 --- /dev/null +++ b/rebase-420/dd05477.md @@ -0,0 +1,70 @@ +# Cherry-pick 冲突解决报告: `dd05477` + +- **原始 commit**: `dd05477` feat: add SetDefaultFS to allow replacing the global filesystem implementation +- **作者**: tuxedomm, 2026-04-09 +- **新 commit**: `4d84994` +- **目标分支**: `feat/main_rebased_420`(基于 `larksuite/cli` 最新 main) + +## 改动范围 + +10 个文件, +179 / -70: + +- **新增**: `cmd/build.go`, `cmd/init.go` +- **修改**: `cmd/root.go`, `cmd/root_integration_test.go`, `internal/cmdutil/factory_default.go`, `internal/cmdutil/factory_default_test.go`, `internal/cmdutil/factory_http_test.go`, `internal/cmdutil/iostreams.go`, `internal/credential/default_provider.go`, `internal/credential/integration_test.go` + +核心意图: +- 把 `cmd.Execute()` 里的 root 命令组装逻辑抽取到新文件 `cmd/build.go` 的 `buildInternal()`, 并暴露 `Build()` 作为库入口 +- 引入 `cmd/init.go` 里的 `SetDefaultFS(fs vfs.FS)` 允许调用方在 `Build/Execute` 之前替换全局 fs +- `cmdutil.NewDefault(inv)` 签名调整为 `NewDefault(streams *IOStreams, inv InvocationContext)` +- `credentialDeps.Keychain` 从 `keychain.KeychainAccess` 改为 `func() keychain.KeychainAccess`(惰性读取, 允许构造后替换) +- `cmdutil.SystemIO()` 新函数封装对真实 stdio 的引用 + +## 冲突情况 + +只有一个文件冲突: `cmd/root.go`(2 处) + +| 位置 | HEAD(main) | fork(dd05477) | +|---|---|---| +| imports 段 | 保留 `cmd/api`, `cmd/auth`, `cmd/completion`, `cmdconfig`, `cmd/doctor`, `cmd/profile`, `cmd/schema`, `cmd/service`, `cmdupdate`, `shortcuts` 等 | 全部删除(这些 import 随 Execute 函数体一起搬去新文件 `cmd/build.go`)| +| `Execute()` 函数体 | 完整包含 Factory 构造 + rootCmd 构造 + 子命令注册 + strict-mode 剪枝 | 精简为 `f, rootCmd := buildInternal(context.Background(), inv)` | + +### 为什么会冲突 + +fork 的 dd05477 比 fork 之前落后 main 很多 commit, 而 main 上(比如 PR #391)在 fork 不知道的情况下加了 `rootCmd.AddCommand(cmdupdate.NewCmdUpdate(f))` 这一行 —— 它处于 fork 想整体搬走的那段代码里。git 无法自动判断这一行应该保留还是跟着搬, 所以报冲突。 + +## 解决方案 + +**两处冲突都采用 fork 的重构结构**(把 imports / 组装逻辑搬去 `cmd/build.go`), 但在 `cmd/build.go` 的 `buildInternal()` 里**追加**了 main 新增的 update 命令。 + +### 具体改动 + +在 `cmd/build.go` 里: + +```go +// imports 段补上 +cmdupdate "github.com/larksuite/cli/cmd/update" + +// 在 rootCmd.AddCommand(completion.NewCmdCompletion(f)) 之后追加 +rootCmd.AddCommand(cmdupdate.NewCmdUpdate(f)) +``` + +如果不这样做, 就会丢失 main PR #391 引入的 `lark-cli update` 子命令。 + +## 非冲突文件处理 + +其余 9 个文件的 patch 全部直接应用, 无语义冲突: + +- `cmd/build.go`, `cmd/init.go`: 新增文件 +- `cmd/root_integration_test.go`, `internal/cmdutil/factory_default_test.go`, `internal/cmdutil/factory_http_test.go`, `internal/credential/integration_test.go`: 跟随签名变更调整调用方(`NewDefault(nil, ...)`、`cachedHttpClientFunc(&Factory{...})` 等) +- `internal/cmdutil/factory_default.go`, `internal/cmdutil/iostreams.go`, `internal/credential/default_provider.go`: 签名/结构体字段类型调整 +- `cmd/root.go`: 冲突段外其余部分(update 检查、错误处理等)保持原样 + +## 验证 + +- `go build ./...` 通过 +- `go test ./cmd/... ./internal/cmdutil/... ./internal/credential/...` 全部通过 + +## 依赖 + +- `internal/vfs` 包(`DefaultFS`、`OsFs`、`FS` interface)在 main 上已存在, `SetDefaultFS` 要切换的全局状态有完整基础 +- `cmdupdate` 包(main PR #391)已存在