Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5f3375a

Browse files
committed
Introduce StashCollection.Apply and Pop
1 parent 2c98992 commit 5f3375a

10 files changed

+425
-0
lines changed

LibGit2Sharp.Tests/StashFixture.cs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,152 @@ public void CanStashIgnoredFiles()
204204
}
205205
}
206206

207+
[Fact]
208+
public void CanStashAndApplyWithOptions()
209+
{
210+
string path = SandboxStandardTestRepo();
211+
using (var repo = new Repository(path))
212+
{
213+
var stasher = Constants.Signature;
214+
215+
const string filename = "staged_file_path.txt";
216+
Touch(repo.Info.WorkingDirectory, filename, "I'm staged\n");
217+
repo.Stage(filename);
218+
219+
repo.Stashes.Add(stasher, "This stash with default options");
220+
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Apply(0));
221+
222+
Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(filename));
223+
Assert.Equal(1, repo.Stashes.Count());
224+
225+
repo.Stage(filename);
226+
227+
repo.Stashes.Add(stasher, "This stash with default options");
228+
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Apply(
229+
0,
230+
new StashApplyOptions
231+
{
232+
ApplyModifiers = StashApplyModifiers.ReinstateIndex,
233+
}));
234+
235+
Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename));
236+
Assert.Equal(2, repo.Stashes.Count());
237+
}
238+
}
239+
240+
[Fact]
241+
public void CanStashAndPop()
242+
{
243+
string path = SandboxStandardTestRepo();
244+
using (var repo = new Repository(path))
245+
{
246+
var stasher = Constants.Signature;
247+
248+
const string filename = "staged_file_path.txt";
249+
const string contents = "I'm staged\n";
250+
string contentsNew = "I'm staged" + Environment.NewLine;
251+
Touch(repo.Info.WorkingDirectory, filename, contents);
252+
repo.Stage(filename);
253+
254+
repo.Stashes.Add(stasher, "This stash with default options");
255+
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Pop(0));
256+
257+
Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(filename));
258+
Assert.Equal(0, repo.Stashes.Count());
259+
Assert.Equal(contentsNew, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename)));
260+
}
261+
}
262+
263+
[Fact]
264+
public void StashReportsConflictsWhenReinstated()
265+
{
266+
string path = SandboxStandardTestRepo();
267+
using (var repo = new Repository(path))
268+
{
269+
var stasher = Constants.Signature;
270+
271+
const string filename = "staged_file_path.txt";
272+
const string originalContents = "I'm pre-stash.";
273+
const string filename2 = "unstaged_file_path.txt";
274+
const string newContents = "I'm post-stash.";
275+
276+
Touch(repo.Info.WorkingDirectory, filename, originalContents);
277+
repo.Stage(filename);
278+
Touch(repo.Info.WorkingDirectory, filename2, originalContents);
279+
280+
repo.Stashes.Add(stasher, "This stash with default options");
281+
282+
Touch(repo.Info.WorkingDirectory, filename, newContents);
283+
repo.Stage(filename);
284+
Touch(repo.Info.WorkingDirectory, filename2, newContents);
285+
286+
Assert.Equal(StashApplyStatus.Conflicts, repo.Stashes.Pop(0, new StashApplyOptions
287+
{
288+
ApplyModifiers = StashApplyModifiers.ReinstateIndex,
289+
}));
290+
Assert.Equal(1, repo.Stashes.Count());
291+
Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename)));
292+
Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename2)));
293+
}
294+
}
295+
296+
[Fact]
297+
public void StashCallsTheCallback()
298+
{
299+
string path = SandboxStandardTestRepo();
300+
using (var repo = new Repository(path))
301+
{
302+
var stasher = Constants.Signature;
303+
bool called;
304+
305+
const string filename = "staged_file_path.txt";
306+
const string filename2 = "unstaged_file_path.txt";
307+
const string originalContents = "I'm pre-stash.";
308+
309+
Touch(repo.Info.WorkingDirectory, filename, originalContents);
310+
repo.Stage(filename);
311+
Touch(repo.Info.WorkingDirectory, filename2, originalContents);
312+
313+
repo.Stashes.Add(stasher, "This stash with default options");
314+
315+
called = false;
316+
repo.Stashes.Apply(0, new StashApplyOptions
317+
{
318+
ProgressHandler = (progress) => { called = true; return true; }
319+
});
320+
321+
Assert.Equal(true, called);
322+
323+
repo.Reset(ResetMode.Hard);
324+
325+
called = false;
326+
repo.Stashes.Pop(0, new StashApplyOptions
327+
{
328+
ProgressHandler = (progress) => { called = true; return true; }
329+
});
330+
331+
Assert.Equal(true, called);
332+
}
333+
}
334+
335+
[Fact]
336+
public void StashApplyReportsNotFound()
337+
{
338+
string path = SandboxStandardTestRepo();
339+
using (var repo = new Repository(path))
340+
{
341+
var stasher = Constants.Signature;
342+
343+
const string filename = "unstaged_file_path.txt";
344+
Touch(repo.Info.WorkingDirectory, filename, "I'm unstaged\n");
345+
346+
repo.Stashes.Add(stasher, "This stash with default options", StashModifiers.IncludeUntracked);
347+
Touch(repo.Info.WorkingDirectory, filename, "I'm another unstaged\n");
348+
349+
Assert.Equal(StashApplyStatus.NotFound, repo.Stashes.Pop(1));
350+
}
351+
}
352+
207353
[Theory]
208354
[InlineData(-1)]
209355
[InlineData(-42)]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace LibGit2Sharp.Core
5+
{
6+
internal delegate int stash_apply_progress_cb(StashApplyProgress progress, IntPtr payload);
7+
8+
[StructLayout(LayoutKind.Sequential)]
9+
internal class GitStashApplyOpts
10+
{
11+
public uint Version = 1;
12+
13+
public StashApplyModifiers Flags;
14+
public GitCheckoutOpts CheckoutOptions;
15+
16+
public stash_apply_progress_cb ApplyProgressCallback;
17+
public IntPtr ProgressPayload;
18+
}
19+
}
20+

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,18 @@ internal static extern int git_stash_foreach(
13661366
[DllImport(libgit2)]
13671367
internal static extern int git_stash_drop(RepositorySafeHandle repo, UIntPtr index);
13681368

1369+
[DllImport(libgit2)]
1370+
internal static extern int git_stash_apply(
1371+
RepositorySafeHandle repo,
1372+
UIntPtr index,
1373+
GitStashApplyOpts opts);
1374+
1375+
[DllImport(libgit2)]
1376+
internal static extern int git_stash_pop(
1377+
RepositorySafeHandle repo,
1378+
UIntPtr index,
1379+
GitStashApplyOpts opts);
1380+
13691381
[DllImport(libgit2)]
13701382
internal static extern int git_status_file(
13711383
out FileStatus statusflags,

LibGit2Sharp/Core/Proxy.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,38 @@ public static void git_stash_drop(RepositorySafeHandle repo, int index)
24522452
Ensure.BooleanResult(res);
24532453
}
24542454

2455+
private static StashApplyStatus get_stash_status(int res)
2456+
{
2457+
if (res == (int)GitErrorCode.Conflict)
2458+
{
2459+
return StashApplyStatus.Conflicts;
2460+
}
2461+
2462+
if (res == (int)GitErrorCode.NotFound)
2463+
{
2464+
return StashApplyStatus.NotFound;
2465+
}
2466+
2467+
Ensure.ZeroResult(res);
2468+
return StashApplyStatus.Applied;
2469+
}
2470+
2471+
public static StashApplyStatus git_stash_apply(
2472+
RepositorySafeHandle repo,
2473+
int index,
2474+
GitStashApplyOpts opts)
2475+
{
2476+
return get_stash_status(NativeMethods.git_stash_apply(repo, (UIntPtr)index, opts));
2477+
}
2478+
2479+
public static StashApplyStatus git_stash_pop(
2480+
RepositorySafeHandle repo,
2481+
int index,
2482+
GitStashApplyOpts opts)
2483+
{
2484+
return get_stash_status(NativeMethods.git_stash_pop(repo, (UIntPtr)index, opts));
2485+
}
2486+
24552487
#endregion
24562488

24572489
#region git_status_

LibGit2Sharp/Handlers.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ namespace LibGit2Sharp.Handlers
112112
/// <param name="problematicRefspec">The refspec which didn't match the default.</param>
113113
public delegate void RemoteRenameFailureHandler(string problematicRefspec);
114114

115+
/// <summary>
116+
/// Delegate definition for stash application callback.
117+
/// </summary>
118+
/// <param name="progress">The current step of the stash application.</param>
119+
/// <returns>True to continue checkout operation; false to cancel checkout operation.</returns>
120+
public delegate bool StashApplyProgressHandler(StashApplyProgress progress);
121+
115122
/// <summary>
116123
/// The stages of pack building.
117124
/// </summary>

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@
357357
<Compile Include="Core\RawContentStream.cs" />
358358
<Compile Include="Core\Handles\OdbStreamSafeHandle.cs" />
359359
<Compile Include="SupportedCredentialTypes.cs" />
360+
<Compile Include="StashApplyProgress.cs" />
361+
<Compile Include="StashApplyOptions.cs" />
362+
<Compile Include="StashApplyStatus.cs" />
363+
<Compile Include="Core\GitStashApplyOpts.cs" />
360364
</ItemGroup>
361365
<ItemGroup>
362366
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

LibGit2Sharp/StashApplyOptions.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using LibGit2Sharp.Core;
3+
using LibGit2Sharp.Handlers;
4+
5+
namespace LibGit2Sharp
6+
{
7+
/// <summary>
8+
/// The options to be used for stash application.
9+
/// </summary>
10+
public sealed class StashApplyOptions
11+
{
12+
/// <summary>
13+
/// <see cref="StashApplyModifiers"/> for controlling checkout index reinstating./>
14+
/// </summary>
15+
/// <value>The flags.</value>
16+
public StashApplyModifiers ApplyModifiers { get; set; }
17+
18+
/// <summary>
19+
/// <see cref="CheckoutOptions"/> controlling checkout behavior.
20+
/// </summary>
21+
/// <value>The checkout options.</value>
22+
public CheckoutOptions CheckoutOptions { get; set; }
23+
24+
/// <summary>
25+
/// <see cref="StashApplyProgressHandler"/> for controlling stash application progress./>
26+
/// </summary>
27+
/// <value>The progress handler.</value>
28+
public StashApplyProgressHandler ProgressHandler { get; set; }
29+
}
30+
31+
/// <summary>
32+
/// The flags which control whether the index should be reinstated.
33+
/// </summary>
34+
[Flags]
35+
public enum StashApplyModifiers
36+
{
37+
/// <summary>
38+
/// Default. Reinstate working directory stashed
39+
/// changes.
40+
/// </summary>
41+
Default = 0,
42+
43+
/// <summary>
44+
/// Reinstate both index and working directory stashed
45+
/// changes.
46+
/// </summary>
47+
ReinstateIndex = (1 << 0),
48+
}
49+
}
50+

LibGit2Sharp/StashApplyProgress.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
3+
namespace LibGit2Sharp
4+
{
5+
/// <summary>
6+
/// The current progress of the stash application.
7+
/// </summary>
8+
public enum StashApplyProgress
9+
{
10+
/// <summary>
11+
/// The stash application has just started.
12+
/// </summary>
13+
None = 0,
14+
15+
/// <summary>
16+
/// Loading the stashed data from the object database.
17+
/// </summary>
18+
LoadingStash,
19+
20+
/// <summary>
21+
/// The stored index is being analyzed.
22+
/// </summary>
23+
AnalyzeIndex,
24+
25+
/// <summary>
26+
/// The modified files are being analyzed.
27+
/// </summary>
28+
AnalyzeModified,
29+
30+
/// <summary>
31+
/// The untracked and ignored files are being analyzed.
32+
/// </summary>
33+
AnalyzeUntracked,
34+
35+
/// <summary>
36+
/// The untracked files are being written to disk.
37+
/// </summary>
38+
CheckoutUntracked,
39+
40+
/// <summary>
41+
/// The modified files are being written to disk.
42+
/// </summary>
43+
CheckoutModified,
44+
45+
/// <summary>
46+
/// The stash was applied successfully.
47+
/// </summary>
48+
Done,
49+
}
50+
51+
}
52+

LibGit2Sharp/StashApplyStatus.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
3+
namespace LibGit2Sharp
4+
{
5+
/// <summary>
6+
/// The result of a stash application operation.
7+
/// </summary>
8+
public enum StashApplyStatus
9+
{
10+
/// <summary>
11+
/// The stash application was successful.
12+
/// </summary>
13+
Applied,
14+
15+
/// <summary>
16+
/// The stash application ended up with conflicts.
17+
/// </summary>
18+
Conflicts,
19+
20+
/// <summary>
21+
/// The stash index given was not found.
22+
/// </summary>
23+
NotFound,
24+
}
25+
}
26+

0 commit comments

Comments
 (0)