feat(adapter): registry with detect filtering and duplicate guard

This commit is contained in:
2026-05-23 02:48:31 +01:00
parent 6ab8d149e1
commit 95962bdf9a
12 changed files with 389 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
// Package merge wraps git merge-file for three-way file merges.
package merge
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
// Inputs:
//
// Base = last-rendered snapshot (state/...)
// Ours = new rendered output (what we'd write now)
// Theirs = current target file contents (what's on disk at the destination)
type Inputs struct {
Base []byte
Ours []byte
Theirs []byte
}
type Result struct {
Body []byte
Conflict bool
}
// ThreeWay runs `git merge-file -p ours base theirs` and returns the
// merged body. When Conflict is true, Body contains conflict markers.
func ThreeWay(in Inputs) (*Result, error) {
tmp, err := os.MkdirTemp("", "harness-sync-merge-")
if err != nil {
return nil, err
}
defer os.RemoveAll(tmp)
oursPath := filepath.Join(tmp, "ours")
basePath := filepath.Join(tmp, "base")
theirsPath := filepath.Join(tmp, "theirs")
if err := os.WriteFile(oursPath, in.Ours, 0o644); err != nil {
return nil, err
}
if err := os.WriteFile(basePath, in.Base, 0o644); err != nil {
return nil, err
}
if err := os.WriteFile(theirsPath, in.Theirs, 0o644); err != nil {
return nil, err
}
cmd := exec.Command(
"git", "merge-file",
"-L", "harness-sync (new)",
"-L", "harness-sync (base)",
"-L", "harness-sync (current)",
"-p",
oursPath, basePath, theirsPath,
)
out, runErr := cmd.Output()
res := &Result{Body: out}
if runErr != nil {
if ee, ok := runErr.(*exec.ExitError); ok {
// git merge-file exits with conflict-count on conflict; body still valid
if ee.ExitCode() > 0 {
res.Conflict = true
return res, nil
}
}
return nil, fmt.Errorf("git merge-file: %w", runErr)
}
return res, nil
}
+42
View File
@@ -0,0 +1,42 @@
package merge
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCleanFastForward(t *testing.T) {
res, err := ThreeWay(Inputs{
Base: []byte("a\nb\nc\n"),
Ours: []byte("a\nb\nc\nd\n"),
Theirs: []byte("a\nb\nc\n"),
})
require.NoError(t, err)
assert.False(t, res.Conflict)
assert.Equal(t, "a\nb\nc\nd\n", string(res.Body))
}
func TestConflict(t *testing.T) {
res, err := ThreeWay(Inputs{
Base: []byte("a\n"),
Ours: []byte("a\nours\n"),
Theirs: []byte("a\ntheirs\n"),
})
require.NoError(t, err)
assert.True(t, res.Conflict)
assert.Contains(t, string(res.Body), "<<<<<<<")
assert.Contains(t, string(res.Body), ">>>>>>>")
}
func TestNoOpWhenAllEqual(t *testing.T) {
res, err := ThreeWay(Inputs{
Base: []byte("a\n"),
Ours: []byte("a\n"),
Theirs: []byte("a\n"),
})
require.NoError(t, err)
assert.False(t, res.Conflict)
assert.Equal(t, "a\n", string(res.Body))
}