Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2sharp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJameson Miller <jamill@microsoft.com>2013-01-09 04:59:23 +0400
committernulltoken <emeric.fermas@gmail.com>2013-01-22 18:14:35 +0400
commit5dc82d2af943232cc0fc0b74781309cff994e92a (patch)
tree72f90a5999b63521286e5d72f04819d101710e40
parent86547599ed4ec0685d34762376fa1322393b00a1 (diff)
Update checkout in response to libgit2 checkout changes
-rw-r--r--LibGit2Sharp.Tests/CheckoutFixture.cs53
-rw-r--r--LibGit2Sharp/Repository.cs64
2 files changed, 61 insertions, 56 deletions
diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs
index cb28d808..082b7d7d 100644
--- a/LibGit2Sharp.Tests/CheckoutFixture.cs
+++ b/LibGit2Sharp.Tests/CheckoutFixture.cs
@@ -10,6 +10,7 @@ namespace LibGit2Sharp.Tests
{
private static readonly string originalFilePath = "a.txt";
private static readonly string originalFileContent = "Hello";
+ private static readonly string conflictingFileContent = "There";
private static readonly string otherBranchName = "other";
[Theory]
@@ -190,8 +191,16 @@ namespace LibGit2Sharp.Tests
}
[Fact]
- public void CanForcefullyCheckoutWithStagedChanges()
+ public void CanForcefullyCheckoutWithConflictingStagedChanges()
{
+ // This test will check that we can checkout a branch that results
+ // in a conflict. Here is the high level steps of the test:
+ // 1) Create branch otherBranch from current commit in master,
+ // 2) Commit change to master
+ // 3) Switch to otherBranch
+ // 4) Create conflicting change
+ // 5) Forcefully checkout master
+
TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath);
using (var repo = new Repository(path.RepositoryPath))
@@ -200,31 +209,39 @@ namespace LibGit2Sharp.Tests
Branch master = repo.Branches["master"];
Assert.True(master.IsCurrentRepositoryHead);
- // Set the working directory to the current head
+ // Set the working directory to the current head.
ResetAndCleanWorkingDirectory(repo);
Assert.False(repo.Index.RetrieveStatus().IsDirty);
- // Add local change
+ // Create otherBranch from current Head.
+ repo.Branches.Add(otherBranchName, master.Tip);
+
+ // Add change to master.
string fullPath = Path.Combine(repo.Info.WorkingDirectory, fileFullPath);
File.WriteAllText(fullPath, originalFileContent);
repo.Index.Stage(fullPath);
+ repo.Commit("change in master", Constants.Signature, Constants.Signature);
- // Verify working directory is now dirty
- Assert.True(repo.Index.RetrieveStatus().IsDirty);
+ // Checkout otherBranch.
+ repo.Checkout(otherBranchName);
- // And that the new file exists
- Assert.True(File.Exists(fileFullPath));
+ // Add change to otherBranch.
+ File.WriteAllText(fullPath, conflictingFileContent);
+ repo.Index.Stage(fullPath);
+
+ // Assert that normal checkout throws exception
+ // for the conflict.
+ Assert.Throws<LibGit2SharpException>(() => master.Checkout());
- // Checkout with the force option
- Branch targetBranch = repo.Branches["i-do-numbers"];
- targetBranch.Checkout(CheckoutOptions.Force, null);
+ // Checkout with force option should succeed.
+ master.Checkout(CheckoutOptions.Force, null);
- // Assert that target branch is checked out
- Assert.True(targetBranch.IsCurrentRepositoryHead);
+ // Assert that master branch is checked out.
+ Assert.True(repo.Branches["master"].IsCurrentRepositoryHead);
- // And that staged change (add) is no longer preset
- Assert.False(File.Exists(fileFullPath));
+ // And that the current index is not dirty.
+ Assert.False(repo.Index.RetrieveStatus().IsDirty);
}
}
@@ -254,11 +271,11 @@ namespace LibGit2Sharp.Tests
// Assert that checking out master throws
// when there are unstaged commits
- Assert.Throws<MergeConflictException>(() => repo.Checkout("master"));
+ Assert.Throws<LibGit2SharpException>(() => repo.Checkout("master"));
// And when there are staged commits
repo.Index.Stage(fullPath);
- Assert.Throws<MergeConflictException>(() => repo.Checkout("master"));
+ Assert.Throws<LibGit2SharpException>(() => repo.Checkout("master"));
}
}
@@ -267,8 +284,8 @@ namespace LibGit2Sharp.Tests
{
using (var repo = new Repository(BareTestRepoPath))
{
- Assert.Throws<InvalidOperationException>(() => repo.Checkout(repo.Branches["refs/heads/test"]));
- Assert.Throws<InvalidOperationException>(() => repo.Checkout("refs/heads/test"));
+ Assert.Throws<BareRepositoryException>(() => repo.Checkout(repo.Branches["refs/heads/test"]));
+ Assert.Throws<BareRepositoryException>(() => repo.Checkout("refs/heads/test"));
}
}
diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs
index 379c7448..668da5bd 100644
--- a/LibGit2Sharp/Repository.cs
+++ b/LibGit2Sharp/Repository.cs
@@ -504,11 +504,16 @@ namespace LibGit2Sharp
if (branch != null)
{
- return CheckoutInternal(branch.CanonicalName, checkoutOptions, onCheckoutProgress);
+ return Checkout(branch, checkoutOptions, onCheckoutProgress);
}
- var commitId = LookupCommit(committishOrBranchSpec).Id;
- return CheckoutInternal(commitId.Sha, checkoutOptions, onCheckoutProgress);
+ Commit commit = LookupCommit(committishOrBranchSpec);
+ CheckoutTree(commit.Tree, checkoutOptions, onCheckoutProgress);
+
+ // Update HEAD.
+ Refs.UpdateTarget("HEAD", commit.Id.Sha);
+
+ return Head;
}
/// <summary>
@@ -522,7 +527,16 @@ namespace LibGit2Sharp
{
Ensure.ArgumentNotNull(branch, "branch");
- return CheckoutInternal(branch.CanonicalName, checkoutOptions, onCheckoutProgress);
+ // Get the current tip commit of the branch, instead of
+ // relying on branch.Tip, which references the commit at
+ // the time the passed in branch object was created.
+ Commit commit = LookupCommit(branch.CanonicalName);
+ CheckoutTree(commit.Tree, checkoutOptions, onCheckoutProgress);
+
+ // Update HEAD.
+ Refs.UpdateTarget("HEAD", branch.CanonicalName);
+
+ return Head;
}
/// <summary>
@@ -533,47 +547,21 @@ namespace LibGit2Sharp
/// <param name="checkoutOptions"><see cref = "CheckoutOptions" /> controlling checkout behavior.</param>
/// <param name="onCheckoutProgress"><see cref = "CheckoutProgressHandler" /> that checkout progress is reported through.</param>
/// <returns>The <see cref = "Branch" /> that was checked out.</returns>
- private Branch CheckoutInternal(string commitIdOrCanonicalBranchName, CheckoutOptions checkoutOptions, CheckoutProgressHandler onCheckoutProgress)
- {
- if (Info.IsBare)
- {
- throw new InvalidOperationException("Checkout is not allowed in a bare repository.");
- }
-
- // Unless the Force option is specified,
- // check if the current index / working tree is in a state
- // where we can checkout a new branch.
- if ((checkoutOptions & CheckoutOptions.Force) != CheckoutOptions.Force)
- {
- RepositoryStatus repositoryStatus = Index.RetrieveStatus();
- if (repositoryStatus.IsDirty)
- {
- throw new MergeConflictException(
- "There are changes to files in the working directory that would be overwritten by a checkout." +
- "Please commit your changes before you switch branches.");
- }
- }
-
- // Update HEAD
- Refs.UpdateTarget("HEAD", commitIdOrCanonicalBranchName);
-
- // Update the working directory
- CheckoutHeadForce(onCheckoutProgress);
-
- return Head;
- }
-
- private void CheckoutHeadForce(CheckoutProgressHandler onCheckoutProgress)
+ private void CheckoutTree(Tree tree, CheckoutOptions checkoutOptions, CheckoutProgressHandler onCheckoutProgress)
{
GitCheckoutOpts options = new GitCheckoutOpts
{
version = 1,
- checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE |
- CheckoutStrategy.GIT_CHECKOUT_REMOVE_UNTRACKED,
+ checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_SAFE,
progress_cb = CheckoutCallbacks.GenerateCheckoutCallbacks(onCheckoutProgress)
};
- Proxy.git_checkout_head(this.Handle, ref options);
+ if (checkoutOptions.HasFlag(CheckoutOptions.Force))
+ {
+ options.checkout_strategy = CheckoutStrategy.GIT_CHECKOUT_FORCE;
+ }
+
+ Proxy.git_checkout_tree(this.Handle, tree.Id, ref options);
}
/// <summary>