Skip to content

Support inserting tree entries that reference arbitrary existing objects #12

@joeycarpinelli

Description

@joeycarpinelli

Problem

Ledger::create always writes new blobs for field values. There is no way to insert a tree entry whose OID points to an existing git object (commit, tree, or blob) with the correct file mode.

Use case

Forge reviews keep an objects/ subtree that pins target objects for GC:

objects/
├── <commit-oid>   # mode 160000 (gitlink)
├── <blob-oid>     # mode 100644
└── <tree-oid>     # mode 040000

Each entry's OID must point to the actual object, not a new blob containing placeholder content. Currently, callers must work around this with a fixup_pin_entries post-pass that:

  1. Reads back the commit that Ledger::create just wrote.
  2. Rebuilds the objects/ subtree with the correct OIDs and file modes.
  3. Creates a second commit and force-updates the ref.

This doubles the number of commits per creation and is fragile.

Proposed API

A new Mutation variant (or a new field type) that tells the ledger to insert this entry name with this existing OID and file mode:

// Strawman — exact API shape is up to you.
Mutation::Pin("objects/abc123...", oid, FileMode::Commit)

The ledger would insert the tree entry directly, the same way treebuilder.insert(name, oid, mode) works, instead of creating a new blob.

Alternatives considered

  • Separate subtree + manual commit: what we do today. Works, but the two-commit dance is ugly and makes ref history harder to follow.
  • Store OID strings as blob content: keeps one commit but defeats the purpose — GC can still collect the referenced objects because nothing in the tree actually references them.

Generated-by: Claude Code (Claude Opus 4.6)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions