refactor: simplify worktree management by removing legacy API

- Remove legacy worktree API usage and related state
- Add Manage Branches button in the Git header for quick access
- Introduce worktree status utilities to derive root branch hints
This commit is contained in:
Bohdan Triapitsyn
2026-02-06 12:38:09 +02:00
parent 2f336a0716
commit 0503f51357
26 changed files with 504 additions and 1450 deletions
-77
View File
@@ -891,24 +891,6 @@ const sanitizeProjects = (input) => {
...(Number.isFinite(lastOpenedAt) && lastOpenedAt >= 0 ? { lastOpenedAt } : {}),
};
// Preserve worktreeDefaults
if (candidate.worktreeDefaults && typeof candidate.worktreeDefaults === 'object') {
const wt = candidate.worktreeDefaults;
const defaults = {};
if (typeof wt.branchPrefix === 'string' && wt.branchPrefix.trim()) {
defaults.branchPrefix = wt.branchPrefix.trim();
}
if (typeof wt.baseBranch === 'string' && wt.baseBranch.trim()) {
defaults.baseBranch = wt.baseBranch.trim();
}
if (typeof wt.autoCreateWorktree === 'boolean') {
defaults.autoCreateWorktree = wt.autoCreateWorktree;
}
if (Object.keys(defaults).length > 0) {
project.worktreeDefaults = defaults;
}
}
if (typeof candidate.sidebarCollapsed === 'boolean') {
project.sidebarCollapsed = candidate.sidebarCollapsed;
}
@@ -7111,65 +7093,6 @@ Context:
}
});
app.post('/api/git/worktrees', async (req, res) => {
const { addWorktree } = await getGitLibraries();
try {
const directory = req.query.directory;
if (!directory) {
return res.status(400).json({ error: 'directory parameter is required' });
}
const { path, branch, createBranch, startPoint } = req.body;
if (!path || !branch) {
return res.status(400).json({ error: 'path and branch are required' });
}
const result = await addWorktree(directory, path, branch, { createBranch, startPoint });
res.json(result);
} catch (error) {
console.error('Failed to add worktree:', error);
res.status(500).json({ error: error.message || 'Failed to add worktree' });
}
});
app.delete('/api/git/worktrees', async (req, res) => {
const { removeWorktree } = await getGitLibraries();
try {
const directory = req.query.directory;
if (!directory) {
return res.status(400).json({ error: 'directory parameter is required' });
}
const { path, force } = req.body;
if (!path) {
return res.status(400).json({ error: 'path is required' });
}
const result = await removeWorktree(directory, path, { force });
res.json(result);
} catch (error) {
console.error('Failed to remove worktree:', error);
res.status(500).json({ error: error.message || 'Failed to remove worktree' });
}
});
app.post('/api/git/ignore-openchamber', async (req, res) => {
// LEGACY_WORKTREES: only needed for <project>/.openchamber era. Safe to remove after legacy support dropped.
const { ensureOpenChamberIgnored } = await getGitLibraries();
try {
const directory = req.query.directory;
if (!directory) {
return res.status(400).json({ error: 'directory parameter is required' });
}
await ensureOpenChamberIgnored(directory);
res.json({ success: true });
} catch (error) {
console.error('Failed to ignore .openchamber directory:', error);
res.status(500).json({ error: error.message || 'Failed to update git ignore' });
}
});
app.get('/api/git/worktree-type', async (req, res) => {
const { isLinkedWorktree } = await getGitLibraries();
try {