gogcligog batch begin详解:创建持久化 Google Docs 请求批次
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
导读
gog batch begin是 gogcli(Google Workspace in your terminal)中批量文档编辑流程的起点命令:它在本机创建一个“持久化请求批次”(persisted request batch),随后你可以陆续把多条 Docs 编辑操作追加进该批次,最后以一次 revision-locked 的documents.batchUpdate原子提交。读完本文,你将掌握gog batch begin的完整用法、全部参数语义、底层实现原理,以及与batch end、--batch队列机制配合的实战工作流。
一、gog batch子命令全景:begin 在整个流程中的位置
gog batch是一组围绕 Google Docs 批量编辑的命令族,共 6 个子命令,begin是整个生命周期中的第一步:
| 子命令 | 别名 | 功能 |
|---|---|---|
gog batch begin | — | 创建一个持久化请求批次(本文主题) |
gog batch list | ls | 列出已持久化的请求批次 |
gog batch show | — | 查看某个请求批次的内容 |
gog batch end | submit | 提交并删除请求批次 |
gog batch abort | rm, delete | 不提交,直接删除请求批次 |
gog batch prune | — | 删除过期的请求批次(默认--older-than 72h) |
这些命令在 internal/cmd/batch.go 中统一注册,结构清晰:
type BatchCmd struct { Begin BatchBeginCmd `cmd:"" help:"Begin a persisted request batch"` List BatchListCmd `cmd:"" aliases:"ls" ...` Show BatchShowCmd `cmd:"" ...` End BatchEndCmd `cmd:"" aliases:"submit" ...` Abort BatchAbortCmd `cmd:"" aliases:"rm,delete" ...` Prune BatchPruneCmd `cmd:"" ...` }批次的典型生命周期为:begin创建 → 多个 Docs 命令通过--batch <id>追加请求 →show检查 →end原子提交;若中途放弃则abort。更完整的流程说明见 docs/docs-batch.md。
二、基本用法与核心参数
gog batch begin的命令签名如下:
gog batch begin --doc=STRING [flags]其中--doc是必填参数,用来指定本次批次将要操作的目标 Google Doc。另有--name与--service两个批次自身的专属参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--doc | string | — | Google Doc ID(必填) |
--name | string | — | 可选的批次标签(batch label) |
--service | string | docs | Google API 服务名,当前枚举仅支持docs |
对应源码定义在 internal/cmd/batch.go:
type BatchBeginCmd struct { Service string `name:"service" help:"Google API service" enum:"docs" default:"docs"` DocID string `name:"doc" required:"" help:"Google Doc ID"` Name string `name:"name" help:"Optional batch label"` }一个最小可用的创建命令:
gog batch begin --doc=1AbC...xyz带标签与账户的完整形式(推荐在脚本中显式指定账户):
BATCH_ID="$(gog --account you@example.com batch begin --service docs --doc <docId> --name "weekly update")" echo "$BATCH_ID"三、完整 Flags 参考(继承自 schema)
gog batch begin继承并支持以下全部 flags(表格来自gog schema --json自动生成的官方文档,对应 docs/commands/gog-batch-begin.md):
| Flag | 类型 | 默认值 | 帮助 |
|---|---|---|---|
--access-token | string | 直接使用提供的 access token(绕过存储的 refresh token;token 约 1 小时后过期) | |
-a--account--acct | string | 认证的 Google API 命令使用的账户 email、别名或auto | |
--client | string | OAuth client 名称(选择存储的凭据与 token 桶) | |
--color | string | auto | 颜色输出:auto\|always\|never |
--disable-commands | string | 逗号分隔的禁用命令列表;支持点路径 | |
--doc | string | Google Doc ID(必填) | |
-n--dry-run--dryrun--noop--preview | bool | 不做任何更改;打印预期动作并以成功状态退出 | |
--enable-commands | string | 逗号分隔的启用命令前缀列表;支持点路径(限制 CLI) | |
--enable-commands-exact | string | 逗号分隔的精确启用命令列表;支持点路径且父命令不会启用子命令 | |
-y--force--assume-yes--yes | bool | 跳过破坏性命令的确认提示 | |
--gmail-no-send | bool | false | 阻止 Gmail 发送操作(Agent 安全) |
-h--help | kong.helpFlag | 显示上下文相关的帮助信息 | |
--home | string | 覆盖 gogcli 配置/数据/状态/缓存根目录(等价于GOG_HOME) | |
-j--json--machine | bool | false | 向 stdout 输出 JSON(最适合脚本化) |
--name | string | 可选的批次标签 | |
--no-input--non-interactive--noninteractive | bool | 永不提示;直接失败(适合 CI) | |
-p--plain--tsv | bool | false | 向 stdout 输出稳定、可解析的文本(TSV;无颜色) |
--quota-project | string | 为 API 用量计费的 Google Cloud 项目(作为X-Goog-User-Project发送;某些 API 配合--access-token或 ADC 时需要) | |
--readonly | bool | false | 运行时阻止变更类 API 请求;auth add也会请求只读 OAuth scope |
--results-only | bool | JSON 模式下仅输出主要结果(丢弃如nextPageToken之类的信封字段) | |
--select--pick--project | string | JSON 模式下选择逗号分隔的字段(尽力而为;支持点路径) | |
--service | string | docs | Google API 服务 |
-v--verbose | bool | 启用详细日志 | |
--version | kong.VersionFlag | 打印版本并退出 | |
--wrap-untrusted | bool | false | 在 JSON/raw 输出中,将拉取的文本字段包装进外部不可信内容标记 |
其中--doc为命令必填参数(required:""),其他 flags 均来自根级共享配置。
四、输出约定:为什么文本模式只打印 UUID
gog batch begin的输出与输出模式(outfmt)密切相关:
- 文本 / plain / TSV 模式:只向 stdout 打印一行批次 UUID,例如
0192f2b1-...,因此用命令替换捕获批次 ID 时结果稳定,不会混入其他字符; - JSON 模式(
--json/--machine):输出完整的批次State结构(见下一节),便于脚本解析。
对应实现位于 internal/cmd/batch.go:
if outfmt.IsJSON(ctx) { return outfmt.WriteJSON(ctx, stdoutWriter(ctx), state) } ui.FromContext(ctx).Out().Println(state.BatchID)这也是官方推荐BATCH_ID="$(gog batch begin ...)"这种命令替换写法的原因:文本模式输出纯净、无前缀无后缀。
五、源码级原理:begin 到底做了什么
gog batch begin的核心执行逻辑在BatchBeginCmd.Run(internal/cmd/batch.go),共分五步:
- 校验
--doc:strings.TrimSpace后若为空直接返回empty --doc用法错误; - 干跑支持:若带有
--dry-run等标志,调用dryRunExit(ctx, flags, "batch.begin", ...),只输出预期动作(service、doc_id、name)而不创建任何批次,并以成功状态退出; - 账户与客户端解析:
requireAccount(flags)确定账户,resolveClientForEmail解析 OAuth client——被选中的账户与 client 会被记录进批次身份; - 打开批次仓库:
newDocsBatchStore(ctx)基于状态目录的batches/子目录创建 docsbatch.Repository,必要时创建目录并持有跨进程互斥锁; - 创建批次状态并落盘:
store.Create(...)生成批次并写入磁盘。
批次状态(State)结构
批次在本地以 JSON 文件持久化,核心字段定义在 internal/docsbatch/repository.go:
type State struct { BatchID string `json:"batch_id"` Name string `json:"name,omitempty"` Service string `json:"service"` DocumentID string `json:"doc_id"` Account string `json:"account"` Client string `json:"client"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` RequiredRevisionID string `json:"required_revision_id,omitempty"` Requests []RequestEntry `json:"requests"` }值得注意的两点:
begin阶段不会读取文档,也不会固定 revision:Create(internal/docsbatch/repository.go)只记录账户、client、目标文档与时间戳,Requests初始为空。首次排队的变更操作才会解析位置并记录文档 revision,因为那时才开始解析请求位置;- 批次 ID 使用 UUID v7 生成(
uuid.NewV7(),见 internal/docsbatch/repository.go),且写入前会再次ValidateID校验,读取时也会校验“文件中存储的 batch ID 必须与文件名一致”(ErrStoredIDMismatch),防止状态目录被篡改。
落盘与权限
批次文件存放在状态目录的batches/子目录下(路径由commandLayout解析,见 internal/cmd/docs_batch_store.go)。仓库层保证:
batches/目录权限为0700;- 每个批次 JSON 文件与锁文件权限为
0600(writeUnlocked中显式传入0o600,见 internal/docsbatch/repository.go); - 所有写操作通过目录内
.lock文件的跨进程互斥锁串行化,默认锁超时 5 秒(defaultLockTimeout)。
由于批次中的请求可能包含文档文本、链接、email 等敏感内容,官方文档明确提示:请把状态目录当作敏感数据目录对待。
六、与后续命令的完整协作流程
begin单独使用没有意义,它构建的批次要配合--batch <id>队列机制与batch end提交,形成完整闭环:
# 1. 创建批次,捕获 UUID BATCH_ID="$(gog --account you@example.com batch begin --service docs --doc <docId> --name "weekly update")" # 2. 陆续追加操作(支持 docs write/update/insert/delete/format/cell-style 等可直接组合的变更) gog --account you@example.com docs insert <docId> "Status: ready" --index 1 --batch "$BATCH_ID" gog --account you@example.com docs format <docId> --match "Status: ready" --bold --batch "$BATCH_ID" # 3. 检查批次的 wire 载荷 gog batch show "$BATCH_ID" --json # 4. 干跑验证(不真正提交) gog --dry-run batch end "$BATCH_ID" --json # 5. 原子提交 gog batch end "$BATCH_ID"关于提交阶段的三个要点(详见 docs/docs-batch.md 与 gog batch end):
- 默认
gog batch end是原子提交:一次 revision-locked 的documents.batchUpdate调用,最多 500 个请求,要么全部生效要么全部不生效; --auto-split以非原子方式按最多 500 个请求的有序分块提交;--continue-on-error在原子校验失败(HTTP 400)后逐个提交并保留失败请求——二者互斥;- 后续排队的追加操作会校验“批次身份”(service、doc、account、client 必须一致,见
ValidateIdentity,internal/docsbatch/repository.go)与“revision 一致性”,不一致时以ErrIdentityMismatch/ErrRevisionChanged拒绝,从机制上避免把编辑应用到错误的文档或过期的版本。
追加时 revision 的语义是:队列中第一条变更记录该文档当时的 revision,后续请求必须携带相同 revision 才能入队;提交时通过writeControl.requiredRevisionId携带该 revision,确保请求针对的是同一个文档版本(wire 载荷组装见 internal/cmd/docs_batch_store.go)。
七、注意事项与适用边界
- 只有“可直接组合”的 Docs 变更支持
--batch:包括docs write(必须是批次中第一条)、docs update、docs insert、docs delete、docs format、docs cell-style、docs table-column-width、docs insert-person、docs insert-file-chip、docs insert-date-chip、docs insert-page-break。Markdown 写入、页面布局、插图、建表等多阶段操作被刻意排除,因为它们会在写入之间执行读取或副作用,无法诚实地共享一次原子 Docs API 请求; - 位置解析针对“当时的线上文档”:范围、锚点、tab、文末位置在每条命令排队时即时解析,不会在本地重放先前已排队的请求。官方建议优先使用稳定的显式索引;若必须按相对位置排队,从文档末尾向开头逐个排队更安全;
begin不带--doc会直接报错:源码中strings.TrimSpace(c.DocID) == ""即返回empty --doc;- 清理机制:
batch abort <batchId>丢弃批次;batch prune --older-than 72h清理超过 72 小时未更新的陈旧批次(默认阈值定义在BatchPruneCmd的OlderThan字段,见 internal/cmd/batch.go)。
八、测试验证与可靠性的源码佐证
本仓库用大量测试锁定了批次行为的正确性,可作为阅读与二次开发的入口:
- internal/cmd/docs_batch_store_test.go:例如
TestBatchEndAtomicSubmitsExactPayloadAndDeletesState用httptest服务端断言提交路径为/documents/doc1:batchUpdate、载荷携带writeControl.requiredRevisionId,且提交完成后批次文件被删除;TestBatchEndAutoSplitChainsRevision验证--auto-split时每个分块会串联下一块所需的最新 revision; - internal/docsbatch/repository_test.go:覆盖仓库层
Create → Append → Get → List → Prune的完整生命周期,并用可注入的Now/NewID函数固定时间与 UUID,验证created_at、updated_at、required_revision_id等字段的精确写入。
这些测试同时印证了文章前述的约定:批次是“持久化 + revision 锁定 + 原子提交”三者的结合,begin正是这套机制在命令行上的统一入口。
相关文档
- gog batch(命令族总览)
- gog batch end(提交与恢复模式)
- Google Docs request batches(完整设计文档)
- Paths and State(状态目录说明)
- 命令索引
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考