|
1 | | -import { mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'; |
| 1 | +import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'; |
2 | 2 | import { tmpdir } from 'node:os'; |
3 | | -import { join } from 'node:path'; |
| 3 | +import { join, relative } from 'node:path'; |
4 | 4 | import { spawnSync } from 'node:child_process'; |
5 | 5 | import { afterEach, expect, it, vi } from 'vitest'; |
6 | 6 | import { removeByName, removeLabelledObjects, TEST_RUN_LABEL } from './fixtures/docker-sweep.ts'; |
@@ -174,23 +174,31 @@ it.each([ |
174 | 174 | expect(readFileSync(calls, 'utf8').split('\n')).toContain(`rm --force ${a}`); |
175 | 175 | }); |
176 | 176 |
|
177 | | -it('finds the real docker once, at load, and refuses a shim when none was found', async () => { |
| 177 | +it('finds the real docker once, at load, uses it by default, and refuses a shim when none was found', async () => { |
178 | 178 | const root = mkdtempSync(join(tmpdir(), 'codeboost-sweep-')); roots.push(root); |
179 | | - // Two directories, each with a docker and the sh the lookup runs, and one with only sh. |
| 179 | + // Two directories, each with a docker and the sh the lookup runs, and one with only sh. Each docker records its calls |
| 180 | + // and answers as Docker 27.4 does for a missing container and for an `ls` with no match; nothing else is asked of it. |
180 | 181 | const bin = (name: string, docker: boolean) => { |
181 | 182 | const dir = join(root, name); mkdirSync(dir); |
182 | 183 | symlinkSync(spawnSync('sh', ['-c', 'command -v sh'], { encoding: 'utf8' }).stdout.trim(), join(dir, 'sh')); |
183 | | - if (docker) writeFileSync(join(dir, 'docker'), '#!/bin/sh\nexit 0\n', { mode: 0o755 }); |
| 184 | + if (docker) writeFileSync(join(dir, 'docker'), ['#!/bin/sh', `printf '%s\\n' "$*" >> '${join(dir, 'calls')}'`, |
| 185 | + 'if [ "$2" = inspect ]; then echo; echo "Error response from daemon: No such container: x" >&2; exit 1; fi', 'exit 0'].join('\n'), |
| 186 | + { mode: 0o755 }); |
184 | 187 | return dir; |
185 | 188 | }; |
186 | 189 | const first = bin('first', true), second = bin('second', true), none = bin('none', false); |
187 | | - vi.stubEnv('PATH', first); |
| 190 | + // A relative PATH entry, resolved at load. |
| 191 | + vi.stubEnv('PATH', relative(process.cwd(), first)); |
188 | 192 | vi.resetModules(); |
189 | 193 | const loaded = await import('./fixtures/docker-sweep.ts') as typeof Sweep; |
190 | | - // A shim put on PATH later does not change it. |
| 194 | + // A shim put on PATH later does not change it, and the removals use it when given no docker. |
191 | 195 | vi.stubEnv('PATH', second); |
192 | 196 | expect(loaded.REAL_DOCKER).toBe(join(first, 'docker')); |
193 | 197 | expect(loaded.requireRealDocker()).toBe(join(first, 'docker')); |
| 198 | + loaded.removeByName('container', 'x', 'test'); |
| 199 | + loaded.removeLabelledObjects(TEST_RUN_LABEL, 'x', 'test'); |
| 200 | + expect(readFileSync(join(first, 'calls'), 'utf8').split('\n').filter(Boolean).length).toBeGreaterThan(1); |
| 201 | + expect(existsSync(join(second, 'calls'))).toBe(false); |
194 | 202 | vi.stubEnv('PATH', none); |
195 | 203 | vi.resetModules(); |
196 | 204 | const missing = await import('./fixtures/docker-sweep.ts') as typeof Sweep; |
|
0 commit comments