refactor: rewrite git restore integration

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-06-02 12:14:22 +08:00
parent 80df53cf04
commit 78f9ae2fa9
No known key found for this signature in database
5 changed files with 71 additions and 18 deletions

View file

@ -36,7 +36,7 @@ namespace SourceGit.Commands
}); });
} }
new Restore(repo, false) { Log = log }.Exec(); new Restore(repo) { Log = log }.Exec();
if (includeIgnored) if (includeIgnored)
new Clean(repo) { Log = log }.Exec(); new Clean(repo) { Log = log }.Exec();
} }
@ -71,10 +71,20 @@ namespace SourceGit.Commands
}); });
} }
for (int i = 0; i < restores.Count; i += 10) if (Native.OS.GitVersion >= Models.GitVersions.RESTORE_WITH_PATHSPECFILE)
{ {
var count = Math.Min(10, restores.Count - i); var tmpFile = Path.GetTempFileName();
new Restore(repo, restores.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec(); File.WriteAllLines(tmpFile, restores);
new Restore(repo, tmpFile, "--worktree --recurse-submodules") { Log = log }.Exec();
File.Delete(tmpFile);
}
else
{
for (int i = 0; i < restores.Count; i += 32)
{
var count = Math.Min(32, restores.Count - i);
new Restore(repo, restores.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
}
} }
} }
} }

View file

@ -5,17 +5,23 @@ namespace SourceGit.Commands
{ {
public class Restore : Command public class Restore : Command
{ {
public Restore(string repo, bool onlyStaged) /// <summary>
/// Only used to discard all changes in the working directory and staged area.
/// </summary>
/// <param name="repo"></param>
public Restore(string repo)
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "restore --source=HEAD --staged --worktree --recurse-submodules .";
if (onlyStaged)
Args = "restore --source=HEAD --staged .";
else
Args = "restore --source=HEAD --staged --worktree --recurse-submodules .";
} }
/// <summary>
/// Discard changes with git (&lt; 2.25.0) that does not support the `--pathspec-from-file` option.
/// </summary>
/// <param name="repo"></param>
/// <param name="files"></param>
/// <param name="extra"></param>
public Restore(string repo, List<string> files, string extra) public Restore(string repo, List<string> files, string extra)
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
@ -30,5 +36,24 @@ namespace SourceGit.Commands
builder.Append(' ').Append('"').Append(f).Append('"'); builder.Append(' ').Append('"').Append(f).Append('"');
Args = builder.ToString(); Args = builder.ToString();
} }
/// <summary>
/// Discard changes with git (&gt;= 2.25.0) that supports the `--pathspec-from-file` option.
/// </summary>
/// <param name="repo"></param>
/// <param name="pathspecFile"></param>
/// <param name="extra"></param>
public Restore(string repo, string pathspecFile, string extra)
{
WorkingDirectory = repo;
Context = repo;
var builder = new StringBuilder();
builder.Append("restore ");
if (!string.IsNullOrEmpty(extra))
builder.Append(extra).Append(" ");
builder.Append("--pathspec-from-file=\"").Append(pathspecFile).Append('"');
Args = builder.ToString();
}
} }
} }

View file

@ -12,6 +12,11 @@
/// </summary> /// </summary>
public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0); public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0);
/// <summary>
/// The minimal version of Git that supports the `restore` command with the `--pathspec-from-file` option.
/// </summary>
public static readonly System.Version RESTORE_WITH_PATHSPECFILE = new System.Version(2, 25, 0);
/// <summary> /// <summary>
/// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option. /// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option.
/// </summary> /// </summary>

View file

@ -124,9 +124,9 @@ namespace SourceGit.ViewModels
} }
else else
{ {
for (int i = 0; i < changes.Count; i += 10) for (int i = 0; i < changes.Count; i += 32)
{ {
var count = Math.Min(10, changes.Count - i); var count = Math.Min(32, changes.Count - i);
var step = changes.GetRange(i, count); var step = changes.GetRange(i, count);
succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, step, KeepIndex); succ = new Commands.Stash(_repo.FullPath).Use(log).Push(Message, step, KeepIndex);
if (!succ) if (!succ)

View file

@ -1634,13 +1634,14 @@ namespace SourceGit.ViewModels
foreach (var c in changes) foreach (var c in changes)
paths.Add(c.Path); paths.Add(c.Path);
for (int i = 0; i < count; i += 10) for (int i = 0; i < count; i += 32)
{ {
var step = paths.GetRange(i, Math.Min(10, count - i)); var step = paths.GetRange(i, Math.Min(32, count - i));
await Task.Run(() => new Commands.Add(_repo.FullPath, step).Use(log).Exec()); await Task.Run(() => new Commands.Add(_repo.FullPath, step).Use(log).Exec());
} }
} }
log.Complete(); log.Complete();
_repo.MarkWorkingCopyDirtyManually(); _repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
IsStaging = false; IsStaging = false;
@ -1664,15 +1665,26 @@ namespace SourceGit.ViewModels
log.AppendLine("$ git update-index --index-info "); log.AppendLine("$ git update-index --index-info ");
await Task.Run(() => new Commands.UnstageChangesForAmend(_repo.FullPath, changes).Exec()); await Task.Run(() => new Commands.UnstageChangesForAmend(_repo.FullPath, changes).Exec());
} }
else if (count == _staged.Count) else if (Native.OS.GitVersion >= Models.GitVersions.RESTORE_WITH_PATHSPECFILE)
{ {
await Task.Run(() => new Commands.Restore(_repo.FullPath, true).Use(log).Exec()); var paths = new List<string>();
foreach (var c in changes)
{
paths.Add(c.Path);
if (c.Index == Models.ChangeState.Renamed)
paths.Add(c.OriginalPath);
}
var tmpFile = Path.GetTempFileName();
File.WriteAllLines(tmpFile, paths);
await Task.Run(() => new Commands.Restore(_repo.FullPath, tmpFile, "--staged").Use(log).Exec());
File.Delete(tmpFile);
} }
else else
{ {
for (int i = 0; i < count; i += 10) for (int i = 0; i < count; i += 32)
{ {
var step = changes.GetRange(i, Math.Min(10, count - i)); var step = changes.GetRange(i, Math.Min(32, count - i));
var files = new List<string>(); var files = new List<string>();
foreach (var c in step) foreach (var c in step)
{ {
@ -1685,6 +1697,7 @@ namespace SourceGit.ViewModels
} }
} }
log.Complete(); log.Complete();
_repo.MarkWorkingCopyDirtyManually(); _repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
IsUnstaging = false; IsUnstaging = false;