diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index e60331ee..17e8b09b 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace SourceGit.Commands { @@ -18,7 +17,61 @@ namespace SourceGit.Commands public List Result() { - Exec(); + var rs = ReadToEnd(); + if (!rs.IsSuccess) + return _commits; + + var nextPartIdx = 0; + var start = 0; + var end = rs.StdOut.IndexOf('\n', start); + var max = rs.StdOut.Length; + while (end > 0) + { + var line = rs.StdOut.Substring(start, end - start); + switch (nextPartIdx) + { + case 0: + _current = new Models.Commit() { SHA = line }; + _commits.Add(_current); + break; + case 1: + ParseParent(line); + break; + case 2: + ParseDecorators(line); + break; + case 3: + _current.Author = Models.User.FindOrAdd(line); + break; + case 4: + _current.AuthorTime = ulong.Parse(line); + break; + case 5: + _current.Committer = Models.User.FindOrAdd(line); + break; + case 6: + _current.CommitterTime = ulong.Parse(line); + start = end + 1; + end = rs.StdOut.IndexOf(_endOfBodyToken, start, StringComparison.Ordinal); + if (end > 0) + { + if (end > start) + _current.Body = rs.StdOut.Substring(start, end - start).TrimEnd(); + + start = end + _endOfBodyToken.Length + 1; + end = start >= max ? -1 : rs.StdOut.IndexOf('\n', start); + } + + nextPartIdx = 0; + continue; + default: + break; + } + + nextPartIdx++; + start = end + 1; + end = rs.StdOut.IndexOf('\n', start); + } if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0) MarkFirstMerged(); @@ -26,56 +79,6 @@ namespace SourceGit.Commands return _commits; } - protected override void OnReadline(string line) - { - switch (_nextPartIdx) - { - case 0: - _current = new Models.Commit() { SHA = line }; - _isSubjectSet = false; - _commits.Add(_current); - break; - case 1: - ParseParent(line); - break; - case 2: - ParseDecorators(line); - break; - case 3: - _current.Author = Models.User.FindOrAdd(line); - break; - case 4: - _current.AuthorTime = ulong.Parse(line); - break; - case 5: - _current.Committer = Models.User.FindOrAdd(line); - break; - case 6: - _current.CommitterTime = ulong.Parse(line); - break; - default: - if (line.Equals(_endOfBodyToken, StringComparison.Ordinal)) - { - _nextPartIdx = 0; - _current.Body = _bodyReader.ToString().TrimEnd(); - _bodyReader.Clear(); - } - else - { - if (!_isSubjectSet) - { - _isSubjectSet = true; - _current.SubjectLen = line.Length; - } - - _bodyReader.AppendLine(line); - } - return; - } - - _nextPartIdx++; - } - private void ParseParent(string data) { if (data.Length < 8) @@ -106,7 +109,7 @@ namespace SourceGit.Commands _current.Decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.Tag, - Name = d.Substring(15).Trim(), + Name = d.Substring(15), }); } else if (d.EndsWith("/HEAD", StringComparison.Ordinal)) @@ -119,7 +122,7 @@ namespace SourceGit.Commands _current.Decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.CurrentBranchHead, - Name = d.Substring(19).Trim(), + Name = d.Substring(19), }); } else if (d.Equals("HEAD")) @@ -128,7 +131,7 @@ namespace SourceGit.Commands _current.Decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.CurrentCommitHead, - Name = d.Trim(), + Name = d, }); } else if (d.StartsWith("refs/heads/", StringComparison.Ordinal)) @@ -136,7 +139,7 @@ namespace SourceGit.Commands _current.Decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.LocalBranchHead, - Name = d.Substring(11).Trim(), + Name = d.Substring(11), }); } else if (d.StartsWith("refs/remotes/", StringComparison.Ordinal)) @@ -144,7 +147,7 @@ namespace SourceGit.Commands _current.Decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.RemoteBranchHead, - Name = d.Substring(13).Trim(), + Name = d.Substring(13), }); } } @@ -152,13 +155,9 @@ namespace SourceGit.Commands _current.Decorators.Sort((l, r) => { if (l.Type != r.Type) - { return (int)l.Type - (int)r.Type; - } else - { return l.Name.CompareTo(r.Name); - } }); if (_current.IsMerged && !_isHeadFounded) @@ -191,10 +190,7 @@ namespace SourceGit.Commands private string _endOfBodyToken = string.Empty; private List _commits = new List(); private Models.Commit _current = null; + private bool _findFirstMerged = false; private bool _isHeadFounded = false; - private bool _findFirstMerged = true; - private int _nextPartIdx = 0; - private bool _isSubjectSet = false; - private StringBuilder _bodyReader = new StringBuilder(); } } diff --git a/src/Commands/QuerySingleCommit.cs b/src/Commands/QuerySingleCommit.cs index a5209908..8d2087ab 100644 --- a/src/Commands/QuerySingleCommit.cs +++ b/src/Commands/QuerySingleCommit.cs @@ -32,7 +32,6 @@ namespace SourceGit.Commands commit.AuthorTime = ulong.Parse(lines[4]); commit.Committer = Models.User.FindOrAdd(lines[5]); commit.CommitterTime = ulong.Parse(lines[6]); - commit.SubjectLen = lines[7].Length; StringBuilder builder = new StringBuilder(); for (int i = 7; i < lines.Length; i++) @@ -58,7 +57,7 @@ namespace SourceGit.Commands decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.Tag, - Name = d.Substring(15).Trim(), + Name = d.Substring(15), }); } else if (d.EndsWith("/HEAD", StringComparison.Ordinal)) @@ -71,7 +70,7 @@ namespace SourceGit.Commands decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.CurrentBranchHead, - Name = d.Substring(19).Trim(), + Name = d.Substring(19), }); } else if (d.Equals("HEAD")) @@ -80,7 +79,7 @@ namespace SourceGit.Commands decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.CurrentCommitHead, - Name = d.Trim(), + Name = d, }); } else if (d.StartsWith("refs/heads/", StringComparison.Ordinal)) @@ -88,7 +87,7 @@ namespace SourceGit.Commands decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.LocalBranchHead, - Name = d.Substring(11).Trim(), + Name = d.Substring(11), }); } else if (d.StartsWith("refs/remotes/", StringComparison.Ordinal)) @@ -96,7 +95,7 @@ namespace SourceGit.Commands decorators.Add(new Models.Decorator() { Type = Models.DecoratorType.RemoteBranchHead, - Name = d.Substring(13).Trim(), + Name = d.Substring(13), }); } } @@ -104,13 +103,9 @@ namespace SourceGit.Commands decorators.Sort((l, r) => { if (l.Type != r.Type) - { return (int)l.Type - (int)r.Type; - } else - { return l.Name.CompareTo(r.Name); - } }); return isHeadOfCurrent; diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 81c48b79..6cf764a5 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -12,7 +12,6 @@ namespace SourceGit.Models public ulong AuthorTime { get; set; } = 0; public User Committer { get; set; } = User.Invalid; public ulong CommitterTime { get; set; } = 0; - public int SubjectLen { get; set; } = 0; public string Body { get; set; } = string.Empty; public List Parents { get; set; } = new List(); public List Decorators { get; set; } = new List(); @@ -20,7 +19,24 @@ namespace SourceGit.Models public bool IsMerged { get; set; } = false; public Thickness Margin { get; set; } = new Thickness(0); - public string Subject => string.IsNullOrWhiteSpace(Body) ? string.Empty : Body.Substring(0, SubjectLen); + public string Subject + { + get + { + var end = Body.IndexOf("\r\n\r\n", StringComparison.Ordinal); + if (end == -1) + { + end = Body.IndexOf("\n\n", StringComparison.Ordinal); + if (end > 0) + return Body.Substring(0, end).Replace("\n", "", StringComparison.Ordinal); + + return Body.Replace("\n", " ", StringComparison.Ordinal); + } + + return Body.Substring(0, end).Replace("\r\n", " ", StringComparison.Ordinal); + } + } + public string AuthorTimeStr => _utcStart.AddSeconds(AuthorTime).ToString("yyyy/MM/dd HH:mm:ss"); public string CommitterTimeStr => _utcStart.AddSeconds(CommitterTime).ToString("yyyy/MM/dd HH:mm:ss"); public string AuthorTimeShortStr => _utcStart.AddSeconds(AuthorTime).ToString("yyyy/MM/dd"); diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 2a01f3c8..5256da49 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -62,7 +62,7 @@ namespace SourceGit.ViewModels Task.Run(() => { - var commits = new Commands.QueryCommits(_repo, $"-n 10000 -- \"{file}\"").Result(); + var commits = new Commands.QueryCommits(_repo, $"-n 10000 -- \"{file}\"", false).Result(); Dispatcher.UIThread.Invoke(() => { IsLoading = false; diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 9decf79c..ffd82bb1 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -84,17 +84,25 @@ namespace SourceGit.ViewModels { if (SetProperty(ref _useAmend, value) && value) { - var commits = new Commands.QueryCommits(_repo.FullPath, "-n 1", false).Result(); - if (commits.Count == 0) + var currentBranch = _repo.Branches.Find(x => x.IsCurrent); + if (currentBranch == null) { App.RaiseException(_repo.FullPath, "No commits to amend!!!"); _useAmend = false; OnPropertyChanged(); + return; } - else + + var head = new Commands.QuerySingleCommit(_repo.FullPath, currentBranch.Head).Result(); + if (head == null) { - CommitMessage = commits[0].Body; + App.RaiseException(_repo.FullPath, "No commits to amend!!!"); + _useAmend = false; + OnPropertyChanged(); + return; } + + CommitMessage = head.Body; } OnPropertyChanged(nameof(IsCommitWithPushVisible)); diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index e5d064c2..a726f57c 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -68,7 +68,7 @@