mirror of https://github.com/garrytan/gstack.git
fix(config): preserve spaces in values
This commit is contained in:
parent
3bef43bc5a
commit
551d0b13be
|
|
@ -248,6 +248,16 @@ resolve_user_slug() {
|
||||||
printf '%s' "$_slug"
|
printf '%s' "$_slug"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_config_value() {
|
||||||
|
local key="$1"
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
grep -E "^${key}:" "$CONFIG_FILE" 2>/dev/null \
|
||||||
|
| tail -1 \
|
||||||
|
| sed -E "s/^${key}:[[:space:]]*//; s/[[:space:]]+$//"
|
||||||
|
}
|
||||||
|
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
get)
|
get)
|
||||||
KEY="${2:?Usage: gstack-config get <key>}"
|
KEY="${2:?Usage: gstack-config get <key>}"
|
||||||
|
|
@ -257,8 +267,7 @@ case "${1:-}" in
|
||||||
echo "Error: key must contain only alphanumeric characters, underscores, and an optional @<hex-hash> suffix" >&2
|
echo "Error: key must contain only alphanumeric characters, underscores, and an optional @<hex-hash> suffix" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# Use literal match for keys containing @ (sha hashes), regex otherwise
|
VALUE=$(read_config_value "$KEY" || true)
|
||||||
VALUE=$(grep -F "${KEY}:" "$CONFIG_FILE" 2>/dev/null | grep -E "^${KEY%@*}(@[a-f0-9]+)?:" | grep -F "${KEY}:" | tail -1 | awk '{print $2}' | tr -d '[:space:]' || true)
|
|
||||||
if [ -z "$VALUE" ]; then
|
if [ -z "$VALUE" ]; then
|
||||||
VALUE=$(lookup_default "$KEY")
|
VALUE=$(lookup_default "$KEY")
|
||||||
fi
|
fi
|
||||||
|
|
@ -307,14 +316,15 @@ case "${1:-}" in
|
||||||
if [ ! -f "$CONFIG_FILE" ]; then
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
printf '%s' "$CONFIG_HEADER" > "$CONFIG_FILE"
|
printf '%s' "$CONFIG_HEADER" > "$CONFIG_FILE"
|
||||||
fi
|
fi
|
||||||
# Escape sed special chars in value and drop embedded newlines
|
# Drop embedded newlines, then escape sed replacement metacharacters.
|
||||||
ESC_VALUE="$(printf '%s' "$VALUE" | head -1 | sed 's/[&/\]/\\&/g')"
|
SAFE_VALUE="$(printf '%s' "$VALUE" | head -1)"
|
||||||
|
ESC_VALUE="$(printf '%s' "$SAFE_VALUE" | sed 's/[&/\]/\\&/g')"
|
||||||
if grep -qE "^${KEY}:" "$CONFIG_FILE" 2>/dev/null; then
|
if grep -qE "^${KEY}:" "$CONFIG_FILE" 2>/dev/null; then
|
||||||
# Portable in-place edit (BSD sed uses -i '', GNU sed uses -i without arg)
|
# Portable in-place edit (BSD sed uses -i '', GNU sed uses -i without arg)
|
||||||
_tmpfile="$(mktemp "${CONFIG_FILE}.XXXXXX")"
|
_tmpfile="$(mktemp "${CONFIG_FILE}.XXXXXX")"
|
||||||
sed "/^${KEY}:/s/.*/${KEY}: ${ESC_VALUE}/" "$CONFIG_FILE" > "$_tmpfile" && mv "$_tmpfile" "$CONFIG_FILE"
|
sed "/^${KEY}:/s/.*/${KEY}: ${ESC_VALUE}/" "$CONFIG_FILE" > "$_tmpfile" && mv "$_tmpfile" "$CONFIG_FILE"
|
||||||
else
|
else
|
||||||
echo "${KEY}: ${VALUE}" >> "$CONFIG_FILE"
|
echo "${KEY}: ${SAFE_VALUE}" >> "$CONFIG_FILE"
|
||||||
fi
|
fi
|
||||||
# Auto-relink skills when prefix setting changes (skip during setup to avoid recursive call)
|
# Auto-relink skills when prefix setting changes (skip during setup to avoid recursive call)
|
||||||
if [ "$KEY" = "skill_prefix" ] && [ -z "${GSTACK_SETUP_RUNNING:-}" ]; then
|
if [ "$KEY" = "skill_prefix" ] && [ -z "${GSTACK_SETUP_RUNNING:-}" ]; then
|
||||||
|
|
@ -332,7 +342,7 @@ case "${1:-}" in
|
||||||
skill_prefix checkpoint_mode checkpoint_push explain_level \
|
skill_prefix checkpoint_mode checkpoint_push explain_level \
|
||||||
codex_reviews gstack_contributor skip_eng_review workspace_root \
|
codex_reviews gstack_contributor skip_eng_review workspace_root \
|
||||||
artifacts_sync_mode artifacts_sync_mode_prompted plan_tune_hooks; do
|
artifacts_sync_mode artifacts_sync_mode_prompted plan_tune_hooks; do
|
||||||
VALUE=$(grep -E "^${KEY}:" "$CONFIG_FILE" 2>/dev/null | tail -1 | awk '{print $2}' | tr -d '[:space:]' || true)
|
VALUE=$(read_config_value "$KEY" || true)
|
||||||
SOURCE="default"
|
SOURCE="default"
|
||||||
if [ -n "$VALUE" ]; then
|
if [ -n "$VALUE" ]; then
|
||||||
SOURCE="set"
|
SOURCE="set"
|
||||||
|
|
|
||||||
|
|
@ -88,3 +88,20 @@ describe('gstack-config explain_level', () => {
|
||||||
expect(run('get', 'explain_level').stdout).toBe('default');
|
expect(run('get', 'explain_level').stdout).toBe('default');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('gstack-config values with spaces', () => {
|
||||||
|
test('workspace_root preserves internal spaces on set/get/list', () => {
|
||||||
|
const value = path.join(os.tmpdir(), 'Conductor Workspaces');
|
||||||
|
expect(run('set', 'workspace_root', value).status).toBe(0);
|
||||||
|
|
||||||
|
expect(run('get', 'workspace_root').stdout).toBe(value);
|
||||||
|
|
||||||
|
const listed = run('list');
|
||||||
|
expect(listed.status).toBe(0);
|
||||||
|
expect(
|
||||||
|
listed.stdout
|
||||||
|
.split('\n')
|
||||||
|
.some((line) => line.includes('workspace_root:') && line.includes(value) && line.includes('(set)')),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue