Merge content into shared files
Use a merge strategy when a pack contributes part of a UTF-8 text or JSON file instead of owning the complete target.
Run these authoring commands against a synthetic pack created with
Add managed content, not a maintained pack under
projects/packs.
Only merge strategies may share one target. Add the selector with
--strategy merge:<method> and test it against representative consumer content.
Sharing applies across different pack IDs. Two selectors from the same pack
cannot resolve to one target, even when both use merge strategies. Directory or
glob expansion and consumer remapping can create this collision, so verify the
expanded dry-run plan rather than checking only literal targets in pack.yml.
Order contributions
Luna applies contributors in resolved graph order. Dependencies contribute
before consumers, sibling dependencies follow their packs declaration order,
and requested roots follow command or project-configuration order. Managed-file
declarations within one pack retain manifest order. Each contribution merges
into the result of the previous contribution.
This fixed order controls appended lines, JSON array values, and section placement. Consumers cannot override merge order separately. Pack authors who need a different order must reorder dependencies or avoid sharing an order-sensitive target.
Merge unique lines
merge:lines keeps target lines in their existing order, then appends source
lines that do not already occur:
managedFiles:
- source: fragments/.gitignore/example-ignore.gitignore
target: .gitignore
strategy: merge:lines
Comparison is ordinal and includes whitespace and casing, so build/,
Build/, and a line beginning with a space followed by build/ are different
lines. Use this method only when each whole line is an independent entry. It
does not parse comments or key-value formats.
Luna normalizes CRLF and lone CR line endings to LF. The result ends with LF when it is non-empty and either source or target ended with a newline.
Replace a marked section
merge:section requires source content with at least two lines. The first and
last source lines are exact boundary markers:
# luna:formatting:start
dotnet format --verify-no-changes
# luna:formatting:end
managedFiles:
- source: fragments/Directory.Build.targets/example-formatting.targets
target: Directory.Build.targets
strategy: merge
method: section
When neither marker exists, Luna appends the complete source section. When each marker occurs exactly once in the correct order, Luna replaces that inclusive range. Installation stops when only one marker exists, either marker is duplicated, or the closing marker occurs first. Choose pack-specific markers so another tool or pack cannot create an ambiguous match.
Luna normalizes line endings to LF and retains a trailing newline when either input had one.
Merge JSON values
merge:json requires valid UTF-8 JSON. Source and target roots must both be
objects or both be arrays:
managedFiles:
- source: fragments/settings.json/example-settings.json
target: .vscode/settings.json
strategy: merge
method: json
Luna merges objects recursively, appends array values that are not deeply equal
to an existing value, and uses the source value for scalars, null, or nested
values of different kinds. Source {"editor":{"formatOnSave":true}}, for
example, preserves unrelated target properties while setting
editor.formatOnSave to true.
JSON output is rewritten with two-space indentation using Luna's serializer, so property layout may change.
Verify lifecycle behavior
luna pack validate
luna install [email protected] --dry-run
Test an absent target, expected existing content, ambiguous section markers, and a user-modified target. Confirm update and uninstall behavior before release.