diff --git a/src/Commands/QueryCommitsWithFullMessage.cs b/src/Commands/QueryCommitsWithFullMessage.cs new file mode 100644 index 00000000..36e22b42 --- /dev/null +++ b/src/Commands/QueryCommitsWithFullMessage.cs @@ -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 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 _commits = new List(); + private Models.CommitWithMessage _current = null; + private string _boundary = ""; + } +} diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 38436fe3..f30596ae 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -104,4 +104,10 @@ namespace SourceGit.Models }); } } + + public class CommitWithMessage + { + public Commit Commit { get; set; } = new Commit(); + public string Message { get; set; } = ""; + } } diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index e6a0b69d..613ffc56 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -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(); + var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}...HEAD").Result(); + var list = new List(); 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(); - foreach (var c in commits) - list.Add(new InteractiveRebaseItem(c, messages[c.SHA])); - Items.AddRange(list); IsLoading = false; });