diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs index 6c381df35..d00359888 100644 --- a/src/Models/DiffResult.cs +++ b/src/Models/DiffResult.cs @@ -95,53 +95,45 @@ public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombin return rs; } - public void GenerateNewPatchFromSelection(Change change, string fileBlobGuid, TextDiffSelection selection, bool revert, string output) + public void GenerateNewPatchFromSelection(Change change, string fileBlobGuid, TextDiffSelection selection, string output) { var isTracked = !string.IsNullOrEmpty(fileBlobGuid); var fileGuid = isTracked ? fileBlobGuid : "00000000"; + // Collect selected added lines first to check if there's anything to write + var selectedAddedLines = new List(); + for (int i = 0; i < Lines.Count; i++) + { + var line = Lines[i]; + if (line.Type != TextDiffLineType.Added) + continue; + + var lineIndex = i + 1; // 1-based line number + if (lineIndex >= selection.StartLine && lineIndex <= selection.EndLine) + selectedAddedLines.Add(line); + } + + if (selectedAddedLines.Count == 0) + return; + using var writer = new StreamWriter(output); writer.NewLine = "\n"; writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}"); - if (!revert && !isTracked) + if (!isTracked) writer.WriteLine("new file mode 100644"); - writer.WriteLine($"index 00000000...{fileGuid}"); - writer.WriteLine($"--- {(revert || isTracked ? $"a/{change.Path}" : "/dev/null")}"); + writer.WriteLine($"index 0000000..{fileGuid}"); + writer.WriteLine($"--- {(isTracked ? $"a/{change.Path}" : "/dev/null")}"); writer.WriteLine($"+++ b/{change.Path}"); - var additions = selection.EndLine - selection.StartLine; - if (selection.StartLine != 1) - additions++; - - if (revert) + writer.WriteLine($"@@ -0,0 +1,{selectedAddedLines.Count} @@"); + foreach (var line in selectedAddedLines) { - var totalLines = Lines.Count - 1; - writer.WriteLine($"@@ -0,{totalLines - additions} +0,{totalLines} @@"); - for (int i = 1; i <= totalLines; i++) - { - var line = Lines[i]; - if (line.Type != TextDiffLineType.Added) - continue; - - if (i >= selection.StartLine - 1 && i < selection.EndLine) - writer.WriteLine($"+{line.Content}"); - else - writer.WriteLine($" {line.Content}"); - } - } - else - { - writer.WriteLine($"@@ -0,0 +0,{additions} @@"); - for (int i = selection.StartLine - 1; i < selection.EndLine; i++) - { - var line = Lines[i]; - if (line.Type != TextDiffLineType.Added) - continue; - writer.WriteLine($"+{line.Content}"); - } + writer.WriteLine($"+{line.Content}"); } - writer.WriteLine("\\ No newline at end of file"); + if (selectedAddedLines[^1].NoNewLineEndOfFile) + writer.WriteLine("\\ No newline at end of file"); + writer.Flush(); } @@ -152,7 +144,7 @@ public void GeneratePatchFromSelection(Change change, string fileTreeGuid, TextD using var writer = new StreamWriter(output); writer.NewLine = "\n"; writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}"); - writer.WriteLine($"index 00000000...{fileTreeGuid} 100644"); + writer.WriteLine($"index 0000000..{fileTreeGuid} 100644"); writer.WriteLine($"--- a/{orgFile}"); writer.WriteLine($"+++ b/{change.Path}"); @@ -255,7 +247,9 @@ public void GeneratePatchFromSelection(Change change, string fileTreeGuid, TextD } } - writer.WriteLine($" {tail}"); + if (tail != null) + writer.WriteLine($" {tail}"); + writer.Flush(); } @@ -266,7 +260,7 @@ public void GeneratePatchFromSelectionSingleSide(Change change, string fileTreeG using var writer = new StreamWriter(output); writer.NewLine = "\n"; writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}"); - writer.WriteLine($"index 00000000...{fileTreeGuid} 100644"); + writer.WriteLine($"index 0000000..{fileTreeGuid} 100644"); writer.WriteLine($"--- a/{orgFile}"); writer.WriteLine($"+++ b/{change.Path}"); @@ -406,7 +400,9 @@ public void GeneratePatchFromSelectionSingleSide(Change change, string fileTreeG } } - writer.WriteLine($" {tail}"); + if (tail != null) + writer.WriteLine($" {tail}"); + writer.Flush(); } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 516b6e8e9..a6b3e140f 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -1495,7 +1495,7 @@ private async void OnStageChunk(object _1, RoutedEventArgs _2) var tmpFile = Path.GetTempFileName(); if (change.WorkTree == Models.ChangeState.Untracked) { - diff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile); + diff.GenerateNewPatchFromSelection(change, null, selection, tmpFile); } else if (chunk.Combined) { @@ -1532,9 +1532,7 @@ private async void OnUnstageChunk(object _1, RoutedEventArgs _2) var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync(); var tmpFile = Path.GetTempFileName(); - if (change.Index == Models.ChangeState.Added) - diff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile); - else if (chunk.Combined) + if (chunk.Combined) diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile); else diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile); @@ -1562,20 +1560,12 @@ private async void OnDiscardChunk(object _1, RoutedEventArgs _2) using var lockWatcher = repo.LockWatcher(); var tmpFile = Path.GetTempFileName(); - if (change.Index == Models.ChangeState.Added) - { - diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile); - } - else if (chunk.Combined) - { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync(); + + if (chunk.Combined) diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile); - } else - { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync(); diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile); - } await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--reverse").ExecAsync(); File.Delete(tmpFile);