Files

48 lines
1.1 KiB
Go

package git
import (
"bytes"
"context"
)
// Status 返回 git status --porcelain=v1 的结构化解析。空 worktree 返回空切片。
func (r *DefaultRunner) Status(ctx context.Context, dir string) ([]FileStatus, error) {
ctx, cancel := withCtx(ctx, r.cfg.OpsTimeout)
defer cancel()
out, _, err := r.exec(ctx, dir, nil, "status", "--porcelain=v1", "-z")
if err != nil {
return nil, err
}
return parsePorcelainV1(out), nil
}
// parsePorcelainV1 解析 -z 输出(NUL 分隔,不转义)。
// 每条记录格式:XY <SP> <path>\0
// renamed/copied 时是 XY <SP> <to>\0<from>\0;本实现把 to 当 path,丢弃 from。
func parsePorcelainV1(buf []byte) []FileStatus {
var out []FileStatus
for len(buf) > 0 {
nul := bytes.IndexByte(buf, 0)
if nul < 0 {
break
}
rec := buf[:nul]
buf = buf[nul+1:]
if len(rec) < 4 {
continue
}
x, y := rec[0], rec[1]
// rec[2] 是空格
path := string(rec[3:])
out = append(out, FileStatus{Path: path, IndexX: x, WorktreeY: y})
// renamed/copied:跳过 from 段
if x == 'R' || x == 'C' {
nul = bytes.IndexByte(buf, 0)
if nul >= 0 {
buf = buf[nul+1:]
}
}
}
return out
}