diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs index cbc19bae..184cc347 100644 --- a/src/Commands/QueryStashes.cs +++ b/src/Commands/QueryStashes.cs @@ -7,11 +7,9 @@ namespace SourceGit.Commands { public QueryStashes(string repo) { - _boundary = $"-----BOUNDARY_OF_COMMIT{Guid.NewGuid()}-----"; - WorkingDirectory = repo; Context = repo; - Args = $"stash list --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B%n{_boundary}\""; + Args = $"stash list -z --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B\""; } public List Result() @@ -21,66 +19,57 @@ namespace SourceGit.Commands if (!rs.IsSuccess) return outs; - var nextPartIdx = 0; - var start = 0; - var end = rs.StdOut.IndexOf('\n', start); - while (end > 0) + var items = rs.StdOut.Split('\0', System.StringSplitOptions.RemoveEmptyEntries); + foreach (var item in items) { - var line = rs.StdOut.Substring(start, end - start); + var current = new Models.Stash(); - switch (nextPartIdx) + var nextPartIdx = 0; + var start = 0; + var end = item.IndexOf('\n', start); + while (end > 0 && nextPartIdx < 4) { - case 0: - _current = new Models.Stash() { SHA = line }; - outs.Add(_current); - break; - case 1: - ParseParent(line); - break; - case 2: - _current.Time = ulong.Parse(line); - break; - case 3: - _current.Name = line; - break; - default: - var boundary = rs.StdOut.IndexOf(_boundary, end + 1, StringComparison.Ordinal); - if (boundary > end) - { - _current.Message = rs.StdOut.Substring(start, boundary - start - 1); - end = boundary + _boundary.Length; - } - else - { - _current.Message = rs.StdOut.Substring(start); - end = rs.StdOut.Length - 2; - } + var line = item.Substring(start, end - start); - nextPartIdx = -1; + switch (nextPartIdx) + { + case 0: + current.SHA = line; + break; + case 1: + ParseParent(line, ref current); + break; + case 2: + current.Time = ulong.Parse(line); + break; + case 3: + current.Name = line; + break; + } + + nextPartIdx++; + + start = end + 1; + if (start >= item.Length - 1) break; + + end = item.IndexOf('\n', start); } - nextPartIdx++; + if (start < item.Length) + current.Message = item.Substring(start); - start = end + 1; - if (start >= rs.StdOut.Length - 1) - break; - - end = rs.StdOut.IndexOf('\n', start); + outs.Add(current); } - return outs; } - private void ParseParent(string data) + private void ParseParent(string data, ref Models.Stash current) { if (data.Length < 8) return; - _current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries)); + current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries)); } - - private Models.Stash _current = null; - private readonly string _boundary; } } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index b5e933c0..a4066891 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -697,6 +697,7 @@ Both staged and unstaged changes of selected file(s) will be stashed!!! Stash Local Changes Apply + Copy Message Drop Save as Patch... Drop Stash diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index f039d54e..1f11425d 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -194,11 +194,21 @@ namespace SourceGit.ViewModels e.Handled = true; }; + var copy = new MenuItem(); + copy.Header = App.Text("StashCM.CopyMessage"); + copy.Icon = App.CreateMenuIcon("Icons.Copy"); + copy.Click += (_, ev) => + { + App.CopyText(stash.Message); + ev.Handled = true; + }; + var menu = new ContextMenu(); menu.Items.Add(apply); menu.Items.Add(drop); menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(patch); + menu.Items.Add(copy); return menu; }