Login
Cambria Check-in/Commit Feature Alignment Plan
Login

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:

  1. 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).
  2. Pre-Commit Validation:
    • Checks for unsaved changes.
    • Performs an optional autosync with 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.
  3. 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.
  4. 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 blob store.
  5. Manifest Creation (create_manifest):
    • A manifest is constructed with various "cards" (e.g., C for comment, D for date, P for parents, F for files).
    • It supports both baseline and delta manifests (Cambria currently only supports baseline, which is sufficient).
    • It embeds tags (T cards), including special tags for branches, colors, and closing branches.
    • It calculates and includes a Z card with an MD5 checksum of the manifest content itself.
  6. Post-Commit Operations:
    • The new manifest is written as a blob and cross-linked.
    • The vfile table (our workdir_file equivalent) is updated to reflect the new baseline.
    • The checkout is now associated with the new manifest's ID.
    • An optional autosync push 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:

  1. Timestamp: If opts.Timestamp is not zero, use it. Otherwise, use time.Now().UTC().
  2. Branching:
    • If opts.Branch is provided, add a *branch tag and a sym-<branchname> tag to the manifest.
    • If opts.BranchColor is provided with a new branch, add a *bgcolor tag.
  3. Colors: If opts.OneTimeColor is provided, add a +bgcolor tag.
  4. Closing Branch: If opts.CloseBranch is true, add a +closed tag.
  5. Private Commits: The IsPrivate flag will be passed to manifest.GenerateManifest but 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.
  6. Pre-Commit Checks:
    • Empty Commit: Add a check at the beginning. If len(files) is zero and opts.AllowEmpty is 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.AllowFork is false, return an error.
    • Older: This requires comparing the commit timestamp with parent timestamps. If the commit is older and opts.AllowOlder is false, return an error.

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:

  1. Iterate through all StatusAdded and StatusModified files from the WorkDir scan.
  2. For each file, read its content from the filesystem.
  3. Perform checks similar to Fossil's commit_warning:
    • Check for NUL bytes (indicates binary).
    • Check for \r characters (indicates CR/LF or CR line endings).
    • Check for unresolved merge conflict markers (<<<<<<<, =======, >>>>>>>).
  4. If any of these are found and opts.NoWarnings (or opts.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

  1. Update pkg/vcs/checkin.go:
    • Modify the CheckinOptions and CommitOptions structs as defined above.
    • Update the Checkin function 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 Checkin function.
    • Update the Commit function to perform content scanning and return errors for binary files, CRLF line endings, and merge conflicts.
  2. Update pkg/artifact/manifest.go:
    • Modify GenerateManifest to accept the new options and correctly format T (tag) cards for branches, colors, and closing.
  3. Update Call Sites:
    • Refactor any code that calls vcs.Checkin or vcs.Commit to use the new option structs.
    • Update tests in pkg/vcs/checkin_test.go to cover the new options and validation logic.
  4. CLI Integration (Future):
    • The cmd/cambria package will be responsible for parsing CLI flags (e.g., --allow-fork, --no-warnings) and populating the CommitOptions struct.
    • The CLI will catch specific errors from Commit (like ErrBinaryContent) and prompt the user interactively.