merge

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package merge is the pure, deterministic three-way reconcile engine at the heart of Milestone S1 team sync. Given a path's three versions (the client's base ancestor, the hub's current HEAD, and the client's incoming change) it decides what the hub should land: a fast-forward, an additive append-merge, a clean delete, or a true conflict that keeps the hub version and parks the loser in a *.sync-conflict sibling. It does no I/O: the hub feeds it bytes read from git (S1.3) so every case is table-testable.

Two SPEC 6.4/6.5 invariants drive it:

  • Append-merge first. Two writers that only ADD blocks to a shared page merge with no conflict (the flywheel's core write pattern), order- and side-independent, deduped by content hash. Only a true overwrite of existing content conflicts.
  • Never lose data. A conflict keeps the hub version live and writes the incoming version to a sibling a human resolves; a delete that races an edit keeps the edit.

Line endings are normalized to LF for hashing and equality only; block bytes are preserved (SPEC 6.5: do not rewrite a teammate's CRLF).

Index

Constants

View Source
const MaxNoteBytes = 1 << 20

MaxNoteBytes caps a mergeable note; larger or binary content is rejected upstream (SPEC: binaries are out of v1).

Variables

This section is empty.

Functions

func BasePath

func BasePath(sibling string) (string, bool)

BasePath reverses SiblingPath: given a sync-conflict sibling path it returns the base note path the loser was parked next to (ok=false if the name is not a sibling). It strips from the LAST marker on the extension-stripped stem, so a sanitized user containing '-' (e.g. alice-smith) and a base whose own stem has hyphens both reverse correctly. A recovered base that still looks like a sibling (a doubly-nested/garbage name) is refused, since no real base note can.

func IsText

func IsText(content []byte) bool

IsText reports whether content is small enough and free of NUL bytes to be a mergeable markdown note (binaries are rejected; SPEC v1 has no blob support).

func SiblingPath

func SiblingPath(path string, now time.Time, user string, losing []byte) string

SiblingPath names a conflict sibling next to path, e.g. notes/x.md -> notes/x.sync-conflict-20260616-alice-1a2b3c4d.md. The short hash of the losing content makes the name unique per distinct version (so two conflicts on the same path/user/day never overwrite each other) AND idempotent (re-syncing the same conflict reuses the same sibling rather than spawning a new one every time).

Types

type Action

type Action string

Action is the resolved outcome for a path.

const (
	ActionNoop     Action = "noop"     // hub is already correct; nothing to land
	ActionUpsert   Action = "upsert"   // write Content at Path
	ActionDelete   Action = "delete"   // remove Path
	ActionConflict Action = "conflict" // keep hub at Path; write the loser to SiblingPath
)

type Incoming

type Incoming struct {
	Op      string // "upsert" | "delete"
	Content []byte // for upsert
}

Incoming is the client's proposed change for a path.

type Resolution

type Resolution struct {
	Path           string
	Action         Action
	Content        []byte // ActionUpsert: the (possibly merged) content to write at Path
	SiblingPath    string // ActionConflict: where the losing version goes
	SiblingContent []byte // ActionConflict: the losing (incoming) content
}

Resolution is what the hub should land for one path.

func MergePath

func MergePath(path string, base, hub Version, in Incoming, now time.Time, user string) Resolution

MergePath resolves one path's three-way state. now + user name the conflict sibling deterministically.

type Version

type Version struct {
	Content []byte
	Exists  bool
}

Version is one side's content for a path. Exists is false when the path is absent on that side (never created, or deleted).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL