deltamesh

Quickstart

From an empty module to an applied patch in five minutes.

Install

go get github.com/deltamesh/deltamesh@v1.9.2

The module has no third-party dependencies. Go 1.21 or newer is required for the iterator interfaces.

Compute a patch

package main

import (
    "context"
    "os"

    "github.com/deltamesh/deltamesh"
)

func main() {
    old, _ := os.Open("snapshot-a.json")
    new, _ := os.Open("snapshot-b.json")
    defer old.Close()
    defer new.Close()

    d := deltamesh.NewDiffer(deltamesh.JSON())
    patch, err := d.Diff(context.Background(), old, new)
    if err != nil {
        panic(err)
    }

    patch.WriteTo(os.Stdout)
}

Apply it

a := deltamesh.NewApplier(deltamesh.JSON())
if err := a.Apply(ctx, src, patch, dst); err != nil {
    log.Fatalf("apply: %v", err)
}
Note. Apply streams into dst as it reads src. Do not point both at the same file — use a temporary file and rename on success.

Configuration

Options are passed to NewDiffer and are all optional.

OptionDefaultEffect
WithMaxDepth(n)256Aborts with ErrTooDeep beyond n levels
WithKeyOrder(f)lexicalComparison order for map keys
WithMoveDetection(b)trueEmits Move instead of Delete+Insert pairs
WithCompactDeletes(b)falseSmaller patches, but no longer reversible
WithBufferSize(n)64 KiBRead buffer per side

Benchmarks

Measured on a 2023 Ryzen 7 7840U, Go 1.22, single core, inputs on tmpfs.

Input pairTimePeak RSSPatch size
12 MB catalogue, 0.4% changed81 ms9 MB54 KB
410 MB export, 2% changed2.6 s14 MB9.1 MB
4.1 GB array, 0.1% changed27 s19 MB4.4 MB