diff --git a/ProjectDirector.Test/CommitTests.cs b/ProjectDirector.Test/CommitTests.cs index 1c17242..3689dc0 100644 --- a/ProjectDirector.Test/CommitTests.cs +++ b/ProjectDirector.Test/CommitTests.cs @@ -223,6 +223,43 @@ public void ARenameWhoseSourceLooksLikeARecordIsStillNotListed() } } + /// + /// A rename can also be reported in the worktree column: a file added with intent-to-add that + /// git matches against a deleted tracked file comes out as R. Its source path still + /// follows as a bare entry and must be consumed, or "ab cd.txt" is listed as "cd.txt". + /// + [TestMethod] + public void AWorktreeRenameReportsOnlyItsDestination() + { + // Arrange + string root = CreateCommittedRepository(); + + try + { + File.WriteAllText(Path.Join(root, "ab cd.txt"), "moved content\n"); + Assert.IsTrue(GitCli.RunIn(root, "add", "--all").Succeeded); + Assert.IsTrue(GitCli.RunIn(root, "commit", "-m", "second").Succeeded); + + File.Delete(Path.Join(root, "ab cd.txt")); + File.WriteAllText(Path.Join(root, "new.txt"), "moved content\n"); + Assert.IsTrue(GitCli.RunIn(root, "add", "-N", "new.txt").Succeeded, "git add -N failed."); + + GitResult status = GitCli.RunIn(root, "status", "--porcelain", "-z"); + Assert.StartsWith(" R new.txt\0", status.Output, "git should report the rename in the worktree column."); + + // Act + Collection changes = GitCli.ListPendingChanges(root); + + // Assert + Assert.HasCount(1, changes); + Assert.AreEqual("new.txt", changes[0]); + } + finally + { + Cleanup(root); + } + } + /// /// A path that is not a repository at all reports nothing rather than throwing, so the button /// degrades to "nothing to commit" instead of taking the application down. diff --git a/ProjectDirector/GitCli.cs b/ProjectDirector/GitCli.cs index 7ea1846..6d2f076 100644 --- a/ProjectDirector/GitCli.cs +++ b/ProjectDirector/GitCli.cs @@ -213,8 +213,10 @@ internal static Collection ListPendingChanges(string repositoryPath) changes.Add(entry[3..]); - // A rename or copy is recorded against the index, in the first status character. - if (entry[0] is 'R' or 'C') + // A rename or copy is usually recorded against the index, in the first status character, + // but one detected in the worktree (an intent-to-add file matched against a deleted + // tracked one) is recorded in the second. Either way the source path follows. + if (entry[0] is 'R' or 'C' || entry[1] is 'R' or 'C') { ++i; }