| ... | ... | @@ -14,6 +14,10 @@ import type { |
| 14 | 14 | TerminalCommandResult, |
| 15 | 15 | } from "@t3tools/contracts"; |
| 16 | 16 | |
| 17 | function escapeSingleQuotes(value: string): string { |
| 18 | return value.replace(/'/g, "'\\''"); |
| 19 | } |
| 20 | |
| 17 | 21 | export async function runTerminalCommand( |
| 18 | 22 | input: TerminalCommandInput, |
| 19 | 23 | ): Promise<TerminalCommandResult> { |
| ... | ... | @@ -111,7 +115,7 @@ export async function listGitBranches( |
| 111 | 115 | current: line.startsWith("* "), |
| 112 | 116 | isDefault: line.replace(/^[*+]\s+/, "") === defaultBranch, |
| 113 | 117 | })) |
| 114 | | .sort((a, b) => { |
| 118 | .toSorted((a, b) => { |
| 115 | 119 | if (a.current !== b.current) return a.current ? -1 : 1; |
| 116 | 120 | if (a.isDefault !== b.isDefault) return a.isDefault ? -1 : 1; |
| 117 | 121 | return a.name.localeCompare(b.name); |
| ... | ... | @@ -123,7 +127,6 @@ export async function listGitBranches( |
| 123 | 127 | export async function createGitWorktree( |
| 124 | 128 | input: GitCreateWorktreeInput, |
| 125 | 129 | ): Promise<GitCreateWorktreeResult> { |
| 126 | | const esc = (s: string) => s.replace(/'/g, "'\\''"); |
| 127 | 130 | const sanitizedBranch = input.newBranch.replace(/\//g, "-"); |
| 128 | 131 | const repoName = path.basename(input.cwd); |
| 129 | 132 | const worktreePath = |
| ... | ... | @@ -132,7 +135,7 @@ export async function createGitWorktree( |
| 132 | 135 | |
| 133 | 136 | // Create a new branch from the base branch in a new worktree |
| 134 | 137 | const result = await runTerminalCommand({ |
| 135 | | command: `git worktree add -b '${esc(input.newBranch)}' '${esc(worktreePath)}' '${esc(input.branch)}'`, |
| 138 | command: `git worktree add -b '${escapeSingleQuotes(input.newBranch)}' '${escapeSingleQuotes(worktreePath)}' '${escapeSingleQuotes(input.branch)}'`, |
| 136 | 139 | cwd: input.cwd, |
| 137 | 140 | timeoutMs: 30_000, |
| 138 | 141 | }); |
| ... | ... | @@ -153,7 +156,7 @@ export async function removeGitWorktree( |
| 153 | 156 | input: GitRemoveWorktreeInput, |
| 154 | 157 | ): Promise<void> { |
| 155 | 158 | const result = await runTerminalCommand({ |
| 156 | | command: `git worktree remove '${input.path.replace(/'/g, "'\\''")}'`, |
| 159 | command: `git worktree remove '${escapeSingleQuotes(input.path)}'`, |
| 157 | 160 | cwd: input.cwd, |
| 158 | 161 | timeoutMs: 15_000, |
| 159 | 162 | }); |
| ... | ... | @@ -167,7 +170,7 @@ export async function createGitBranch( |
| 167 | 170 | input: GitCreateBranchInput, |
| 168 | 171 | ): Promise<void> { |
| 169 | 172 | const result = await runTerminalCommand({ |
| 170 | | command: `git branch '${input.branch.replace(/'/g, "'\\''")}'`, |
| 173 | command: `git branch '${escapeSingleQuotes(input.branch)}'`, |
| 171 | 174 | cwd: input.cwd, |
| 172 | 175 | timeoutMs: 10_000, |
| 173 | 176 | }); |
| ... | ... | @@ -181,7 +184,7 @@ export async function checkoutGitBranch( |
| 181 | 184 | input: GitCheckoutInput, |
| 182 | 185 | ): Promise<void> { |
| 183 | 186 | const result = await runTerminalCommand({ |
| 184 | | command: `git checkout '${input.branch.replace(/'/g, "'\\''")}'`, |
| 187 | command: `git checkout '${escapeSingleQuotes(input.branch)}'`, |
| 185 | 188 | cwd: input.cwd, |
| 186 | 189 | timeoutMs: 10_000, |
| 187 | 190 | }); |