feat(scripts): merge-settings.sh — jq merge with preservation of theme/editorMode
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"theme": "dark",
|
||||
"editorMode": "vscode",
|
||||
"statusLine": "compact",
|
||||
"enabledPlugins": {
|
||||
"old-plugin@old-marketplace": true
|
||||
},
|
||||
"permissions": {
|
||||
"allow": ["Bash(old:*)"],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
},
|
||||
"hooks": {
|
||||
"SessionStart": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# Merge brain settings-fragment.json into consumer's settings.json
|
||||
# Replaces: enabledPlugins, permissions, hooks
|
||||
# Preserves: theme, editorMode, statusLine, all other keys
|
||||
#
|
||||
# Usage: merge-settings.sh <consumer-settings.json> <brain-fragment.json>
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
target="$1"
|
||||
fragment="$2"
|
||||
|
||||
require_cmd jq || exit 1
|
||||
[ -f "$fragment" ] || { log_error "Fragment not found: $fragment"; exit 1; }
|
||||
|
||||
# If target doesn't exist, just copy fragment
|
||||
if [ ! -f "$target" ]; then
|
||||
log_info "Target settings.json missing, creating from fragment"
|
||||
cp "$fragment" "$target"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Backup
|
||||
backup="${target}.bak.$(date +%s)"
|
||||
cp "$target" "$backup"
|
||||
|
||||
# Merge: target.* keys preserved EXCEPT enabledPlugins/permissions/hooks — those are REPLACED
|
||||
# (not deep-merged) from fragment. Use --slurpfile to load fragment into $frag.
|
||||
tmp="${target}.tmp"
|
||||
jq --slurpfile frag "$fragment" \
|
||||
'.enabledPlugins = $frag[0].enabledPlugins
|
||||
| .permissions = $frag[0].permissions
|
||||
| .hooks = $frag[0].hooks' \
|
||||
"$target" > "$tmp"
|
||||
|
||||
# Validate output JSON
|
||||
jq empty "$tmp" || { log_error "Merge produced invalid JSON"; rm "$tmp"; exit 1; }
|
||||
|
||||
mv "$tmp" "$target"
|
||||
log_info "settings.json merged (backup: $backup)"
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
source "$SCRIPT_DIR/lib/common.sh"
|
||||
|
||||
FAILURES=0
|
||||
assert_eq() {
|
||||
local expected="$1" actual="$2" name="$3"
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "PASS: $name"
|
||||
else
|
||||
echo "FAIL: $name (expected '$expected', got '$actual')"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# Setup: temp consumer settings + brain fragment
|
||||
tmpdir=$(mktemp -d)
|
||||
cp "$SCRIPT_DIR/fixtures/sample-settings.json" "$tmpdir/settings.json"
|
||||
cat > "$tmpdir/fragment.json" <<EOF2
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"new-plugin@new-mp": true
|
||||
},
|
||||
"permissions": {
|
||||
"allow": ["Bash(new:*)"],
|
||||
"deny": ["Bash(rm:*)"],
|
||||
"ask": []
|
||||
},
|
||||
"hooks": {
|
||||
"SessionStart": [{"hooks": [{"type": "command", "command": "echo new"}]}]
|
||||
}
|
||||
}
|
||||
EOF2
|
||||
|
||||
# Run merge
|
||||
bash "$SCRIPT_DIR/lib/merge-settings.sh" "$tmpdir/settings.json" "$tmpdir/fragment.json"
|
||||
|
||||
# Test 1: theme preserved
|
||||
theme=$(jq -r '.theme' "$tmpdir/settings.json")
|
||||
assert_eq "dark" "$theme" "theme preserved"
|
||||
|
||||
# Test 2: editorMode preserved
|
||||
em=$(jq -r '.editorMode' "$tmpdir/settings.json")
|
||||
assert_eq "vscode" "$em" "editorMode preserved"
|
||||
|
||||
# Test 3: enabledPlugins replaced (not merged)
|
||||
plugins=$(jq -r '.enabledPlugins | keys[]' "$tmpdir/settings.json")
|
||||
assert_eq "new-plugin@new-mp" "$plugins" "enabledPlugins replaced with brain version"
|
||||
|
||||
# Test 4: permissions.deny populated from fragment
|
||||
deny=$(jq -r '.permissions.deny[0]' "$tmpdir/settings.json")
|
||||
assert_eq "Bash(rm:*)" "$deny" "permissions.deny from fragment"
|
||||
|
||||
# Test 5: hooks replaced
|
||||
hook_cmd=$(jq -r '.hooks.SessionStart[0].hooks[0].command' "$tmpdir/settings.json")
|
||||
assert_eq "echo new" "$hook_cmd" "hooks replaced with brain version"
|
||||
|
||||
# Cleanup
|
||||
rm -rf "$tmpdir"
|
||||
|
||||
echo "---"
|
||||
echo "Failures: $FAILURES"
|
||||
exit $FAILURES
|
||||
Reference in New Issue
Block a user