feat(worker): use the list base branch as worktree base and default merge target
This commit is contained in:
+1
-3
@@ -865,9 +865,7 @@ public sealed class MergeMcpTools
|
||||
throw new InvalidOperationException(
|
||||
"Merge preview unavailable for this task (worktree inactive or repo is not a git repository).");
|
||||
|
||||
var target = string.IsNullOrWhiteSpace(targetBranch)
|
||||
? await _git.GetCurrentBranchAsync(list.WorkingDir, ct)
|
||||
: targetBranch;
|
||||
var target = await _merge.ResolveTargetAsync(list, targetBranch, ct);
|
||||
var behind = await WorktreeMcpTools.GitRevListCountAsync(list.WorkingDir, $"{wt.BranchName}..{target}", ct);
|
||||
|
||||
var changedFiles = Directory.Exists(wt.Path)
|
||||
|
||||
@@ -411,6 +411,7 @@ public sealed class TaskMergeService
|
||||
return new MergeResult(StatusDirtyTarget, Array.Empty<string>(),
|
||||
"target working tree has uncommitted changes");
|
||||
|
||||
targetBranch = await ResolveTargetAsync(list, targetBranch, ct);
|
||||
var currentBranch = await _git.GetCurrentBranchAsync(list.WorkingDir, ct);
|
||||
if (!string.Equals(currentBranch, targetBranch, StringComparison.Ordinal))
|
||||
{
|
||||
@@ -874,12 +875,26 @@ public sealed class TaskMergeService
|
||||
if (string.IsNullOrWhiteSpace(list.WorkingDir))
|
||||
return new MergeTargets("", Array.Empty<string>(), defaultMessage);
|
||||
|
||||
var current = await _git.GetCurrentBranchAsync(list.WorkingDir, ct);
|
||||
var current = await ResolveTargetAsync(list, null, ct);
|
||||
var branches = await _git.ListLocalBranchesAsync(list.WorkingDir, ct);
|
||||
var dirty = await _git.HasChangesAsync(list.WorkingDir, includeUntracked: false, ct);
|
||||
return new MergeTargets(current, branches, defaultMessage, dirty);
|
||||
}
|
||||
|
||||
/// <summary>Leeres Ziel → <c>list_config.base_branch</c>, sonst der ausgecheckte Branch des Main-Checkouts.</summary>
|
||||
public async Task<string> ResolveTargetAsync(ListEntity list, string? targetBranch, CancellationToken ct)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(targetBranch)) return targetBranch;
|
||||
using var ctx = _dbFactory.CreateDbContext();
|
||||
var baseBranch = await ctx.ListConfigs.AsNoTracking()
|
||||
.Where(c => c.ListId == list.Id)
|
||||
.Select(c => c.BaseBranch)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
return string.IsNullOrWhiteSpace(baseBranch)
|
||||
? await _git.GetCurrentBranchAsync(list.WorkingDir!, ct)
|
||||
: baseBranch;
|
||||
}
|
||||
|
||||
/// The commit message a merge uses when the caller passes none. Built here rather than in the
|
||||
/// UI/MCP callers because only this layer knows the task's commit type and its list's name.
|
||||
private static string DefaultMergeMessage(TaskEntity task, ListEntity list) =>
|
||||
@@ -907,9 +922,7 @@ public sealed class TaskMergeService
|
||||
if (string.IsNullOrWhiteSpace(list.WorkingDir) || !await _git.IsGitRepoAsync(list.WorkingDir, ct))
|
||||
return new MergePreviewResult(PreviewUnavailable, Array.Empty<string>(), 0);
|
||||
|
||||
var target = string.IsNullOrWhiteSpace(targetBranch)
|
||||
? await _git.GetCurrentBranchAsync(list.WorkingDir, ct)
|
||||
: targetBranch;
|
||||
var target = await ResolveTargetAsync(list, targetBranch, ct);
|
||||
|
||||
// merge-tree (below) is a pure object-level check — it has no idea the working directory
|
||||
// has an untracked file that would block (or, worse, silently be lost by) the real merge.
|
||||
@@ -1013,9 +1026,7 @@ public sealed class TaskMergeService
|
||||
return Blocked(
|
||||
$"worktree was reverted and its branch '{wt.BranchName}' no longer exists — cannot re-approve; discard the task or start a fresh worktree instead.");
|
||||
|
||||
var reviveTarget = string.IsNullOrWhiteSpace(targetBranch)
|
||||
? await _git.GetCurrentBranchAsync(list.WorkingDir, ct)
|
||||
: targetBranch;
|
||||
var reviveTarget = await ResolveTargetAsync(list, targetBranch, ct);
|
||||
|
||||
// A branch that was already merged once (reverted or not) is already an ancestor of
|
||||
// the target tip -- `git merge` on it again is a silent "Already up to date." no-op,
|
||||
@@ -1074,9 +1085,7 @@ public sealed class TaskMergeService
|
||||
if (string.IsNullOrWhiteSpace(list.WorkingDir))
|
||||
return Blocked("list has no working directory");
|
||||
|
||||
var target = string.IsNullOrWhiteSpace(targetBranch)
|
||||
? await _git.GetCurrentBranchAsync(list.WorkingDir, ct)
|
||||
: targetBranch;
|
||||
var target = await ResolveTargetAsync(list, targetBranch, ct);
|
||||
|
||||
// MergeAsync transitions the task WaitingForReview -> Done on a successful merge.
|
||||
// Remove the worktree on approve (matching the unit-merge path) so merged
|
||||
|
||||
@@ -274,6 +274,13 @@ public sealed class WorktreeManager
|
||||
return parentHead;
|
||||
}
|
||||
}
|
||||
return await _git.RevParseHeadAsync(workingDir, ct);
|
||||
using var cfgCtx = _dbFactory.CreateDbContext();
|
||||
var baseBranch = await cfgCtx.ListConfigs.AsNoTracking()
|
||||
.Where(c => c.ListId == task.ListId)
|
||||
.Select(c => c.BaseBranch)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
return string.IsNullOrWhiteSpace(baseBranch)
|
||||
? await _git.RevParseHeadAsync(workingDir, ct)
|
||||
: await _git.RevParseAsync(workingDir, baseBranch, ct);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user