feat(worker): implement TaskMergeService happy path
This commit is contained in:
@@ -75,8 +75,55 @@ public sealed class TaskMergeService
|
|||||||
if (await _git.HasChangesAsync(list.WorkingDir, ct))
|
if (await _git.HasChangesAsync(list.WorkingDir, ct))
|
||||||
return Blocked("target working tree has uncommitted changes");
|
return Blocked("target working tree has uncommitted changes");
|
||||||
|
|
||||||
// Body added in later tasks.
|
var (exitCode, stderr) = await _git.MergeNoFfAsync(list.WorkingDir, wt.BranchName, commitMessage, ct);
|
||||||
throw new NotImplementedException();
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
List<string> files;
|
||||||
|
try { files = await _git.ListConflictedFilesAsync(list.WorkingDir, ct); }
|
||||||
|
catch { files = new(); }
|
||||||
|
try { await _git.MergeAbortAsync(list.WorkingDir, ct); }
|
||||||
|
catch (Exception ex) { _logger.LogWarning(ex, "git merge --abort failed after conflict"); }
|
||||||
|
|
||||||
|
if (files.Count == 0)
|
||||||
|
{
|
||||||
|
// Non-conflict failure (e.g. unrelated histories).
|
||||||
|
return new MergeResult(StatusBlocked, Array.Empty<string>(), $"merge failed: {stderr}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MergeResult(StatusConflict, files, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
string? cleanupWarning = null;
|
||||||
|
if (removeWorktree)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _git.WorktreeRemoveAsync(list.WorkingDir, wt.Path, force: false, ct);
|
||||||
|
try { await _git.BranchDeleteAsync(list.WorkingDir, wt.BranchName, force: false, ct); }
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "branch delete failed for {Branch}", wt.BranchName);
|
||||||
|
cleanupWarning = $"worktree removed, branch delete failed: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "worktree remove failed for {Path}", wt.Path);
|
||||||
|
cleanupWarning = $"worktree remove failed: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var ctx = _dbFactory.CreateDbContext())
|
||||||
|
{
|
||||||
|
await new WorktreeRepository(ctx).SetStateAsync(taskId, WorktreeState.Merged, ct);
|
||||||
|
}
|
||||||
|
await _broadcaster.WorktreeUpdated(taskId);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Merged task {TaskId} branch {Branch} into {Target} (remove worktree: {Remove})",
|
||||||
|
taskId, wt.BranchName, targetBranch, removeWorktree);
|
||||||
|
|
||||||
|
return new MergeResult(StatusMerged, Array.Empty<string>(), cleanupWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MergeTargets> GetTargetsAsync(string taskId, CancellationToken ct)
|
public async Task<MergeTargets> GetTargetsAsync(string taskId, CancellationToken ct)
|
||||||
|
|||||||
Reference in New Issue
Block a user