a changed external is a polad, and add no longer overwrites anything
Restores something the specimen said and the round that discarded the specimen lost with it: a changed external becomes a polad in the cart, and somebody decides. check now stages what moved into .loom/cart/current/polad/ with the ETag that was served alongside the bytes, and prints the .usages.md beside it, because reconciliation runs the other way — the facets usually survive and what moves is the code a usage named. It says so when there is no usages file, which is its own finding. With no cart open, check reports and stages nothing. The tool does not open a round: a cart is a bounded exchange between two presences and starting one is somebody's act, not a side effect of asking about freshness. add now adopts what is not here and refuses what is already adopted, superseding the entry that had it announce an overwrite — it no longer overwrites at all. The one exception is the only way out of a dead end: a document present but unlocked was fetched by hand, nothing records its origin, and the path does not round-trip, so check cannot ask about it and a refusal would strand it forever. add accepts it and the bytes decide — identical locks it without rewriting anything, which makes the lock's assertion verified rather than assumed, and different stages a polad and leaves the local copy alone because it is the only evidence anything moved. apply exists because the lock is the half a person forgets: moving a polad by hand leaves a lock describing the copy you just replaced. Recorded with its limit — for an external, discard does not mean the change goes away, so discarding is really knowingly stale and nothing yet records that choice. Measured end to end on this repository: eight hand-fetched documents, all eight locked, nothing rewritten. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018UTxuSizozEA8yDitPuris
This commit is contained in:
+16
-7
@@ -42,18 +42,24 @@ type Record struct {
|
||||
|
||||
// Set is every lock, keyed by path.
|
||||
type Set struct {
|
||||
root string
|
||||
file string
|
||||
recs map[string]Record
|
||||
}
|
||||
|
||||
func path(root string) string { return filepath.Join(root, Dir, File) }
|
||||
// Path is the lock file for the repository at root.
|
||||
func Path(root string) string { return filepath.Join(root, Dir, File) }
|
||||
|
||||
// Load reads the lock file for the repository at root. A missing file is an
|
||||
// empty set, not an error: a repository whose externals were fetched by hand has
|
||||
// no locks, and reporting that is the point.
|
||||
func Load(root string) (*Set, error) {
|
||||
s := &Set{root: root, recs: map[string]Record{}}
|
||||
f, err := os.Open(path(root))
|
||||
func Load(root string) (*Set, error) { return LoadFile(Path(root)) }
|
||||
|
||||
// LoadFile reads a lock file from an explicit path. A staged polad carries its
|
||||
// own alongside it, so that applying it uses the ETag that was served with the
|
||||
// bytes somebody reviewed, rather than whatever the publisher serves later.
|
||||
func LoadFile(file string) (*Set, error) {
|
||||
s := &Set{file: file, recs: map[string]Record{}}
|
||||
f, err := os.Open(file)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return s, nil
|
||||
}
|
||||
@@ -70,13 +76,16 @@ func Load(root string) (*Set, error) {
|
||||
}
|
||||
parts := strings.Split(line, "\t")
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("%s:%d: want 3 tab-separated fields, got %d", path(root), n, len(parts))
|
||||
return nil, fmt.Errorf("%s:%d: want 3 tab-separated fields, got %d", file, n, len(parts))
|
||||
}
|
||||
s.recs[parts[0]] = Record{Path: parts[0], URL: parts[1], ETag: parts[2]}
|
||||
}
|
||||
return s, sc.Err()
|
||||
}
|
||||
|
||||
// Remove drops a record.
|
||||
func (s *Set) Remove(p string) { delete(s.recs, p) }
|
||||
|
||||
// Get returns the record for a path, and whether there was one.
|
||||
func (s *Set) Get(p string) (Record, bool) { r, ok := s.recs[p]; return r, ok }
|
||||
|
||||
@@ -96,7 +105,7 @@ func (s *Set) All() []Record {
|
||||
// Save writes the lock file, replacing it atomically so an interrupted write
|
||||
// cannot leave a repository holding half a lock.
|
||||
func (s *Set) Save() error {
|
||||
p := path(s.root)
|
||||
p := s.file
|
||||
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user