// Package statedir names the directory Codey keeps its per-repository state in, // and moves the one the old name left behind. // // The name lives here rather than in the two packages that write into it, // because a directory name that two packages spell independently is a name // that will one day be spelled two ways — which is exactly what the rename // from harness to Codey would have cost. package statedir import ( "fmt" "os" "path/filepath" ) // Dir is where sessions and the event log live, relative to the working root. // LegacyDir is what it was called before the rename. const ( Dir = ".codey" LegacyDir = ".harness" ) // Migrate renames a pre-rename state directory under root, reporting whether // it moved one. It is called once at startup, before anything opens a file // inside Dir. // // A rename rather than a read-time fallback, because the event log is // append-only: leaving the old file where it is would split a repository's // history across two names and quietly break the numbers METRICS.md reports. // // Three cases are deliberately left alone. Nothing to move is the common one, // and must not create an empty directory. Both present means both builds have // run here, so the new directory is the live state and the old one is history // — merging them could only lose whichever copy it picked against. And a // plain file of that name is not our state directory at all. func Migrate(root string) (bool, error) { old := filepath.Join(root, LegacyDir) info, err := os.Lstat(old) if err != nil || !info.IsDir() { return false, nil } if _, err := os.Lstat(filepath.Join(root, Dir)); err == nil { return false, nil } if err := os.Rename(old, filepath.Join(root, Dir)); err != nil { return false, fmt.Errorf("state: moving %s to %s: %w", LegacyDir, Dir, err) } return true, nil }