feat(worker): add ContinueMergeAsync to resume a conflicted merge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-24 15:17:57 +02:00
parent e77ba35b0e
commit 62106ff644
2 changed files with 78 additions and 0 deletions

View File

@@ -155,6 +155,44 @@ public sealed class TaskMergeService
CancellationToken ct)
=> MergeAsync(taskId, targetBranch, removeWorktree, commitMessage, leaveConflictsInTree: false, ct);
public async Task<MergeResult> ContinueMergeAsync(string taskId, CancellationToken ct)
{
TaskEntity task;
ListEntity list;
WorktreeEntity? wt;
using (var ctx = _dbFactory.CreateDbContext())
{
task = await new TaskRepository(ctx).GetByIdAsync(taskId, ct)
?? throw new KeyNotFoundException($"Task '{taskId}' not found.");
list = await new ListRepository(ctx).GetByIdAsync(task.ListId, ct)
?? throw new InvalidOperationException("List not found.");
wt = await new WorktreeRepository(ctx).GetByTaskIdAsync(taskId, ct);
}
if (wt is null) return Blocked("task has no worktree");
if (string.IsNullOrWhiteSpace(list.WorkingDir)) return Blocked("list has no working directory");
if (!await _git.IsMidMergeAsync(list.WorkingDir, ct))
return Blocked("repo is not mid-merge");
await _git.AddAllAsync(list.WorkingDir, ct);
var remaining = await _git.ListConflictedFilesAsync(list.WorkingDir, ct);
if (remaining.Count > 0)
return new MergeResult(StatusConflict, remaining, "conflicts not fully resolved");
await _git.CommitAsync(list.WorkingDir, $"Merge branch '{wt.BranchName}'", ct);
using (var ctx = _dbFactory.CreateDbContext())
{
await new WorktreeRepository(ctx).SetStateAsync(taskId, WorktreeState.Merged, ct);
}
await _broadcaster.WorktreeUpdated(taskId);
_logger.LogInformation("Continued merge of task {TaskId} branch {Branch}", taskId, wt.BranchName);
return new MergeResult(StatusMerged, Array.Empty<string>(), null);
}
public async Task<MergeTargets> GetTargetsAsync(string taskId, CancellationToken ct)
{
TaskEntity task;