Skip to content

Commit 0009536

Browse files
committed
Escape GT binary paths in JSON hook templates
1 parent 99b806c commit 0009536

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

internal/hooks/installer.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,28 @@ func resolveAndSubstitute(provider, hooksFile, role string) ([]byte, error) {
150150

151151
if bytes.Contains(content, []byte("{{GT_BIN}}")) {
152152
gtBin := resolveGTBinary()
153+
if isSettingsFile(hooksFile) {
154+
gtBin = jsonTemplateStringValue(gtBin)
155+
}
153156
content = bytes.ReplaceAll(content, []byte("{{GT_BIN}}"), []byte(gtBin))
154157
}
155158

156159
return content, nil
157160
}
158161

162+
// jsonTemplateStringValue escapes a string for insertion into an existing JSON
163+
// string literal template. json.Marshal adds surrounding quotes, so strip them.
164+
func jsonTemplateStringValue(value string) string {
165+
encoded, err := json.Marshal(value)
166+
if err != nil {
167+
return value
168+
}
169+
if len(encoded) >= 2 {
170+
return string(encoded[1 : len(encoded)-1])
171+
}
172+
return value
173+
}
174+
159175
// writeTemplate resolves a template, substitutes placeholders, and writes it to targetPath.
160176
func writeTemplate(provider, role, hooksFile, targetPath string) error {
161177
content, err := resolveAndSubstitute(provider, hooksFile, role)

internal/hooks/installer_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,19 @@ func TestSyncForRole_GeminiWithGTBinSubstitution(t *testing.T) {
281281
}
282282
}
283283

284+
func TestJSONTemplateStringValue_EscapesWindowsPath(t *testing.T) {
285+
value := `C:\Users\sws\bin\gt.exe`
286+
escaped := jsonTemplateStringValue(value)
287+
288+
var decoded string
289+
if err := json.Unmarshal([]byte(`"`+escaped+`"`), &decoded); err != nil {
290+
t.Fatalf("json.Unmarshal escaped value: %v", err)
291+
}
292+
if decoded != value {
293+
t.Fatalf("decoded value = %q, want %q", decoded, value)
294+
}
295+
}
296+
284297
func TestInstallForRole_SettingsDirVsWorkDir(t *testing.T) {
285298
settingsDir := t.TempDir()
286299
workDir := t.TempDir()

0 commit comments

Comments
 (0)