fix: directly patch the final file when trying to stage/unstage/discard selected hunk with renamed/copied file (#2272)

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2026-04-16 12:23:15 +08:00
parent 8bdba69cb4
commit 5a35c41517
2 changed files with 21 additions and 25 deletions

View File

@@ -99,19 +99,19 @@ namespace SourceGit.Models
return rs;
}
public void GenerateNewPatchFromSelection(Change change, string fileBlobGuid, TextDiffSelection selection, bool revert, string output)
public void GenerateNewPatchFromSelection(string file, string fileBlobGuid, TextDiffSelection selection, bool revert, string output)
{
var isTracked = !string.IsNullOrEmpty(fileBlobGuid);
var fileGuid = isTracked ? fileBlobGuid : "00000000";
using var writer = new StreamWriter(output);
writer.NewLine = "\n";
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
writer.WriteLine($"diff --git a/{file} b/{file}");
if (!revert && !isTracked)
writer.WriteLine("new file mode 100644");
writer.WriteLine($"index 00000000...{fileGuid}");
writer.WriteLine($"--- {(revert || isTracked ? $"a/{change.Path}" : "/dev/null")}");
writer.WriteLine($"+++ b/{change.Path}");
writer.WriteLine($"--- {(revert || isTracked ? $"a/{file}" : "/dev/null")}");
writer.WriteLine($"+++ b/{file}");
var additions = selection.EndLine - selection.StartLine;
if (selection.StartLine != 1)
@@ -148,16 +148,14 @@ namespace SourceGit.Models
writer.Flush();
}
public void GeneratePatchFromSelection(Change change, string fileTreeGuid, TextDiffSelection selection, bool revert, string output)
public void GeneratePatchFromSelection(string file, string fileTreeGuid, TextDiffSelection selection, bool revert, string output)
{
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
using var writer = new StreamWriter(output);
writer.NewLine = "\n";
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
writer.WriteLine($"diff --git a/{file} b/{file}");
writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
writer.WriteLine($"--- a/{orgFile}");
writer.WriteLine($"+++ b/{change.Path}");
writer.WriteLine($"--- a/{file}");
writer.WriteLine($"+++ b/{file}");
// If last line of selection is a change. Find one more line.
TextDiffLine tail = null;
@@ -263,16 +261,14 @@ namespace SourceGit.Models
writer.Flush();
}
public void GeneratePatchFromSelectionSingleSide(Change change, string fileTreeGuid, TextDiffSelection selection, bool revert, bool isOldSide, string output)
public void GeneratePatchFromSelectionSingleSide(string file, string fileTreeGuid, TextDiffSelection selection, bool revert, bool isOldSide, string output)
{
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
using var writer = new StreamWriter(output);
writer.NewLine = "\n";
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
writer.WriteLine($"diff --git a/{file} b/{file}");
writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
writer.WriteLine($"--- a/{orgFile}");
writer.WriteLine($"+++ b/{change.Path}");
writer.WriteLine($"--- a/{file}");
writer.WriteLine($"+++ b/{file}");
// If last line of selection is a change. Find one more line.
TextDiffLine tail = null;

View File

@@ -1495,17 +1495,17 @@ namespace SourceGit.Views
var tmpFile = Path.GetTempFileName();
if (change.WorkTree == Models.ChangeState.Untracked)
{
diff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile);
diff.GenerateNewPatchFromSelection(change.Path, null, selection, false, tmpFile);
}
else if (chunk.Combined)
{
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
diff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
diff.GeneratePatchFromSelection(change.Path, treeGuid, selection, false, tmpFile);
}
else
{
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, chunk.IsOldSide, tmpFile);
diff.GeneratePatchFromSelectionSingleSide(change.Path, treeGuid, selection, false, chunk.IsOldSide, tmpFile);
}
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--cache --index").ExecAsync();
@@ -1533,11 +1533,11 @@ namespace SourceGit.Views
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);
diff.GenerateNewPatchFromSelection(change.Path, treeGuid, selection, true, tmpFile);
else if (chunk.Combined)
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
diff.GeneratePatchFromSelection(change.Path, treeGuid, selection, true, tmpFile);
else
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
diff.GeneratePatchFromSelectionSingleSide(change.Path, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--cache --index --reverse").ExecAsync();
File.Delete(tmpFile);
@@ -1564,17 +1564,17 @@ namespace SourceGit.Views
var tmpFile = Path.GetTempFileName();
if (change.WorkTree == Models.ChangeState.Untracked)
{
diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
diff.GenerateNewPatchFromSelection(change.Path, null, selection, true, tmpFile);
}
else if (chunk.Combined)
{
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
diff.GeneratePatchFromSelection(change.Path, 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);
diff.GeneratePatchFromSelectionSingleSide(change.Path, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
}
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--reverse").ExecAsync();