Last Updated: 2025-12-14
1. Overview
This document outlines a plan to align Cambria's checkin and commit
functionality more closely with the implementation found in Fossil SCM's
checkin.c. The goal is to enhance our vcs.Checkin and vcs.Commit
operations to be more robust and feature-rich, mirroring Fossil's capabilities
where appropriate, without introducing significant database schema changes
beyond the already-planned vfile table.
Based on an analysis of checkin.c, Fossil's commit process is significantly
more complex than Cambria's current implementation. It includes numerous
pre-commit checks, detailed user interaction for comments, content-based
warnings, and sophisticated manifest creation options.
2. Analysis of Fossil's checkin.c
The commit_cmd function in Fossil reveals a multi-stage process:
- Option Parsing: A vast number of CLI options are handled to control
commit behavior (e.g.,
--allow-fork,--branch,--date-override,--private,--tag, content warnings). - Pre-Commit Validation:
- Checks for unsaved changes.
- Performs an optional
autosyncwith a remote repository. - Detects and warns about clock skew.
- Handles partial commits (committing only a subset of changed files).
- Prevents forking, committing against closed branches, and other invalid states unless explicitly allowed.
- Comment Generation: A detailed commit message prompt is generated,
including a summary of changes (
status_report), and the user's editor is invoked. This is a highly interactive process. - Content Processing & Warnings:
- For each modified file, the content is read from disk.
commit_warning()is called to inspect file content for:- Binary data (NUL bytes).
- CR/LF or mixed line endings.
- Unicode byte-order marks (BOMs).
- Invalid UTF-8 sequences.
- Oversized files.
- The user is prompted to confirm if any of these are found, with options to abort or continue.
- The new file content is written to the
blobstore.
- Manifest Creation (
create_manifest):- A manifest is constructed with various "cards" (e.g.,
Cfor comment,Dfor date,Pfor parents,Ffor files). - It supports both baseline and delta manifests (Cambria currently only supports baseline, which is sufficient).
- It embeds tags (
Tcards), including special tags for branches, colors, and closing branches. - It calculates and includes a
Zcard with an MD5 checksum of the manifest content itself.
- A manifest is constructed with various "cards" (e.g.,
- Post-Commit Operations:
- The new manifest is written as a blob and cross-linked.
- The
vfiletable (ourworkdir_fileequivalent) is updated to reflect the new baseline. - The checkout is now associated with the new manifest's ID.
- An optional
autosyncpush is performed.
3. Proposed Changes for Cambria
We will adopt key features from Fossil's process in phases.
Phase 1: Enhance CheckinOptions and Core Logic
The current vcs.CheckinOptions is insufficient. We will expand it and the
Checkin function to support more of Fossil's capabilities.
3.1. New vcs.CheckinOptions Struct
The CheckinOptions struct in pkg/vcs/checkin.go will be updated to:
// pkg/vcs/checkin.go
// CheckinOptions holds optional parameters for a check-in operation.
type CheckinOptions struct {
Comment string
User string
Timestamp time.Time // Allow overriding the commit timestamp
Labels []string // For tags like 'release-v1.0'
IsMerge bool
CloseBranch bool // Corresponds to Fossil's 'closed' tag
Branch string // New branch name for this commit
BranchColor string // Persistent color for the new branch
OneTimeColor string // One-time background color for this commit
AllowFork bool // Allow this commit to create a fork
AllowEmpty bool // Allow a commit with no file changes
AllowOlder bool // Allow commit to be older than its parent
IsPrivate bool // If true, this is a private commit
}
3.2. Update vcs.Checkin Function Signature
The function signature in pkg/vcs/checkin.go will be updated to accept the new
options struct directly.
// pkg/vcs/checkin.go
func (r *Repository) Checkin(
files []artifact.FileEntry,
parents []string,
opts CheckinOptions,
) (string, error) {
// ... function implementation ...
}
3.3. Implement New Options in vcs.Checkin
The Checkin function will be modified to handle the new options:
- Timestamp: If
opts.Timestampis not zero, use it. Otherwise, usetime.Now().UTC(). - Branching:
- If
opts.Branchis provided, add a*branchtag and asym-<branchname>tag to the manifest. - If
opts.BranchColoris provided with a new branch, add a*bgcolortag.
- If
- Colors: If
opts.OneTimeColoris provided, add a+bgcolortag. - Closing Branch: If
opts.CloseBranchis true, add a+closedtag. - Private Commits: The
IsPrivateflag will be passed tomanifest.GenerateManifestbut its full implementation (preventing sync) is deferred. For now, it can be recorded in the manifest generation logic if we decide to add a specific marker. - Pre-Commit Checks:
- Empty Commit: Add a check at the beginning. If
len(files)is zero andopts.AllowEmptyis false, return an error. - Forking: This requires querying the parent(s) to see if they are
leaves. This logic will be added. If a fork would be created and
opts.AllowForkis false, return an error. - Older: This requires comparing the commit timestamp with parent
timestamps. If the commit is older and
opts.AllowOlderis false, return an error.
- Empty Commit: Add a check at the beginning. If
Phase 2: Content Warnings in vcs.Commit
The vcs.Commit function, which orchestrates a commit from a working directory,
is the ideal place to introduce content-based warnings.
3.4. New CommitOptions Struct
The CommitOptions struct in pkg/vcs/checkin.go will be updated to control
these new behaviors.
// pkg/vcs/checkin.go
// CommitOptions holds optional parameters for a commit operation.
type CommitOptions struct {
CheckinOptions // Embed all check-in options
NoWarnings bool // Skip all content-based warnings
AllowConflict bool // Allow commit with merge-conflict markers
}
3.5. Implement Content Scanning in vcs.Commit
Before calling r.Checkin, the Commit function will:
- Iterate through all
StatusAddedandStatusModifiedfiles from theWorkDirscan. - For each file, read its content from the filesystem.
- Perform checks similar to Fossil's
commit_warning:- Check for NUL bytes (indicates binary).
- Check for
\rcharacters (indicates CR/LF or CR line endings). - Check for unresolved merge conflict markers (
<<<<<<<,=======,>>>>>>>).
- If any of these are found and
opts.NoWarnings(oropts.AllowConflict) is false, return a specific error (e.g.,ErrBinaryContent,ErrCRLFLineEndings,ErrMergeConflict). The CLI layer will be responsible for interpreting these errors and prompting the user.
4. Implementation Plan
- Update
pkg/vcs/checkin.go:- Modify the
CheckinOptionsandCommitOptionsstructs as defined above. - Update the
Checkinfunction signature. - Implement the logic for the new
CheckinOptions(timestamp override, tags for branch/color/close). - Add the pre-commit validation checks (empty, fork, older) to the
Checkinfunction. - Update the
Commitfunction to perform content scanning and return errors for binary files, CRLF line endings, and merge conflicts.
- Modify the
- Update
pkg/artifact/manifest.go:- Modify
GenerateManifestto accept the new options and correctly formatT(tag) cards for branches, colors, and closing.
- Modify
- Update Call Sites:
- Refactor any code that calls
vcs.Checkinorvcs.Committo use the new option structs. - Update tests in
pkg/vcs/checkin_test.goto cover the new options and validation logic.
- Refactor any code that calls
- CLI Integration (Future):
- The
cmd/cambriapackage will be responsible for parsing CLI flags (e.g.,--allow-fork,--no-warnings) and populating theCommitOptionsstruct. - The CLI will catch specific errors from
Commit(likeErrBinaryContent) and prompt the user interactively.
- The