Files
ClaudeDo/tests/ClaudeDo.Worker.Tests/Lifecycle/LegacyWorktreeFolderRecoveryTests.cs
T
mika kuns 5d362b6973 fix(worker): stop sibling worktrees from landing inside the repo tree
Path.GetDirectoryName returned workingDir itself instead of its parent
whenever list.WorkingDir ended in a directory separator, placing
.claudedo-worktrees inside the target repo's own working tree. Add
WorktreeRootResolver to normalize the trailing separator before deriving
the sibling root and to guard that the resulting worktree path never
lands inside workingDir, used by both WorktreeManager and
PlanningSessionManager. Add a startup sweep (LegacyWorktreeFolderRecovery)
that warns when a list's working dir already contains a leftover
.claudedo-worktrees folder from before the fix.
2026-08-10 11:58:34 +02:00

72 lines
2.2 KiB
C#

using ClaudeDo.Data.Models;
using ClaudeDo.Worker.Lifecycle;
using ClaudeDo.Worker.Tests.Infrastructure;
using Microsoft.Extensions.Logging.Abstractions;
namespace ClaudeDo.Worker.Tests.Lifecycle;
public sealed class LegacyWorktreeFolderRecoveryTests : IDisposable
{
private readonly DbFixture _db = new();
private readonly List<string> _tempDirs = new();
public void Dispose()
{
_db.Dispose();
foreach (var d in _tempDirs)
{
try { Directory.Delete(d, recursive: true); } catch { }
}
}
private string MakeWorkingDir()
{
var dir = Path.Combine(Path.GetTempPath(), $"claudedo_legacy_wt_{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
_tempDirs.Add(dir);
return dir;
}
[Fact]
public void FindAffectedListNames_FolderInsideWorkingDir_ReturnsListName()
{
var wd = MakeWorkingDir();
Directory.CreateDirectory(Path.Combine(wd, ".claudedo-worktrees"));
var list = new ListEntity { Id = "1", Name = "Bandel.Hub", WorkingDir = wd, CreatedAt = DateTime.UtcNow };
var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list });
Assert.Equal(new[] { "Bandel.Hub" }, affected);
}
[Fact]
public void FindAffectedListNames_NoLegacyFolder_ReturnsEmpty()
{
var wd = MakeWorkingDir();
var list = new ListEntity { Id = "1", Name = "Clean", WorkingDir = wd, CreatedAt = DateTime.UtcNow };
var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list });
Assert.Empty(affected);
}
[Fact]
public void FindAffectedListNames_NullWorkingDir_IsSkipped()
{
var list = new ListEntity { Id = "1", Name = "NoRepo", WorkingDir = null, CreatedAt = DateTime.UtcNow };
var affected = LegacyWorktreeFolderRecovery.FindAffectedListNames(new[] { list });
Assert.Empty(affected);
}
[Fact]
public async Task StartAsync_NoLists_DoesNotThrow()
{
var sut = new LegacyWorktreeFolderRecovery(_db.CreateFactory(), NullLogger<LegacyWorktreeFolderRecovery>.Instance);
await sut.StartAsync(CancellationToken.None);
await sut.StopAsync(CancellationToken.None);
}
}