merge

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package merge provides three-way merge with pluggable strategies.

Register strategies at init time via Register, then look them up by name with StrategyByName. The built-in strategies are:

  • ThreeWayText: line-level LCS-based merge with conflict markers
  • Binary: treats any difference as a conflict
  • LastWriterWins: always picks the remote side
  • ConflictFork: creates a fork instead of merging

FindCommonAncestor walks the plink DAG to locate the merge base for two divergent checkins. DetectForks identifies open forks in a repository.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnsureConflictTable

func EnsureConflictTable(r *repo.Repo) error

EnsureConflictTable creates the conflict table if it doesn't exist. Follows Fossil conventions: REFERENCES blob for rids, julianday REAL for timestamps.

func FindCommonAncestor

func FindCommonAncestor(r *repo.Repo, ridA, ridB libfossil.FslID) (libfossil.FslID, error)

FindCommonAncestor walks the plink DAG backwards from two checkin rids to find their most recent common ancestor via bidirectional BFS.

func ListConflictForks

func ListConflictForks(r *repo.Repo) ([]string, error)

ListConflictForks returns all unresolved conflict-fork entries.

func RecordConflictFork

func RecordConflictFork(r *repo.Repo, filename string, baseRID, localRID, remoteRID int64) error

RecordConflictFork inserts a conflict-fork entry.

func Register

func Register(s Strategy)

Register adds a strategy to the registry.

func ResolveConflictFork

func ResolveConflictFork(r *repo.Repo, filename string) error

ResolveConflictFork deletes a resolved entry (Fossil convention: delete, don't flag).

Types

type Binary

type Binary struct{}

Binary always returns a conflict. Binary files cannot be auto-merged.

func (*Binary) Merge

func (b *Binary) Merge(base, local, remote []byte) (*Result, error)

func (*Binary) Name

func (b *Binary) Name() string

type Conflict

type Conflict struct {
	StartLine int
	EndLine   int
	Local     []byte
	Remote    []byte
	Base      []byte
}

Conflict describes one conflicting region.

type ConflictFork

type ConflictFork struct{}

ConflictFork preserves all divergent versions without merging. Used for offline-first scenarios where conflicts accumulate. Stores references in a conflict table (Fossil-idiomatic schema).

func (*ConflictFork) Merge

func (c *ConflictFork) Merge(base, local, remote []byte) (*Result, error)

func (*ConflictFork) Name

func (c *ConflictFork) Name() string

type Fork

type Fork struct {
	Ancestor  libfossil.FslID
	LocalTip  libfossil.FslID
	RemoteTip libfossil.FslID
}

Fork represents two divergent checkins sharing a common ancestor.

func DetectForks

func DetectForks(r *repo.Repo) ([]Fork, error)

DetectForks finds divergent branches by querying the leaf table (maintained by Fossil/manifest.Checkin) for checkins with no children.

type LastWriterWins

type LastWriterWins struct{}

LastWriterWins picks the newer version. The caller passes the newer content as remote. Always clean — no conflicts possible.

func (*LastWriterWins) Merge

func (l *LastWriterWins) Merge(base, local, remote []byte) (*Result, error)

func (*LastWriterWins) Name

func (l *LastWriterWins) Name() string

type PatternRule

type PatternRule struct {
	Glob     string
	Strategy string
}

PatternRule maps a glob pattern to a strategy name.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver picks the merge strategy for a given filename.

func LoadResolver

func LoadResolver(r *repo.Repo, tipRid libfossil.FslID) *Resolver

LoadResolver reads the .libfossil-merge file from the repo at the given version, plus the merge-strategy config key as fallback.

func (*Resolver) Resolve

func (res *Resolver) Resolve(filename string) string

Resolve returns the strategy name for a filename.

type Result

type Result struct {
	Content   []byte     // merged output (may contain conflict markers)
	Conflicts []Conflict // unresolved conflict regions
	Clean     bool       // true if no conflicts
}

Result of a merge operation.

type Strategy

type Strategy interface {
	Name() string
	Merge(base, local, remote []byte) (*Result, error)
}

Strategy merges three versions of content.

func StrategyByName

func StrategyByName(name string) (Strategy, bool)

StrategyByName returns a strategy implementation by name.

type ThreeWayText

type ThreeWayText struct{}

ThreeWayText implements line-level 3-way merge.

Example
package main

import (
	"fmt"

	"github.com/danmestas/libfossil/internal/merge"
)

func main() {
	base := []byte("line 1\nline 2\nline 3\n")
	local := []byte("line 1\nlocal change\nline 3\n")
	remote := []byte("line 1\nline 2\nline 3\nremote addition\n")

	result, err := (&merge.ThreeWayText{}).Merge(base, local, remote)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("clean:", result.Clean)
	fmt.Print(string(result.Content))
}
Output:
clean: true
line 1
local change
line 3
remote addition

func (*ThreeWayText) Merge

func (t *ThreeWayText) Merge(base, local, remote []byte) (*Result, error)

func (*ThreeWayText) Name

func (t *ThreeWayText) Name() string

Jump to

Keyboard shortcuts

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