claude-dev-env 8.40.0 → 8.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/install.mjs
CHANGED
|
@@ -1364,8 +1364,12 @@ function commandRunsHookOfRootSharingSettings(normalizedCommand, relativePath, s
|
|
|
1364
1364
|
const characterAfterPath = normalizedCommand[tailStart + hookPathTail.length];
|
|
1365
1365
|
if (characterAfterPath === undefined || commandArgumentBoundary.test(characterAfterPath)) {
|
|
1366
1366
|
let rootStart = tailStart;
|
|
1367
|
-
|
|
1368
|
-
rootStart
|
|
1367
|
+
if (characterAfterPath === '"' || characterAfterPath === "'") {
|
|
1368
|
+
rootStart = normalizedCommand.lastIndexOf(characterAfterPath, tailStart - 1) + 1;
|
|
1369
|
+
} else {
|
|
1370
|
+
while (rootStart > 0 && !commandArgumentBoundary.test(normalizedCommand[rootStart - 1])) {
|
|
1371
|
+
rootStart--;
|
|
1372
|
+
}
|
|
1369
1373
|
}
|
|
1370
1374
|
const rootPath = normalizedCommand.slice(rootStart, tailStart);
|
|
1371
1375
|
const rootSettingsRealPath = rootPath
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { tmpdir } from 'node:os';
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
19
19
|
import { spawnSync } from 'node:child_process';
|
|
20
|
-
import { managedHookScriptRelativePaths, mergeHooksIntoSettings } from './install.mjs';
|
|
20
|
+
import { commandArgumentFromPath, managedHookScriptRelativePaths, mergeHooksIntoSettings } from './install.mjs';
|
|
21
21
|
|
|
22
22
|
const INSTALLER_PATH = fileURLToPath(new URL('./install.mjs', import.meta.url));
|
|
23
23
|
const PACKAGE_HOOKS_JSON_PATH = fileURLToPath(new URL('../hooks/hooks.json', import.meta.url));
|
|
@@ -200,3 +200,46 @@ test('the merge prunes a hook of a root sharing the settings file and keeps one
|
|
|
200
200
|
rmSync(sandboxRoot, { recursive: true, force: true });
|
|
201
201
|
}
|
|
202
202
|
});
|
|
203
|
+
|
|
204
|
+
test('the merge prunes a quoted hook of a sharing root whose path holds a space', t => {
|
|
205
|
+
const sandboxRoot = mkdtempSync(join(tmpdir(), 'cdev-shared-settings-space-'));
|
|
206
|
+
try {
|
|
207
|
+
const installRoot = join(sandboxRoot, 'install-root');
|
|
208
|
+
const sharingRoot = join(sandboxRoot, 'Jane Doe', 'profiles', 'second');
|
|
209
|
+
for (const eachRoot of [installRoot, sharingRoot]) mkdirSync(eachRoot, { recursive: true });
|
|
210
|
+
const settingsPath = join(installRoot, 'settings.json');
|
|
211
|
+
writeFileSync(settingsPath, '{}\n');
|
|
212
|
+
try {
|
|
213
|
+
symlinkSync(settingsPath, join(sharingRoot, 'settings.json'), 'file');
|
|
214
|
+
} catch (linkError) {
|
|
215
|
+
t.skip(`this host cannot create a file symlink (${linkError.code})`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const hooksConfig = {
|
|
219
|
+
hooks: {
|
|
220
|
+
SessionStart: [{
|
|
221
|
+
matcher: '',
|
|
222
|
+
hooks: [{ type: 'command', command: 'python3 ${CLAUDE_PLUGIN_ROOT}/hooks/session/start.py' }],
|
|
223
|
+
}],
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
const forwardSlashed = rootPath => rootPath.replace(/\\/g, '/');
|
|
227
|
+
const sharingHookPath = `${forwardSlashed(sharingRoot)}/hooks/session/start.py`;
|
|
228
|
+
for (const eachPlatform of ['linux', 'win32']) {
|
|
229
|
+
const sharingCommand = `python3 ${commandArgumentFromPath(sharingHookPath, eachPlatform)}`;
|
|
230
|
+
const settings = {
|
|
231
|
+
hooks: {
|
|
232
|
+
SessionStart: [{ matcher: '', hooks: [{ type: 'command', command: sharingCommand }] }],
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
mergeHooksIntoSettings(settings, hooksConfig, forwardSlashed(installRoot), 'python3', settingsPath);
|
|
237
|
+
|
|
238
|
+
const allCommands = settings.hooks.SessionStart.flatMap(group => group.hooks.map(hook => hook.command));
|
|
239
|
+
assert.ok(!allCommands.includes(sharingCommand), `the ${eachPlatform}-quoted sharing root entry is pruned`);
|
|
240
|
+
assert.equal(allCommands.length, 1, `only the install root entry stays after the ${eachPlatform} merge`);
|
|
241
|
+
}
|
|
242
|
+
} finally {
|
|
243
|
+
rmSync(sandboxRoot, { recursive: true, force: true });
|
|
244
|
+
}
|
|
245
|
+
});
|