From baf85af7c0a1d2b3d9a99a56f3f5db95f7cc99aa Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 10 Mar 2026 17:11:24 +0800 Subject: [PATCH] fix: parsing copied change (#2174) Signed-off-by: leo --- src/Commands/CompareRevisions.cs | 13 +++++-------- src/Commands/QueryFileHistory.cs | 14 ++++++-------- src/Commands/QueryStagedChangesWithAmend.cs | 12 +++++------- src/Models/Change.cs | 2 +- src/Models/DiffOption.cs | 18 ++++++++++++++---- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs index a4ed972d..2e1062cf 100644 --- a/src/Commands/CompareRevisions.cs +++ b/src/Commands/CompareRevisions.cs @@ -7,9 +7,9 @@ namespace SourceGit.Commands { public partial class CompareRevisions : Command { - [GeneratedRegex(@"^([MADC])\s+(.+)$")] + [GeneratedRegex(@"^([MAD])\s+(.+)$")] private static partial Regex REG_FORMAT(); - [GeneratedRegex(@"^R[0-9]{0,4}\s+(.+)$")] + [GeneratedRegex(@"^([CR])[0-9]{0,4}\s+(.+)$")] private static partial Regex REG_RENAME_FORMAT(); public CompareRevisions(string repo, string start, string end) @@ -47,8 +47,9 @@ namespace SourceGit.Commands match = REG_RENAME_FORMAT().Match(line); if (match.Success) { - var renamed = new Models.Change() { Path = match.Groups[1].Value }; - renamed.Set(Models.ChangeState.Renamed); + var type = match.Groups[1].Value; + var renamed = new Models.Change() { Path = match.Groups[2].Value }; + renamed.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied); changes.Add(renamed); } @@ -72,10 +73,6 @@ namespace SourceGit.Commands change.Set(Models.ChangeState.Deleted); changes.Add(change); break; - case 'C': - change.Set(Models.ChangeState.Copied); - changes.Add(change); - break; } } diff --git a/src/Commands/QueryFileHistory.cs b/src/Commands/QueryFileHistory.cs index 3c2b4a66..d112377a 100644 --- a/src/Commands/QueryFileHistory.cs +++ b/src/Commands/QueryFileHistory.cs @@ -8,9 +8,9 @@ namespace SourceGit.Commands { public partial class QueryFileHistory : Command { - [GeneratedRegex(@"^([MADC])\s+(.+)$")] + [GeneratedRegex(@"^([MAD])\s+(.+)$")] private static partial Regex REG_FORMAT(); - [GeneratedRegex(@"^R[0-9]{0,4}\s+(.+)$")] + [GeneratedRegex(@"^([CR])[0-9]{0,4}\s+(.+)$")] private static partial Regex REG_RENAME_FORMAT(); public QueryFileHistory(string repo, string path, string head) @@ -20,7 +20,7 @@ namespace SourceGit.Commands RaiseError = false; var builder = new StringBuilder(); - builder.Append("log --follow --no-show-signature --date-order -n 10000 --decorate=no --format=\"@%H%x00%P%x00%aN±%aE%x00%at%x00%s\" --name-status "); + builder.Append("log --no-show-signature --date-order -n 10000 --decorate=no --format=\"@%H%x00%P%x00%aN±%aE%x00%at%x00%s\" --follow --name-status "); if (!string.IsNullOrEmpty(head)) builder.Append(head).Append(" "); builder.Append("-- ").Append(path.Quoted()); @@ -64,8 +64,9 @@ namespace SourceGit.Commands match = REG_RENAME_FORMAT().Match(line); if (match.Success) { - last.Change.Path = match.Groups[1].Value; - last.Change.Set(Models.ChangeState.Renamed); + var type = match.Groups[1].Value; + last.Change.Path = match.Groups[2].Value; + last.Change.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied); } continue; @@ -85,9 +86,6 @@ namespace SourceGit.Commands case 'D': last.Change.Set(Models.ChangeState.Deleted); break; - case 'C': - last.Change.Set(Models.ChangeState.Copied); - break; } } } diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs index 229d9e65..cff939e2 100644 --- a/src/Commands/QueryStagedChangesWithAmend.cs +++ b/src/Commands/QueryStagedChangesWithAmend.cs @@ -6,9 +6,9 @@ namespace SourceGit.Commands { public partial class QueryStagedChangesWithAmend : Command { - [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMT])\d{0,6}\t(.*)$")] + [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ADMT])\d{0,6}\t(.*)$")] private static partial Regex REG_FORMAT1(); - [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")] + [GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([RC])\d{0,6}\t(.*\t.*)$")] private static partial Regex REG_FORMAT2(); public QueryStagedChangesWithAmend(string repo, string parent) @@ -34,7 +34,7 @@ namespace SourceGit.Commands { var change = new Models.Change() { - Path = match.Groups[3].Value, + Path = match.Groups[4].Value, DataForAmend = new Models.ChangeDataForAmend() { FileMode = match.Groups[1].Value, @@ -42,7 +42,8 @@ namespace SourceGit.Commands ParentSHA = _parent, }, }; - change.Set(Models.ChangeState.Renamed); + var type = match.Groups[3].Value; + change.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied); changes.Add(change); continue; } @@ -67,9 +68,6 @@ namespace SourceGit.Commands case "A": change.Set(Models.ChangeState.Added); break; - case "C": - change.Set(Models.ChangeState.Copied); - break; case "D": change.Set(Models.ChangeState.Deleted); break; diff --git a/src/Models/Change.cs b/src/Models/Change.cs index 2ad448ad..baf6e850 100644 --- a/src/Models/Change.cs +++ b/src/Models/Change.cs @@ -60,7 +60,7 @@ Index = index; WorkTree = workTree; - if (index == ChangeState.Renamed || workTree == ChangeState.Renamed) + if (index == ChangeState.Renamed || index == ChangeState.Copied || workTree == ChangeState.Renamed) { var parts = Path.Split('\t', 2); if (parts.Length < 2) diff --git a/src/Models/DiffOption.cs b/src/Models/DiffOption.cs index 6a9f400a..088ab7b1 100644 --- a/src/Models/DiffOption.cs +++ b/src/Models/DiffOption.cs @@ -86,10 +86,20 @@ namespace SourceGit.Models /// public DiffOption(FileVersion ver) { - _revisions.Add(ver.HasParent ? $"{ver.SHA}^" : Commit.EmptyTreeSHA1); - _revisions.Add(ver.SHA); - _path = ver.Path; - _orgPath = ver.Change.OriginalPath; + if (string.IsNullOrEmpty(ver.Change.OriginalPath)) + { + _revisions.Add(ver.HasParent ? $"{ver.SHA}^" : Commit.EmptyTreeSHA1); + _revisions.Add(ver.SHA); + _path = ver.Path; + } + else + { + _revisions.Add($"{ver.SHA}^:{ver.Change.OriginalPath.Quoted()}"); + _revisions.Add($"{ver.SHA}:{ver.Path.Quoted()}"); + _path = ver.Path; + _orgPath = ver.Change.OriginalPath; + _ignorePaths = true; + } } ///