Skip to content

Add --preserve for surgical, formatting-preserving json/yaml edits#6

Merged
machado144 merged 1 commit into
mainfrom
feature/preserve-formatting-edits
Jun 8, 2026
Merged

Add --preserve for surgical, formatting-preserving json/yaml edits#6
machado144 merged 1 commit into
mainfrom
feature/preserve-formatting-edits

Conversation

@machado144

@machado144 machado144 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

Adds a --preserve (-P) flag to json/yaml set and del. Instead of the default decode → mutate → re-encode round-trip (which drops comments, reorders keys, re-indents, and rewrites quoting), --preserve performs a byte-level surgical edit: only the targeted node changes and everything else stays byte-for-byte identical — comments and their column alignment, key order, quoting style, indentation, and blank lines.

Motivation: bumping e.g. .image.tag in a hand-maintained Helm values.yaml shouldn't reformat the whole file.

How

  • YAML — locate the target via the yaml.Node source line/column and splice the new value into the original bytes. Every splice is re-parsed and validated against the intended value; on any mismatch (e.g. a type-ambiguous plain-numeric edit) it falls back to the safe re-encode path, so a surgical edit can never corrupt or mis-edit the file.
  • JSON — splice the exact value span. set can also insert a new key into an existing object, formatting-matched to its siblings (mirrors comma/newline separator and colon spacing). del removes the entry plus one adjacent comma.
  • Atomic writes — in-place writes go through temp file + fsync + rename, preserving the original file's permission bits. A crash mid-write can't truncate the file.
  • toml/csv return a clear error in preserve mode.

Compatibility

Default behavior is unchanged; --preserve is strictly opt-in.

Examples

# Edit existing value — only this line changes, comments/alignment kept
pipekit yaml set values.yaml --path '.image.tag' --value 'v2.0.0' --in-place --preserve

# Insert a new key, formatting-matched
pipekit json set config.json --path '.newKey' --json-value '{"on":true}' --in-place --preserve

# Delete a key, keeping the rest intact
pipekit json del config.json --path '.legacy' --in-place --preserve

Tests

  • 29 service tests, including byte-for-byte YAML set/del assertions and JSON insert cases.
  • 4 end-to-end tests (preserve set, del, key insert, file-mode retention).
  • Full suite (243 tests) green, go vet clean.

json/yaml set/del gain a --preserve (-P) flag that performs byte-level
edits instead of the default decode/re-encode round-trip, so only the
targeted node changes and everything else (comments and their column
alignment, key order, quoting, indentation, blank lines) stays
byte-for-byte identical.

- YAML: locate the target via the yaml.Node source line/column and splice
  the new value into the original bytes; every splice is re-parsed and
  validated, falling back to the safe re-encode path on any mismatch.
- JSON: splice the exact value span; set can also insert a new key into an
  existing object, formatting-matched to siblings; del drops the entry plus
  one adjacent comma.
- In-place writes are atomic (temp file + fsync + rename) and preserve the
  original file mode.
- toml/csv return a clear error in preserve mode.

Default behavior is unchanged; --preserve is opt-in. Adds 29 service tests
and 4 end-to-end tests.
@machado144 machado144 merged commit bbfb68e into main Jun 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant