Skip to content

Commit 66c2a82

Browse files
committed
🤖 Remove dead code from gitService
removeWorktreeSafe(), isWorktreeClean(), and hasSubmodules() were orphaned during the Runtime architecture refactoring (commit 95c0a14, Oct 25). Production now uses Runtime.deleteWorkspace() for all workspace deletion. These functions existed only in tests and provided no value. Changes: - Removed 153 lines of dead code from gitService.ts (189 → 36 lines) - Removed 265 lines of dead tests (275 → 10 lines) - Total: 418 lines removed - Tests: 807 → 796 (removed 11 tests for dead functions) The active functions (removeWorktree, pruneWorktrees) are preserved as they're used by ipcMain for cleanup operations. _Generated with `cmux`_
1 parent 551370d commit 66c2a82

File tree

2 files changed

+7
-422
lines changed

2 files changed

+7
-422
lines changed

src/services/gitService.test.ts

Lines changed: 7 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -1,273 +1,10 @@
1-
import { describe, test, expect, beforeEach, afterEach } from "@jest/globals";
2-
import * as fs from "fs/promises";
3-
import * as path from "path";
4-
import { execSync } from "child_process";
5-
import { removeWorktreeSafe, isWorktreeClean, hasSubmodules } from "./gitService";
6-
import { createWorktree, detectDefaultTrunkBranch } from "@/git";
7-
import type { Config } from "@/config";
1+
import { describe } from "@jest/globals";
82

9-
// Helper to create a test git repo
10-
async function createTestRepo(basePath: string): Promise<string> {
11-
const repoPath = path.join(basePath, "test-repo");
12-
await fs.mkdir(repoPath, { recursive: true });
3+
// gitService.ts exports removeWorktree() and pruneWorktrees() which are used by ipcMain.
4+
// These functions are thin wrappers around git commands and are better tested via
5+
// integration tests that exercise the full Runtime.deleteWorkspace() flow.
136

14-
execSync("git init", { cwd: repoPath });
15-
execSync("git config user.email 'test@test.com'", { cwd: repoPath });
16-
execSync("git config user.name 'Test User'", { cwd: repoPath });
17-
18-
// Create initial commit
19-
await fs.writeFile(path.join(repoPath, "README.md"), "# Test Repo");
20-
execSync("git add .", { cwd: repoPath });
21-
execSync('git commit -m "Initial commit"', { cwd: repoPath });
22-
23-
return repoPath;
24-
}
25-
26-
// Helper to create mock config with unique temp directory
27-
function createMockConfig(tempDir: string): Config {
28-
return {
29-
srcDir: path.join(tempDir, "test-workspaces"),
30-
getWorkspacePath: (projectPath: string, branchName: string) => {
31-
return path.join(path.dirname(projectPath), "workspaces", branchName);
32-
},
33-
} as unknown as Config;
34-
}
35-
36-
describe("removeWorktreeSafe", () => {
37-
let tempDir: string;
38-
let repoPath: string;
39-
let defaultBranch: string;
40-
let mockConfig: Config;
41-
42-
beforeEach(async () => {
43-
tempDir = await fs.mkdtemp(path.join(__dirname, "..", "test-temp-"));
44-
mockConfig = createMockConfig(tempDir);
45-
repoPath = await createTestRepo(tempDir);
46-
defaultBranch = await detectDefaultTrunkBranch(repoPath);
47-
});
48-
49-
afterEach(async () => {
50-
try {
51-
await fs.rm(tempDir, { recursive: true, force: true });
52-
} catch {
53-
// Ignore cleanup errors
54-
}
55-
});
56-
57-
test("should instantly remove clean worktree via rename", async () => {
58-
// Create a worktree
59-
const result = await createWorktree(mockConfig, repoPath, "test-branch", {
60-
trunkBranch: defaultBranch,
61-
});
62-
expect(result.success).toBe(true);
63-
const worktreePath = result.path!;
64-
65-
// Verify worktree exists
66-
const existsBefore = await fs
67-
.access(worktreePath)
68-
.then(() => true)
69-
.catch(() => false);
70-
expect(existsBefore).toBe(true);
71-
72-
// Remove it (should be instant since it's clean)
73-
const startTime = Date.now();
74-
const removeResult = await removeWorktreeSafe(repoPath, worktreePath);
75-
const duration = Date.now() - startTime;
76-
77-
expect(removeResult.success).toBe(true);
78-
79-
// Should complete quickly (<200ms accounting for CI overhead)
80-
expect(duration).toBeLessThan(200);
81-
82-
// Worktree should be gone immediately
83-
const existsAfter = await fs
84-
.access(worktreePath)
85-
.then(() => true)
86-
.catch(() => false);
87-
expect(existsAfter).toBe(false);
88-
});
89-
90-
test("should block removal of dirty worktree", async () => {
91-
// Create a worktree
92-
const result = await createWorktree(mockConfig, repoPath, "dirty-branch", {
93-
trunkBranch: defaultBranch,
94-
});
95-
expect(result.success).toBe(true);
96-
const worktreePath = result.path!;
97-
98-
// Make it dirty by adding uncommitted changes
99-
await fs.writeFile(path.join(worktreePath, "new-file.txt"), "uncommitted content");
100-
101-
// Verify it's dirty
102-
const isClean = await isWorktreeClean(worktreePath);
103-
expect(isClean).toBe(false);
104-
105-
// Try to remove it - should fail due to uncommitted changes
106-
const removeResult = await removeWorktreeSafe(repoPath, worktreePath);
107-
108-
expect(removeResult.success).toBe(false);
109-
expect(removeResult.error).toMatch(/modified|untracked|changes/i);
110-
111-
// Worktree should still exist
112-
const existsAfter = await fs
113-
.access(worktreePath)
114-
.then(() => true)
115-
.catch(() => false);
116-
expect(existsAfter).toBe(true);
117-
});
118-
119-
test("should handle already-deleted worktree gracefully", async () => {
120-
// Create a worktree
121-
const result = await createWorktree(mockConfig, repoPath, "temp-branch", {
122-
trunkBranch: defaultBranch,
123-
});
124-
expect(result.success).toBe(true);
125-
const worktreePath = result.path!;
126-
127-
// Manually delete it (simulating external deletion)
128-
await fs.rm(worktreePath, { recursive: true, force: true });
129-
130-
// Remove via removeWorktreeSafe - should succeed and prune git records
131-
const removeResult = await removeWorktreeSafe(repoPath, worktreePath);
132-
133-
expect(removeResult.success).toBe(true);
134-
});
135-
136-
test("should remove clean worktree with staged changes using git", async () => {
137-
// Create a worktree
138-
const result = await createWorktree(mockConfig, repoPath, "staged-branch", {
139-
trunkBranch: defaultBranch,
140-
});
141-
expect(result.success).toBe(true);
142-
const worktreePath = result.path!;
143-
144-
// Add staged changes
145-
await fs.writeFile(path.join(worktreePath, "staged.txt"), "staged content");
146-
execSync("git add .", { cwd: worktreePath });
147-
148-
// Verify it's dirty (staged changes count as dirty)
149-
const isClean = await isWorktreeClean(worktreePath);
150-
expect(isClean).toBe(false);
151-
152-
// Try to remove it - should fail
153-
const removeResult = await removeWorktreeSafe(repoPath, worktreePath);
154-
155-
expect(removeResult.success).toBe(false);
156-
});
157-
158-
test("should call onBackgroundDelete callback on errors", async () => {
159-
// Create a worktree
160-
const result = await createWorktree(mockConfig, repoPath, "callback-branch", {
161-
trunkBranch: defaultBranch,
162-
});
163-
expect(result.success).toBe(true);
164-
const worktreePath = result.path!;
165-
166-
const errors: Array<{ tempDir: string; error?: Error }> = [];
167-
168-
// Remove it
169-
const removeResult = await removeWorktreeSafe(repoPath, worktreePath, {
170-
onBackgroundDelete: (tempDir, error) => {
171-
errors.push({ tempDir, error });
172-
},
173-
});
174-
175-
expect(removeResult.success).toBe(true);
176-
177-
// Wait a bit for background deletion to complete
178-
await new Promise((resolve) => setTimeout(resolve, 100));
179-
180-
// Callback should be called for successful background deletion
181-
// (or not called at all if deletion succeeds without error)
182-
// This test mainly ensures the callback doesn't crash
183-
});
184-
});
185-
186-
describe("isWorktreeClean", () => {
187-
let tempDir: string;
188-
let repoPath: string;
189-
let defaultBranch: string;
190-
let mockConfig: Config;
191-
192-
beforeEach(async () => {
193-
tempDir = await fs.mkdtemp(path.join(__dirname, "..", "test-temp-"));
194-
mockConfig = createMockConfig(tempDir);
195-
repoPath = await createTestRepo(tempDir);
196-
defaultBranch = await detectDefaultTrunkBranch(repoPath);
197-
});
198-
199-
afterEach(async () => {
200-
try {
201-
await fs.rm(tempDir, { recursive: true, force: true });
202-
} catch {
203-
// Ignore cleanup errors
204-
}
205-
});
206-
207-
test("should return true for clean worktree", async () => {
208-
const result = await createWorktree(mockConfig, repoPath, "clean-check", {
209-
trunkBranch: defaultBranch,
210-
});
211-
expect(result.success).toBe(true);
212-
213-
const isClean = await isWorktreeClean(result.path!);
214-
expect(isClean).toBe(true);
215-
});
216-
217-
test("should return false for worktree with uncommitted changes", async () => {
218-
const result = await createWorktree(mockConfig, repoPath, "dirty-check", {
219-
trunkBranch: defaultBranch,
220-
});
221-
expect(result.success).toBe(true);
222-
const worktreePath = result.path!;
223-
224-
// Add uncommitted file
225-
await fs.writeFile(path.join(worktreePath, "uncommitted.txt"), "content");
226-
227-
const isClean = await isWorktreeClean(worktreePath);
228-
expect(isClean).toBe(false);
229-
});
230-
231-
test("should return false for non-existent path", async () => {
232-
const isClean = await isWorktreeClean("/non/existent/path");
233-
expect(isClean).toBe(false);
234-
});
235-
});
236-
237-
describe("hasSubmodules", () => {
238-
let tempDir: string;
239-
240-
beforeEach(async () => {
241-
tempDir = await fs.mkdtemp(path.join(__dirname, "..", "test-temp-"));
242-
});
243-
244-
afterEach(async () => {
245-
try {
246-
await fs.rm(tempDir, { recursive: true, force: true });
247-
} catch {
248-
// Ignore cleanup errors
249-
}
250-
});
251-
252-
test("should return true when .gitmodules exists", async () => {
253-
const testDir = path.join(tempDir, "with-submodule");
254-
await fs.mkdir(testDir, { recursive: true });
255-
await fs.writeFile(path.join(testDir, ".gitmodules"), '[submodule "test"]\n\tpath = test\n');
256-
257-
const result = await hasSubmodules(testDir);
258-
expect(result).toBe(true);
259-
});
260-
261-
test("should return false when .gitmodules does not exist", async () => {
262-
const testDir = path.join(tempDir, "no-submodule");
263-
await fs.mkdir(testDir, { recursive: true });
264-
265-
const result = await hasSubmodules(testDir);
266-
expect(result).toBe(false);
267-
});
268-
269-
test("should return false for non-existent path", async () => {
270-
const result = await hasSubmodules("/non/existent/path");
271-
expect(result).toBe(false);
272-
});
7+
describe("gitService", () => {
8+
// Placeholder describe block to keep test file structure
9+
// Add unit tests here if needed for removeWorktree() or pruneWorktrees()
27310
});

0 commit comments

Comments
 (0)