You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
returnnil, fmt.Errorf("stack file has schema version %d, but this version of gh-stack only supports up to version %d — please upgrade gh-stack", sf.SchemaVersion, schemaVersion)
256
266
}
257
267
268
+
sum:=sha256.Sum256(data)
269
+
sf.loadChecksum=sum[:]
258
270
return&sf, nil
259
271
}
260
272
261
-
// Save acquires an exclusive lock on the stack file, writes sf as JSON, and
262
-
// releases the lock. The lock is held only for the duration of the write.
263
-
// Returns *LockError if the lock times out due to contention.
273
+
// Save acquires an exclusive lock on the stack file, verifies the file hasn't
274
+
// been modified since Load (optimistic concurrency), writes sf as JSON, and
275
+
// releases the lock. The lock is held only for the read-compare-write window.
276
+
// Returns *LockError if the lock times out, or *StaleError if another process
277
+
// modified the file since it was loaded.
264
278
funcSave(gitDirstring, sf*StackFile) error {
265
279
lock, err:=Lock(gitDir)
266
280
iferr!=nil {
267
281
returnerr// *LockError for contention, plain error for I/O failures
268
282
}
269
283
deferlock.Unlock()
284
+
285
+
iferr:=checkStale(gitDir, sf); err!=nil {
286
+
returnerr
287
+
}
270
288
returnwriteStackFile(gitDir, sf)
271
289
}
272
290
273
291
// SaveNonBlocking attempts to save without blocking. If another process holds
274
-
// the lock, the save is silently skipped. Use this for best-effort metadata
275
-
// persistence (e.g. syncing PR state in view).
292
+
// the lock or the file was modified since Load, the save is silently skipped.
293
+
// Use this for best-effort metadata persistence (e.g. syncing PR state in view).
0 commit comments