Check the exact publication record filename before writing

This commit is contained in:
2026-11-02 22:17:59 +00:00
parent 0d19a5546f
commit d2b1329095
3 changed files with 57 additions and 12 deletions

View File

@@ -59,21 +59,16 @@ func SaveEvidence(repositoryDir, override string, evidence Evidence) (string, er
}
func saveEvidenceInDir(repositoryDir, root, override, recordDir string, evidence Evidence) (string, error) {
return saveEvidenceNamed(repositoryDir, root, override, recordDir, evidence, proposedRecordPath)
}
func saveEvidenceNamed(repositoryDir, root, override, recordDir string, evidence Evidence, nextPath func(string) (string, error)) (string, error) {
if evidence.RecordedAt == "" {
evidence.RecordedAt = time.Now().UTC().Format(time.RFC3339Nano)
}
if err := os.MkdirAll(recordDir, 0o700); err != nil {
return "", &RecoveryError{Kind: "record_write", cause: fmt.Errorf("create record directory %q: %w", recordDir, err)}
}
if override != "" && root != "" {
path, pathErr := proposedRecordPath(recordDir)
if pathErr != nil {
return "", &RecoveryError{Kind: "record_write", cause: pathErr}
}
if err := rejectUnignoredWorktreePath(repositoryDir, root, path); err != nil {
return "", &RecoveryError{Kind: "record_write", cause: err}
}
}
evidenceJSON, err := json.Marshal(evidence)
if err != nil {
return "", &RecoveryError{Kind: "record_write", cause: fmt.Errorf("encode publication evidence: %w", err)}
@@ -83,11 +78,15 @@ func saveEvidenceInDir(repositoryDir, root, override, recordDir string, evidence
return "", &RecoveryError{Kind: "record_write", cause: fmt.Errorf("encode publication evidence: %w", err)}
}
for attempt := 0; attempt < 5; attempt++ {
var nonce [16]byte
if _, err := rand.Read(nonce[:]); err != nil {
path, err := nextPath(recordDir)
if err != nil {
return "", &RecoveryError{Kind: "record_write", cause: fmt.Errorf("name publication record: %w", err)}
}
path := filepath.Join(recordDir, "attempt-"+hex.EncodeToString(nonce[:])+".json")
if override != "" && root != "" {
if err := rejectUnignoredWorktreePath(repositoryDir, root, path); err != nil {
return "", &RecoveryError{Kind: "record_write", cause: err}
}
}
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)
if errors.Is(err, os.ErrExist) {
continue