Skip to content

Commit 38d87fa

Browse files
committed
feature: use git stash show -u --name-status <stash_name> command to query changes in selected stash if git >= 2.32.0
Signed-off-by: leo <[email protected]>
1 parent 65dbfd3 commit 38d87fa

File tree

4 files changed

+98
-13
lines changed

4 files changed

+98
-13
lines changed

src/Commands/QueryStashChanges.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text.RegularExpressions;
4+
5+
namespace SourceGit.Commands
6+
{
7+
/// <summary>
8+
/// Query stash changes. Requires git >= 2.32.0
9+
/// </summary>
10+
public partial class QueryStashChanges : Command
11+
{
12+
[GeneratedRegex(@"^([MADRC])\s+(.+)$")]
13+
private static partial Regex REG_FORMAT();
14+
15+
public QueryStashChanges(string repo, string stash)
16+
{
17+
WorkingDirectory = repo;
18+
Context = repo;
19+
Args = $"stash show -u --name-status \"{stash}\"";
20+
}
21+
22+
public List<Models.Change> Result()
23+
{
24+
var rs = ReadToEnd();
25+
if (!rs.IsSuccess)
26+
return [];
27+
28+
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
29+
var outs = new List<Models.Change>();
30+
foreach (var line in lines)
31+
{
32+
var match = REG_FORMAT().Match(line);
33+
if (!match.Success)
34+
continue;
35+
36+
var change = new Models.Change() { Path = match.Groups[2].Value };
37+
var status = match.Groups[1].Value;
38+
39+
switch (status[0])
40+
{
41+
case 'M':
42+
change.Set(Models.ChangeState.Modified);
43+
outs.Add(change);
44+
break;
45+
case 'A':
46+
change.Set(Models.ChangeState.Added);
47+
outs.Add(change);
48+
break;
49+
case 'D':
50+
change.Set(Models.ChangeState.Deleted);
51+
outs.Add(change);
52+
break;
53+
case 'R':
54+
change.Set(Models.ChangeState.Renamed);
55+
outs.Add(change);
56+
break;
57+
case 'C':
58+
change.Set(Models.ChangeState.Copied);
59+
outs.Add(change);
60+
break;
61+
}
62+
}
63+
64+
outs.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
65+
return outs;
66+
}
67+
}
68+
}

src/Models/GitVersions.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ public static class GitVersions
1313
public static readonly System.Version ADD_WITH_PATHSPECFILE = new System.Version(2, 25, 0);
1414

1515
/// <summary>
16-
/// The minimal version of Git that supports the `stash` command with the `--pathspec-from-file` option.
16+
/// The minimal version of Git that supports the `stash push` command with the `--pathspec-from-file` option.
1717
/// </summary>
18-
public static readonly System.Version STASH_WITH_PATHSPECFILE = new System.Version(2, 26, 0);
18+
public static readonly System.Version STASH_PUSH_WITH_PATHSPECFILE = new System.Version(2, 26, 0);
1919

2020
/// <summary>
21-
/// The minimal version of Git that supports the `stash` command with the `--staged` option.
21+
/// The minimal version of Git that supports the `stash push` command with the `--staged` option.
2222
/// </summary>
23-
public static readonly System.Version STASH_ONLY_STAGED = new System.Version(2, 35, 0);
23+
public static readonly System.Version STASH_PUSH_ONLY_STAGED = new System.Version(2, 35, 0);
24+
25+
/// <summary>
26+
/// The minimal version of Git that supports the `stash show` command with the `-u` option.
27+
/// </summary>
28+
public static readonly System.Version STASH_SHOW_WITH_UNTRACKED = new System.Version(2, 32, 0);
2429
}
2530
}

src/ViewModels/StashChanges.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public override Task<bool> Sure()
6464
{
6565
if (OnlyStaged)
6666
{
67-
if (Native.OS.GitVersion >= Models.GitVersions.STASH_ONLY_STAGED)
67+
if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_ONLY_STAGED)
6868
{
6969
succ = new Commands.Stash(_repo.FullPath).PushOnlyStaged(Message, KeepIndex);
7070
}
@@ -109,7 +109,7 @@ private bool StashWithChanges(List<Models.Change> changes)
109109
return true;
110110

111111
var succ = false;
112-
if (Native.OS.GitVersion >= Models.GitVersions.STASH_WITH_PATHSPECFILE)
112+
if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_WITH_PATHSPECFILE)
113113
{
114114
var paths = new List<string>();
115115
foreach (var c in changes)

src/ViewModels/StashesPage.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,26 @@ public Models.Stash SelectedStash
5858
{
5959
Task.Run(() =>
6060
{
61-
var changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
62-
if (value.Parents.Count == 3)
63-
{
64-
var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result();
65-
foreach (var c in untracked)
66-
changes.Add(c);
61+
var changes = null as List<Models.Change>;
6762

68-
changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
63+
if (Native.OS.GitVersion >= Models.GitVersions.STASH_SHOW_WITH_UNTRACKED)
64+
{
65+
changes = new Commands.QueryStashChanges(_repo.FullPath, value.Name).Result();
66+
}
67+
else
68+
{
69+
changes = new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).Result();
70+
if (value.Parents.Count == 3)
71+
{
72+
var untracked = new Commands.CompareRevisions(_repo.FullPath, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", value.Parents[2]).Result();
73+
var needSort = changes.Count > 0;
74+
75+
foreach (var c in untracked)
76+
changes.Add(c);
77+
78+
if (needSort)
79+
changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
80+
}
6981
}
7082

7183
Dispatcher.UIThread.Invoke(() => Changes = changes);

0 commit comments

Comments
 (0)