enhance: reduce commits loading time for interactive rebase

This commit is contained in:
leo 2024-08-01 18:05:58 +08:00
parent 7891b1124e
commit eb437df9fe
No known key found for this signature in database
3 changed files with 101 additions and 13 deletions

View file

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
namespace SourceGit.Commands
{
public class QueryCommitsWithFullMessage : Command
{
public QueryCommitsWithFullMessage(string repo, string args)
{
_boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----";
WorkingDirectory = repo;
Context = repo;
Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}";
}
public List<Models.CommitWithMessage> Result()
{
var rs = ReadToEnd();
if (!rs.IsSuccess)
return _commits;
var nextPartIdx = 0;
var start = 0;
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)
{
var line = rs.StdOut.Substring(start, end - start);
switch (nextPartIdx)
{
case 0:
_current = new Models.CommitWithMessage();
_current.Commit.SHA = line;
_commits.Add(_current);
break;
case 1:
ParseParent(line);
break;
case 2:
_current.Commit.ParseDecorators(line);
break;
case 3:
_current.Commit.Author = Models.User.FindOrAdd(line);
break;
case 4:
_current.Commit.AuthorTime = ulong.Parse(line);
break;
case 5:
_current.Commit.Committer = Models.User.FindOrAdd(line);
break;
case 6:
_current.Commit.CommitterTime = ulong.Parse(line);
break;
default:
if (line.Equals(_boundary, StringComparison.Ordinal))
nextPartIdx = -1;
else
_current.Message += line;
break;
}
nextPartIdx++;
start = end + 1;
end = rs.StdOut.IndexOf('\n', start);
}
return _commits;
}
private void ParseParent(string data)
{
if (data.Length < 8)
return;
var idx = data.IndexOf(' ', StringComparison.Ordinal);
if (idx == -1)
{
_current.Commit.Parents.Add(data);
return;
}
_current.Commit.Parents.Add(data.Substring(0, idx));
_current.Commit.Parents.Add(data.Substring(idx + 1));
}
private List<Models.CommitWithMessage> _commits = new List<Models.CommitWithMessage>();
private Models.CommitWithMessage _current = null;
private string _boundary = "";
}
}

View file

@ -104,4 +104,10 @@ namespace SourceGit.Models
});
}
}
public class CommitWithMessage
{
public Commit Commit { get; set; } = new Commit();
public string Message { get; set; } = "";
}
}

View file

@ -51,9 +51,7 @@ namespace SourceGit.ViewModels
public InteractiveRebaseItem(Models.Commit c, string message)
{
Commit = c;
_subject = c.Subject;
_fullMessage = message;
FullMessage = message;
}
public void SetAction(object param)
@ -120,21 +118,14 @@ namespace SourceGit.ViewModels
Task.Run(() =>
{
var commits = new Commands.QueryCommits(repoPath, $"{on.SHA}...HEAD", false).Result();
var messages = new Dictionary<string, string>();
var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}...HEAD").Result();
var list = new List<InteractiveRebaseItem>();
foreach (var c in commits)
{
var fullMessage = new Commands.QueryCommitFullMessage(repoPath, c.SHA).Result();
messages.Add(c.SHA, fullMessage);
}
list.Add(new InteractiveRebaseItem(c.Commit, c.Message));
Dispatcher.UIThread.Invoke(() =>
{
var list = new List<InteractiveRebaseItem>();
foreach (var c in commits)
list.Add(new InteractiveRebaseItem(c, messages[c.SHA]));
Items.AddRange(list);
IsLoading = false;
});