Skip to content

Commit 85fb1ba

Browse files
CopilotJusterZhu
andauthored
fix: DefaultCleanMatcher.Match incorrectly returns null for same-name files in different directories (#170)
* Initial plan * fix: match by RelativePath in DefaultCleanMatcher to handle same-name files in different dirs Agent-Logs-Url: https://github.com/GeneralLibrary/GeneralUpdate/sessions/6c694de5-ffd1-4c1e-bff3-6dc8faf754fe Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> * style: replace en dashes with hyphens in test comments Agent-Logs-Url: https://github.com/GeneralLibrary/GeneralUpdate/sessions/6c694de5-ffd1-4c1e-bff3-6dc8faf754fe Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> * fix: use null-safe string.Equals and remove redundant RelativePath guard in DefaultCleanMatcher.Match Agent-Logs-Url: https://github.com/GeneralLibrary/GeneralUpdate/sessions/a7ee21b0-87cc-4658-a34b-b23a6338f938 Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com>
1 parent 6c3f513 commit 85fb1ba

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

src/c#/DifferentialTest/Matchers/MatcherTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,36 @@ public void DefaultCleanMatcher_ReturnsNull_WhenNewFileDoesNotExist()
182182
Assert.Null(result);
183183
}
184184

185+
[Fact]
186+
public void DefaultCleanMatcher_ReturnsCorrectNode_WhenSameNameFilesExistInDifferentDirectories()
187+
{
188+
// Arrange - two old files with the same name but different relative paths
189+
var fileInRoot = Path.Combine(_testDirectory, "a.txt");
190+
var subDir = Path.Combine(_testDirectory, "sub");
191+
Directory.CreateDirectory(subDir);
192+
var fileInSub = Path.Combine(subDir, "a.txt");
193+
File.WriteAllText(fileInRoot, "root");
194+
File.WriteAllText(fileInSub, "sub");
195+
196+
// The new file lives in the sub-directory
197+
var newFile = new FileNode { Name = "a.txt", FullName = fileInSub, RelativePath = "sub/a.txt" };
198+
var oldFileRoot = new FileNode { Name = "a.txt", FullName = fileInRoot, RelativePath = "a.txt" };
199+
var oldFileSub = new FileNode { Name = "a.txt", FullName = fileInSub, RelativePath = "sub/a.txt" };
200+
201+
// oldFileRoot appears first in the list - before the fix FirstOrDefault would
202+
// return oldFileRoot, then the RelativePath guard would return null, hiding oldFileSub.
203+
var leftNodes = new List<FileNode> { oldFileRoot, oldFileSub };
204+
205+
var matcher = new DefaultCleanMatcher();
206+
207+
// Act
208+
var result = matcher.Match(newFile, leftNodes);
209+
210+
// Assert - must find oldFileSub, not be tricked by oldFileRoot
211+
Assert.NotNull(result);
212+
Assert.Same(oldFileSub, result);
213+
}
214+
185215
[Fact]
186216
public void DefaultCleanMatcher_ReturnsNull_WhenLeftNodesIsEmpty()
187217
{

src/c#/GeneralUpdate.Differential/Matchers/DefaultCleanMatcher.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ public ComparisonResult Compare(string sourcePath, string targetPath)
3030
/// <inheritdoc/>
3131
public FileNode? Match(FileNode newFile, IEnumerable<FileNode> leftNodes)
3232
{
33-
var oldFile = leftNodes.FirstOrDefault(i => i.Name.Equals(newFile.Name));
33+
var oldFile = leftNodes.FirstOrDefault(i =>
34+
string.Equals(i.Name, newFile.Name) &&
35+
string.Equals(i.RelativePath, newFile.RelativePath));
3436
if (oldFile is null) return null;
3537
if (!File.Exists(oldFile.FullName)) return null;
3638
if (!File.Exists(newFile.FullName)) return null;
37-
if (!string.Equals(oldFile.RelativePath, newFile.RelativePath)) return null;
3839
return oldFile;
3940
}
4041
}

0 commit comments

Comments
 (0)