-
Notifications
You must be signed in to change notification settings - Fork 897
Introduce StashCollection.Apply and Pop #1068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -204,6 +204,156 @@ public void CanStashIgnoredFiles() | |
} | ||
} | ||
|
||
[Fact] | ||
public void CanStashAndApplyWithOptions() | ||
{ | ||
string path = SandboxStandardTestRepo(); | ||
using (var repo = new Repository(path)) | ||
{ | ||
var stasher = Constants.Signature; | ||
|
||
const string filename = "staged_file_path.txt"; | ||
Touch(repo.Info.WorkingDirectory, filename, "I'm staged\n"); | ||
repo.Stage(filename); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options"); | ||
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Apply(0)); | ||
|
||
Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(filename)); | ||
Assert.Equal(1, repo.Stashes.Count()); | ||
|
||
repo.Stage(filename); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options"); | ||
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Apply( | ||
0, | ||
new StashApplyOptions | ||
{ | ||
ApplyModifiers = StashApplyModifiers.ReinstateIndex, | ||
})); | ||
|
||
Assert.Equal(FileStatus.NewInIndex, repo.RetrieveStatus(filename)); | ||
Assert.Equal(2, repo.Stashes.Count()); | ||
} | ||
} | ||
|
||
[Fact] | ||
public void CanStashAndPop() | ||
{ | ||
string path = SandboxStandardTestRepo(); | ||
using (var repo = new Repository(path)) | ||
{ | ||
var stasher = Constants.Signature; | ||
|
||
Assert.Equal(0, repo.Stashes.Count()); | ||
|
||
const string filename = "staged_file_path.txt"; | ||
const string contents = "I'm staged"; | ||
Touch(repo.Info.WorkingDirectory, filename, contents); | ||
repo.Stage(filename); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Assert.Equal(1, repo.Stashes.Count()); | ||
|
||
Assert.Equal(StashApplyStatus.Applied, repo.Stashes.Pop(0)); | ||
Assert.Equal(0, repo.Stashes.Count()); | ||
|
||
Assert.Equal(FileStatus.NewInWorkdir, repo.RetrieveStatus(filename)); | ||
Assert.Equal(contents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename))); | ||
} | ||
} | ||
|
||
[Fact] | ||
public void StashReportsConflictsWhenReinstated() | ||
{ | ||
string path = SandboxStandardTestRepo(); | ||
using (var repo = new Repository(path)) | ||
{ | ||
var stasher = Constants.Signature; | ||
|
||
const string filename = "staged_file_path.txt"; | ||
const string originalContents = "I'm pre-stash."; | ||
const string filename2 = "unstaged_file_path.txt"; | ||
const string newContents = "I'm post-stash."; | ||
|
||
Touch(repo.Info.WorkingDirectory, filename, originalContents); | ||
repo.Stage(filename); | ||
Touch(repo.Info.WorkingDirectory, filename2, originalContents); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options"); | ||
|
||
Touch(repo.Info.WorkingDirectory, filename, newContents); | ||
repo.Stage(filename); | ||
Touch(repo.Info.WorkingDirectory, filename2, newContents); | ||
|
||
Assert.Equal(StashApplyStatus.Conflicts, repo.Stashes.Pop(0, new StashApplyOptions | ||
{ | ||
ApplyModifiers = StashApplyModifiers.ReinstateIndex, | ||
})); | ||
Assert.Equal(1, repo.Stashes.Count()); | ||
Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename))); | ||
Assert.Equal(newContents, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, filename2))); | ||
} | ||
} | ||
|
||
[Fact] | ||
public void StashCallsTheCallback() | ||
{ | ||
string path = SandboxStandardTestRepo(); | ||
using (var repo = new Repository(path)) | ||
{ | ||
var stasher = Constants.Signature; | ||
bool called; | ||
|
||
const string filename = "staged_file_path.txt"; | ||
const string filename2 = "unstaged_file_path.txt"; | ||
const string originalContents = "I'm pre-stash."; | ||
|
||
Touch(repo.Info.WorkingDirectory, filename, originalContents); | ||
repo.Stage(filename); | ||
Touch(repo.Info.WorkingDirectory, filename2, originalContents); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options"); | ||
|
||
called = false; | ||
repo.Stashes.Apply(0, new StashApplyOptions | ||
{ | ||
ProgressHandler = (progress) => { called = true; return true; } | ||
}); | ||
|
||
Assert.Equal(true, called); | ||
|
||
repo.Reset(ResetMode.Hard); | ||
|
||
called = false; | ||
repo.Stashes.Pop(0, new StashApplyOptions | ||
{ | ||
ProgressHandler = (progress) => { called = true; return true; } | ||
}); | ||
|
||
Assert.Equal(true, called); | ||
} | ||
} | ||
|
||
[Fact] | ||
public void StashApplyReportsNotFound() | ||
{ | ||
string path = SandboxStandardTestRepo(); | ||
using (var repo = new Repository(path)) | ||
{ | ||
var stasher = Constants.Signature; | ||
|
||
const string filename = "unstaged_file_path.txt"; | ||
Touch(repo.Info.WorkingDirectory, filename, "I'm unstaged\n"); | ||
|
||
repo.Stashes.Add(stasher, "This stash with default options", StashModifiers.IncludeUntracked); | ||
Touch(repo.Info.WorkingDirectory, filename, "I'm another unstaged\n"); | ||
|
||
Assert.Equal(StashApplyStatus.NotFound, repo.Stashes.Pop(1)); | ||
Assert.Throws<ArgumentException>(() => repo.Stashes.Pop(-1)); | ||
} | ||
} | ||
|
||
[Theory] | ||
[InlineData(-1)] | ||
[InlineData(-42)] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace LibGit2Sharp.Core | ||
{ | ||
internal delegate int stash_apply_progress_cb(StashApplyProgress progress, IntPtr payload); | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal class GitStashApplyOpts | ||
{ | ||
public uint Version = 1; | ||
|
||
public StashApplyModifiers Flags; | ||
public GitCheckoutOpts CheckoutOptions; | ||
|
||
public stash_apply_progress_cb ApplyProgressCallback; | ||
public IntPtr ProgressPayload; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using LibGit2Sharp.Core; | ||
using LibGit2Sharp.Handlers; | ||
|
||
namespace LibGit2Sharp | ||
{ | ||
/// <summary> | ||
/// The options to be used for stash application. | ||
/// </summary> | ||
public sealed class StashApplyOptions | ||
{ | ||
/// <summary> | ||
/// <see cref="StashApplyModifiers"/> for controlling checkout index reinstating./> | ||
/// </summary> | ||
/// <value>The flags.</value> | ||
public StashApplyModifiers ApplyModifiers { get; set; } | ||
|
||
/// <summary> | ||
/// <see cref="CheckoutOptions"/> controlling checkout behavior. | ||
/// </summary> | ||
/// <value>The checkout options.</value> | ||
public CheckoutOptions CheckoutOptions { get; set; } | ||
|
||
/// <summary> | ||
/// <see cref="StashApplyProgressHandler"/> for controlling stash application progress./> | ||
/// </summary> | ||
/// <value>The progress handler.</value> | ||
public StashApplyProgressHandler ProgressHandler { get; set; } | ||
} | ||
|
||
/// <summary> | ||
/// The flags which control whether the index should be reinstated. | ||
/// </summary> | ||
[Flags] | ||
public enum StashApplyModifiers | ||
{ | ||
/// <summary> | ||
/// Default. Will apply the stash and result in an index with conflicts | ||
/// if any arise. | ||
/// </summary> | ||
Default = 0, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about making it explicit? eg. |
||
|
||
/// <summary> | ||
/// In case any conflicts arise, this will not apply the stash. | ||
/// </summary> | ||
ReinstateIndex = (1 << 0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing is, it's weird git naming. ReinstateIndex gives a merge conflict, default doesn't pop. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was really bad at thinking when I responded. I'm bringing this libgit2 comment into place. What I meant is that ReinstateIndex will not create an index when conflicts arise (doesn't pop/apply), but when the default is used, it'll generate an index with conflicts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duh. Stash is hard. But your explanation makes it much clearer. Thanks! I really think this deserves to be described in the xml doc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah so, naming should stay as is, so we match cli git and libgit2 flags. I'll update the docs to reflect the stuff. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
|
||
namespace LibGit2Sharp | ||
{ | ||
/// <summary> | ||
/// The current progress of the stash application. | ||
/// </summary> | ||
public enum StashApplyProgress | ||
{ | ||
/// <summary> | ||
/// Not passed by the callback. Used as dummy value. | ||
/// </summary> | ||
None = 0, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I'm not even sure that its called the first time. Judging from https://github.com/libgit2/libgit2/pull/3018/files#diff-f54e4a7883cb063f36ebd8f4206ce55fR290, I may have misnamed it. |
||
|
||
/// <summary> | ||
/// Loading the stashed data from the object database. | ||
/// </summary> | ||
LoadingStash, | ||
|
||
/// <summary> | ||
/// The stored index is being analyzed. | ||
/// </summary> | ||
AnalyzeIndex, | ||
|
||
/// <summary> | ||
/// The modified files are being analyzed. | ||
/// </summary> | ||
AnalyzeModified, | ||
|
||
/// <summary> | ||
/// The untracked and ignored files are being analyzed. | ||
/// </summary> | ||
AnalyzeUntracked, | ||
|
||
/// <summary> | ||
/// The untracked files are being written to disk. | ||
/// </summary> | ||
CheckoutUntracked, | ||
|
||
/// <summary> | ||
/// The modified files are being written to disk. | ||
/// </summary> | ||
CheckoutModified, | ||
|
||
/// <summary> | ||
/// The stash was applied successfully. | ||
/// </summary> | ||
Done, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System; | ||
|
||
namespace LibGit2Sharp | ||
{ | ||
/// <summary> | ||
/// The result of a stash application operation. | ||
/// </summary> | ||
public enum StashApplyStatus | ||
{ | ||
/// <summary> | ||
/// The stash application was successful. | ||
/// </summary> | ||
Applied, | ||
|
||
/// <summary> | ||
/// The stash application ended up with conflicts. | ||
/// </summary> | ||
Conflicts, | ||
|
||
/// <summary> | ||
/// The stash index given was not found. | ||
/// </summary> | ||
NotFound, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert.Equal(0, repo.Stashes.Count());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixt.