98 lines
3.0 KiB
Go
98 lines
3.0 KiB
Go
// Package store persists workspace-level PR review confirmation state.
|
|
//
|
|
// Confirmations live in <workspace>/.spx/pr-review-confirmed.json as a
|
|
// map[string][]string. File-level confirmations use key "<issueNumber>:<sha>"
|
|
// and hold the confirmed file paths of that commit; commit-level confirmations
|
|
// use key "<issueNumber>:commits" and hold the confirmed commit SHAs. Directories
|
|
// are not tracked separately. A missing or malformed file reads as empty.
|
|
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"superwork-tui/internal/config"
|
|
)
|
|
|
|
type confirmedMap = map[string][]string
|
|
|
|
func confirmedFile(workspaceRoot string) string {
|
|
return filepath.Join(config.SpxDir(workspaceRoot), "pr-review-confirmed.json")
|
|
}
|
|
|
|
func fileKey(issueNumber int, sha string) string {
|
|
return strconv.Itoa(issueNumber) + ":" + sha
|
|
}
|
|
|
|
func commitsKey(issueNumber int) string {
|
|
return strconv.Itoa(issueNumber) + ":commits"
|
|
}
|
|
|
|
// readMap returns the whole confirmation map. A missing or unparseable file
|
|
// reads as an empty map rather than an error.
|
|
func readMap(workspaceRoot string) confirmedMap {
|
|
raw, err := os.ReadFile(confirmedFile(workspaceRoot))
|
|
if err != nil {
|
|
return confirmedMap{}
|
|
}
|
|
var parsed confirmedMap
|
|
if err := json.Unmarshal(raw, &parsed); err != nil {
|
|
return confirmedMap{}
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
// writeMap persists the confirmation map, creating .spx if needed.
|
|
func writeMap(workspaceRoot string, m confirmedMap) error {
|
|
if err := os.MkdirAll(config.SpxDir(workspaceRoot), 0o755); err != nil {
|
|
return fmt.Errorf("create .spx dir: %w", err)
|
|
}
|
|
data, err := json.MarshalIndent(m, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("marshal confirmations: %w", err)
|
|
}
|
|
if err := os.WriteFile(confirmedFile(workspaceRoot), append(data, '\n'), 0o644); err != nil {
|
|
return fmt.Errorf("write confirmations: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ReadConfirmed returns the confirmed file paths for a (issueNumber, sha) commit.
|
|
func ReadConfirmed(workspaceRoot string, issueNumber int, sha string) ([]string, error) {
|
|
return readMap(workspaceRoot)[fileKey(issueNumber, sha)], nil
|
|
}
|
|
|
|
// WriteConfirmed sets the confirmed file paths for a (issueNumber, sha) commit.
|
|
// An empty slice deletes the key.
|
|
func WriteConfirmed(workspaceRoot string, issueNumber int, sha string, paths []string) error {
|
|
m := readMap(workspaceRoot)
|
|
key := fileKey(issueNumber, sha)
|
|
if len(paths) > 0 {
|
|
m[key] = paths
|
|
} else {
|
|
delete(m, key)
|
|
}
|
|
return writeMap(workspaceRoot, m)
|
|
}
|
|
|
|
// ReadConfirmedCommits returns the confirmed commit SHAs for an issue.
|
|
func ReadConfirmedCommits(workspaceRoot string, issueNumber int) ([]string, error) {
|
|
return readMap(workspaceRoot)[commitsKey(issueNumber)], nil
|
|
}
|
|
|
|
// WriteConfirmedCommits sets the confirmed commit SHAs for an issue.
|
|
// An empty slice deletes the key.
|
|
func WriteConfirmedCommits(workspaceRoot string, issueNumber int, shas []string) error {
|
|
m := readMap(workspaceRoot)
|
|
key := commitsKey(issueNumber)
|
|
if len(shas) > 0 {
|
|
m[key] = shas
|
|
} else {
|
|
delete(m, key)
|
|
}
|
|
return writeMap(workspaceRoot, m)
|
|
}
|