MCPcopy Create free account
hub / github.com/Noumena-Network/code / performPostCreationSetup

Function performPostCreationSetup

src/utils/worktree.ts:522–636  ·  view source on GitHub ↗

* Post-creation setup for a newly created worktree. * Propagates settings.local.json, configures git hooks, and symlinks directories.

(
  repoRoot: string,
  worktreePath: string,
)

Source from the content-addressed store, hash-verified

520 * Propagates settings.local.json, configures git hooks, and symlinks directories.
521 */
522async function performPostCreationSetup(
523 repoRoot: string,
524 worktreePath: string,
525): Promise<void> {
526 // Copy settings.local.json to the worktree's .claude directory
527 // This propagates local settings (which may contain secrets) to the worktree
528 const localSettingsRelativePath =
529 getRelativeSettingsFilePathForSource('localSettings')
530 const sourceSettingsLocal = join(repoRoot, localSettingsRelativePath)
531 try {
532 const destSettingsLocal = join(worktreePath, localSettingsRelativePath)
533 await mkdirRecursive(dirname(destSettingsLocal))
534 await copyFile(sourceSettingsLocal, destSettingsLocal)
535 logForDebugging(
536 `Copied settings.local.json to worktree: ${destSettingsLocal}`,
537 )
538 } catch (e: unknown) {
539 const code = getErrnoCode(e)
540 if (code !== 'ENOENT') {
541 logForDebugging(
542 `Failed to copy settings.local.json: ${(e as Error).message}`,
543 { level: 'warn' },
544 )
545 }
546 }
547
548 // Configure the worktree to use hooks from the main repository
549 // This solves issues with .husky and other git hooks that use relative paths
550 const huskyPath = join(repoRoot, '.husky')
551 const gitHooksPath = join(repoRoot, '.git', 'hooks')
552 let hooksPath: string | null = null
553 for (const candidatePath of [huskyPath, gitHooksPath]) {
554 try {
555 const s = await stat(candidatePath)
556 if (s.isDirectory()) {
557 hooksPath = candidatePath
558 break
559 }
560 } catch {
561 // Path doesn't exist or can't be accessed
562 }
563 }
564 if (hooksPath) {
565 // `git config` (no --worktree flag) writes to the main repo's .git/config,
566 // shared by all worktrees. Once set, every subsequent worktree create is a
567 // no-op — skip the subprocess (~14ms spawn) when the value already matches.
568 const gitDir = await resolveGitDir(repoRoot)
569 const configDir = gitDir ? ((await getCommonDir(gitDir)) ?? gitDir) : null
570 const existing = configDir
571 ? await parseGitConfigValue(configDir, 'core', null, 'hooksPath')
572 : null
573 if (existing !== hooksPath) {
574 const { code: configCode, stderr: configError } =
575 await execFileNoThrowWithCwd(
576 gitExe(),
577 ['config', 'core.hooksPath', hooksPath],
578 { cwd: worktreePath },
579 )

Callers 3

createWorktreeForSessionFunction · 0.85
createAgentWorktreeFunction · 0.85
execIntoTmuxWorktreeFunction · 0.85

Calls 12

mkdirRecursiveFunction · 0.85
getErrnoCodeFunction · 0.85
statFunction · 0.85
resolveGitDirFunction · 0.85
getCommonDirFunction · 0.85
parseGitConfigValueFunction · 0.85
execFileNoThrowWithCwdFunction · 0.85
symlinkDirectoriesFunction · 0.85
copyWorktreeIncludeFilesFunction · 0.85
logForDebuggingFunction · 0.70
getInitialSettingsFunction · 0.50

Tested by

no test coverage detected