| 248 | |
| 249 | // Stops the given containers (by name). Returns true only if all stopped cleanly. |
| 250 | async function stopDockerContainers(names: string[]): Promise<boolean> { |
| 251 | if (names.length === 0) { |
| 252 | return true; |
| 253 | } |
| 254 | return new Promise<boolean>((resolve) => { |
| 255 | const child = spawn('docker', ['stop', ...names], { stdio: ['ignore', 'ignore', 'pipe'] }); |
| 256 | let err = ''; |
| 257 | child.stderr?.on('data', (chunk: Buffer) => { |
| 258 | err += chunk.toString(); |
| 259 | }); |
| 260 | child.on('exit', (code) => { |
| 261 | if (code !== 0 && err.trim()) { |
| 262 | console.error(chalk.red('✗ ') + err.trim()); |
| 263 | } |
| 264 | resolve(code === 0); |
| 265 | }); |
| 266 | child.on('error', () => resolve(false)); |
| 267 | }); |
| 268 | } |
| 269 | |
| 270 | // Mirrors Docker Compose's project-name normalization for the default case |
| 271 | // where the project name is derived from the working directory basename. |