Artifact 1ed5c9576eb96a17e21d934809d22e8380ed664756a7d5e555bc0204c253aed5:
- File
internal/checkout/types.go
— part of check-in
[318f46de9e]
at
2026-10-21 11:48:51
on branch feat/submanifest-reader
— feat(checkout): verify a present R card on extract, as fossil's checkout
Extract now runs fossil's repo-cksum check after materializing: a present R card is compared with the aggregate over every file the manifest names, read from the store, so a sparse checkout over a dense store reaches the same verdict as a dense one, and a sparse store skips the check. Like fossil, a disagreement is a warning delivered through ExtractOpts.Warn and never fails the extract; repo-cksum off disables it. The conformance case builds its repository with fossil and checks fossil warns exactly where go-libfossil does. Clears the SC-4.3-4 scope note. (user: [email protected], size: 8330) [annotate] [blame] [check-ins using] [more...]
package checkout import ( "time" "github.com/danmestas/go-libfossil/internal/cone" libfossil "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/vfile" "github.com/danmestas/go-libfossil/simio" ) // VFileChange — vfile.chnged column values (matches Fossil's vfile states) type VFileChange int const ( VFileNone VFileChange = 0 // unchanged VFileMod VFileChange = 1 // modified VFileMergeMod VFileChange = 2 // modified via merge VFileMergeAdd VFileChange = 3 // added via merge VFileIntMod VFileChange = 4 // modified via integrate VFileIntAdd VFileChange = 5 // added via integrate VFileIsExec VFileChange = 6 // became executable VFileBecameLink VFileChange = 7 // became symlink VFileNotExec VFileChange = 8 // lost executable VFileNotLink VFileChange = 9 // lost symlink ) // FileChange — checkout-level change types (maps to fsl_ckout_change_e). // Package vfile owns their meaning; these names keep the checkout API. type FileChange = vfile.Change const ( ChangeNone = vfile.ChangeNone ChangeAdded = vfile.ChangeAdded ChangeRemoved = vfile.ChangeRemoved ChangeMissing = vfile.ChangeMissing ChangeRenamed = vfile.ChangeRenamed ChangeModified = vfile.ChangeModified ChangeExecutable = vfile.ChangeExecutable ChangeSymlink = vfile.ChangeSymlink ChangeUnexec = vfile.ChangeUnexec ChangeUnlink = vfile.ChangeUnlink ) // UpdateChange — file states during extract/update (maps to fsl_ckup_fchange_e) type UpdateChange int const ( UpdateNone UpdateChange = iota UpdateAdded UpdateAddPropagated UpdateRemoved UpdateRmPropagated UpdateUpdated UpdateUpdatedBinary UpdateMerged UpdateConflictMerged UpdateConflictAdded UpdateConflictUnmanaged UpdateConflictRm UpdateConflictSymlink UpdateConflictBinary UpdateRenamed UpdateEdited ) // RevertChange — revert operation types (maps to fsl_ckout_revert_e) type RevertChange int const ( RevertNone RevertChange = iota RevertUnmanage RevertRemove RevertRename RevertPermissions RevertContents ) // ScanFlags — controls ScanChanges behavior type ScanFlags uint32 const ( ScanHash ScanFlags = 1 << iota // hash file content (not just mtime) ScanENotFile // refuse non-regular files (fossil's CKSIG_ENOTFILE) ScanSetMTime // update mtime in vfile ScanKeepOthers // keep other version entries ) // ManifestFlags — controls WriteManifest behavior type ManifestFlags int const ( ManifestMain ManifestFlags = 1 << iota // write manifest file ManifestUUID // write manifest.uuid file ) // OpenOpts configures opening an existing checkout. type OpenOpts struct { Env *simio.Env // nil → RealEnv Observer Observer // nil → nopObserver SearchParents bool // search parent dirs for .fslckout } // CreateOpts configures creating a new checkout from a repo. type CreateOpts struct { Env *simio.Env // nil → RealEnv Observer Observer // nil → nopObserver // Cone makes the checkout sparse (draft-fossil-sparse-cone-00 §4): only // the files it covers are materialized and managed. nil is dense. Cone *cone.Cone } // ExtractOpts configures file extraction from a checkin. type ExtractOpts struct { Callback func(name string, change UpdateChange) error // per-file notification SetMTime bool // as fossil's --setmtime: each file's last check-in time DryRun bool Force bool // overwrite locally modified files // Warn receives what fossil's checkout prints as a warning and proceeds // past, such as a present R card disagreeing with the manifest's files. // nil discards warnings; they never fail the extract. Warn func(message string) } // UpdateOpts configures updating to a new version with merge. type UpdateOpts struct { TargetRID libfossil.FslID // 0 → auto-calculate via CalcUpdateVersion Callback func(name string, change UpdateChange) error SetMTime bool // as fossil's --setmtime: each file's last check-in time DryRun bool } // UpdateResult reports what Update actually did. Paths, not counts: a // caller needs to know which files to show a user, not merely how many // changed. All four slices are sorted (sort.Strings) before Update // returns, so the order is deterministic and safe to compare with // reflect.DeepEqual — it does not depend on Go's randomized map iteration. // // Conflicted is non-empty when three-way merge could not resolve a file // cleanly and wrote "<<<<<<<"-style conflict markers into it on disk. That // is a successful update, not a failure — Update still returns a nil error // in that case. A caller that only checks the error gets today's behavior; // a caller that wants to detect marker text in the working tree must // inspect Conflicted. Every path in Conflicted also appears in // FilesWritten: the marker text is what was written there. // // Unmerged lists the files fossil's update also counts as conflicts but // that hold no markers, left for the caller to reconcile: // - a file edited locally that the target deletes: kept on disk as it // was, no longer tracked; // - a file added locally that the target also adds: the local file kept, // now tracked as the target's file, so it shows as edited; // - a binary file both the working copy and the target changed: the // target's content written (so also in FilesWritten), the working // copy saved beside it as NAME-original. // - a file edited locally that the target renamed without changing it: // left under its old name, untracked, the new name not written (as // fossil does; the new name shows as missing). type UpdateResult struct { FilesWritten []string // paths written (added, updated, or merged, clean or not); includes every Conflicted path FilesRemoved []string // paths deleted from the working tree Conflicted []string // paths that now contain conflict markers; also present in FilesWritten Unmerged []string // paths left to reconcile without markers (see above) // OutOfCone counts the changes a sparse checkout's update applied to // files outside its cone: recorded, never written to disk // (draft-fossil-sparse-cone-00 §4.4). OutOfCone int } // ManageOpts configures adding files to tracking. type ManageOpts struct { Paths []string Callback func(name string, added bool) error } // ManageCounts reports the result of a Manage operation. type ManageCounts struct { Added, Updated, Skipped int } // UnmanageOpts configures removing files from tracking. type UnmanageOpts struct { Paths []string // pathnames to unmanage VFileIDs []libfossil.FslID // alternative: pass IDs directly Callback func(name string) error } // EnqueueOpts configures staging files for commit. type EnqueueOpts struct { Paths []string Callback func(name string) error } // DequeueOpts configures unstaging files. type DequeueOpts struct { Paths []string // empty → dequeue all } // CommitOpts configures creating a checkin from staged files. type CommitOpts struct { Message string User string Branch string // empty → current branch Tags []string // additional T-cards Delta bool Time time.Time // zero → env.Clock.Now() PreCommitCheck func() error // nil = no check; non-nil error aborts commit AllowConflict bool // commit files that hold merge conflict markers AllowEmpty bool // commit even when nothing changed } // RevertOpts configures reverting file changes. type RevertOpts struct { Paths []string // empty → revert all Callback func(name string, change RevertChange) error } // RenameOpts configures renaming a tracked file. type RenameOpts struct { From, To string DoFsMove bool // also move on filesystem via Storage Callback func(from, to string) error } // ChangeEntry describes a single file change in the checkout. type ChangeEntry struct { Name string Change FileChange VFileID libfossil.FslID IsExec bool IsLink bool OrigName string // non-empty if renamed } // ChangeVisitor is called for each changed file during VisitChanges. type ChangeVisitor func(entry ChangeEntry) error