IfNotExists / LatestRevisionID are silently ignored when CreateRevision=false #31
Labels
No labels
area/client
area/revisions
bug
clarity/ambiguous
clarity/clear
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
size/L
size/M
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
basepeak-ai/workspace-provider#31
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
WriteOptionsdocuments that a conflict error is returned whenLatestRevisionIDis not the latest, and thatIfNotExistswrites only when the file does not exist (pkg/client/client.go:210-214).IfNotExistsis implemented asLatestRevisionID = "-1"(client.go:230).Both checks live in
beginWrite(pkg/client/revisionwrite.go~line 125), which returns immediately whenCreateRevision=false:So
WriteFile(…, WriteOptions{CreateRevision: &false, IfNotExists: true})overwrites an existing file with no error, and a staleLatestRevisionIDis silently accepted. The comment abovebeginWritegives the reason for skipping the revision store (connectors must not break on a corrupt index), but that reason does not cover dropping the caller's precondition.Concrete failure scenario
A caller that uses
IfNotExistsas a create-once guard (e.g. "write the default config only if none exists") and also passesCreateRevision=falseto avoid history clobbers the user's file on every run.Fix
Pick one, and document it:
IfNotExistsis set andCreateRevision=false, check existence withcontentExists/StatFileand return theConflictError. WhenLatestRevisionIDis set without revisions, return an error, since there is no revision to compare against.Silently ignoring it is the one wrong answer. Add tests for both options on each provider.
Where it was found
Review of #27 / #28. Related to basepeak-ai/bpai#1220.
Confirmed in pkg/client/revisionwrite.go:124-127: beginWrite returns
nil, nilimmediately whenopt.CreateRevision != nil && !*opt.CreateRevision, before theIfNotExists/LatestRevisionIDcheck at lines 134-143 ever runs, so both preconditions are silently dropped wheneverCreateRevision=false. AcontentExists(ctx, fileName) (bool, error)method already exists on the provider interface (revisionwrite.go:56) and is already used for exactly this kind of existence probe (used around line 82), so implementing the 'enforce it' option is a small, local change: in theCreateRevision=falsebranch, ifopt.IfNotExistsis set, callcontentExistsand return aConflictError(whichWriteFilein client.go:240-242 already converts toFileExistsError) when the file exists; ifopt.LatestRevisionIDis set to anything other than the IfNotExists sentinel, return an error since there's no revision store to compare against. Tests would need to be added per provider (directory/s3/azure) mirroring the existingskipS3Tests/skipAzureTestsgating in directory_test.go.Questions before this can start: