From f9b2f191c6c106dd7edbf0f846540133941d313b Mon Sep 17 00:00:00 2001 From: Bham06 Date: Tue, 28 Jul 2026 19:25:50 +0100 Subject: [PATCH] schemas: Indent .lock.json for readability The schema lock file (.lock.json) was written on a single line, making it hard to read and prone to merge conflicts whenever more than one dependency changed. Write it with json.MarshalIndent (two-space indent) and a trailing newline so each dependency is on its own line. Reads are unaffected; getLock decodes the file with a json.Decoder and indented JSON remains valid. Fixes #168 Signed-off-by: Bham06 --- internal/schemas/manager/manager.go | 5 +++- internal/schemas/manager/manager_test.go | 32 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/internal/schemas/manager/manager.go b/internal/schemas/manager/manager.go index ee87194d..3fe60e7c 100644 --- a/internal/schemas/manager/manager.go +++ b/internal/schemas/manager/manager.go @@ -231,10 +231,13 @@ func (m *Manager) updateLock(l *lock) error { return errors.Wrap(err, "failed to ensure schema directory exists") } - bs, err := json.Marshal(l) + bs, err := json.MarshalIndent(l, "", " ") if err != nil { return errors.Wrap(err, "failed to serialize schema lock") } + // Append a trailing newline so the file ends cleanly and edits to the last + // entry produce minimal diffs. + bs = append(bs, '\n') if err := afero.WriteFile(m.fs, lockFileName, bs, 0o600); err != nil { return errors.Wrap(err, "failed to write schema lock file") diff --git a/internal/schemas/manager/manager_test.go b/internal/schemas/manager/manager_test.go index 8dba1a28..62e1b18c 100644 --- a/internal/schemas/manager/manager_test.go +++ b/internal/schemas/manager/manager_test.go @@ -171,6 +171,38 @@ func TestManager_Add(t *testing.T) { } } +func TestUpdateLockIsIndented(t *testing.T) { + // The lock file must be written with one entry per line (indented) so it is + // human-readable and avoids spurious merge conflicts. See issue #168. + fs := afero.NewMemMapFs() + m := New(fs, nil, nil) + + l := newLock() + l.Packages["xpkg://pkg.example/bar:v1.0.0"] = "sha256:bbb" + l.Packages["xpkg://pkg.example/foo:v0.5.2"] = "sha256:aaa" + + if err := m.updateLock(l); err != nil { + t.Fatalf("updateLock: %v", err) + } + + got, err := afero.ReadFile(fs, lockFileName) + if err != nil { + t.Fatalf("read lock: %v", err) + } + + // Map keys are marshalled in sorted order, so this golden is deterministic. + want := `{ + "packages": { + "xpkg://pkg.example/bar:v1.0.0": "sha256:bbb", + "xpkg://pkg.example/foo:v0.5.2": "sha256:aaa" + } +} +` + if diff := cmp.Diff(want, string(got)); diff != "" { + t.Errorf("lock file is not indented as expected (-want +got):\n%s", diff) + } +} + type mockGenerator struct { files map[string]string }