diff options
author | Jameson Miller <jamill@microsoft.com> | 2013-01-22 08:07:05 +0400 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2013-01-22 18:22:17 +0400 |
commit | 6aad7fd187028cf91e22998b79f9cd2a177e2ab0 (patch) | |
tree | 624aba93cb03d64be709b66ec9ab3af85cf0c6a6 | |
parent | 91da7861cabe59c231a38d1f9c9b80e5440aa641 (diff) |
Checkout branch as snapshot
-rw-r--r-- | LibGit2Sharp.Tests/CheckoutFixture.cs | 54 | ||||
-rw-r--r-- | LibGit2Sharp/Branch.cs | 10 | ||||
-rw-r--r-- | LibGit2Sharp/Repository.cs | 27 |
3 files changed, 80 insertions, 11 deletions
diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs index 6df94fe6..3b219f3e 100644 --- a/LibGit2Sharp.Tests/CheckoutFixture.cs +++ b/LibGit2Sharp.Tests/CheckoutFixture.cs @@ -233,10 +233,10 @@ namespace LibGit2Sharp.Tests // Assert that normal checkout throws exception // for the conflict. - Assert.Throws<LibGit2SharpException>(() => master.Checkout()); + Assert.Throws<LibGit2SharpException>(() => repo.Checkout(master.CanonicalName)); // Checkout with force option should succeed. - master.Checkout(CheckoutOptions.Force, null); + repo.Checkout(master.CanonicalName, CheckoutOptions.Force, null); // Assert that master branch is checked out. Assert.True(repo.Branches["master"].IsCurrentRepositoryHead); @@ -504,6 +504,56 @@ namespace LibGit2Sharp.Tests } } + [Fact] + public void CheckoutBranchSnapshot() + { + SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); + + using (var repo = Repository.Init(scd.DirectoryPath)) + { + PopulateBasicRepository(repo); + + // Get the current status of master + // and the current tip. + Branch initial = repo.Branches["master"]; + Commit initialCommit = initial.Tip; + + // Add commit to master + string fullPath = Path.Combine(repo.Info.WorkingDirectory, originalFilePath); + File.WriteAllText(fullPath, "Update : hello from master branch!\n"); + repo.Index.Stage(fullPath); + repo.Commit("2nd commit", Constants.Signature, Constants.Signature); + + initial.Checkout(); + + // Head should point at initial commit. + Assert.Equal(repo.Head.Tip, initialCommit); + Assert.False(repo.Index.RetrieveStatus().IsDirty); + // Verify that HEAD is detached. + Assert.Equal(repo.Refs["HEAD"].TargetIdentifier, initial.Tip.Sha); + } + } + + [Fact] + public void CheckingOutRemoteBranchResultsInDetachedHead() + { + TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath); + using (var repo = new Repository(path.RepositoryPath)) + { + Branch master = repo.Branches["master"]; + Assert.True(master.IsCurrentRepositoryHead); + + // Set the working directory to the current head + ResetAndCleanWorkingDirectory(repo); + + repo.Checkout("refs/remotes/origin/master"); + + // Verify that HEAD is detached. + Assert.Equal(repo.Refs["HEAD"].TargetIdentifier, repo.Branches["origin/master"].Tip.Sha); + + } + } + /// <summary> /// Helper method to populate a simple repository with /// a single file and two branches. diff --git a/LibGit2Sharp/Branch.cs b/LibGit2Sharp/Branch.cs index 8744b2ff..da7e8dd7 100644 --- a/LibGit2Sharp/Branch.cs +++ b/LibGit2Sharp/Branch.cs @@ -189,7 +189,10 @@ namespace LibGit2Sharp } /// <summary> - /// Checkout this branch. + /// Checkout the tip commit of this <see cref = "Branch" /> object. + /// If this commit is the current tip of the branch, will checkout + /// the named branch. Otherwise, will checkout the tip commit as a + /// detached HEAD. /// </summary> public virtual void Checkout() { @@ -197,7 +200,10 @@ namespace LibGit2Sharp } /// <summary> - /// Checkout this branch with a callback for progress reporting. + /// Checkout the tip commit of this <see cref = "Branch" /> object + /// with a callback for progress reporting. If this commit is the + /// current tip of the branch, will checkout the named branch. Otherwise, + /// will checkout the tip commit as a detached HEAD. /// </summary> /// <param name="checkoutOptions">Options controlling checkout behavior.</param> /// <param name="onCheckoutProgress">Callback method to report checkout progress updates through.</param> diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index 668da5bd..08452cf3 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -517,7 +517,9 @@ namespace LibGit2Sharp } /// <summary> - /// Checkout the specified <see cref = "Branch" />. + /// Checkout the tip commit of the specified <see cref = "Branch" /> object. If this commit is the + /// current tip of the branch, will checkout the named branch. Otherwise, will checkout the tip commit + /// as a detached HEAD. /// </summary> /// <param name="branch">The <see cref = "Branch" /> to check out. </param> /// <param name="checkoutOptions"><see cref = "CheckoutOptions" /> controlling checkout behavior.</param> @@ -527,14 +529,25 @@ namespace LibGit2Sharp { Ensure.ArgumentNotNull(branch, "branch"); - // 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); + // Make sure this is not an unborn branch. + if (branch.Tip.Tree == null) + { + throw new Exception("branch tip is null, nothing to checkout."); + } + + CheckoutTree(branch.Tip.Tree, checkoutOptions, onCheckoutProgress); // Update HEAD. - Refs.UpdateTarget("HEAD", branch.CanonicalName); + if (!branch.IsRemote && + string.Equals(Refs[branch.CanonicalName].TargetIdentifier, branch.Tip.Id.Sha, + StringComparison.OrdinalIgnoreCase)) + { + Refs.UpdateTarget("HEAD", branch.CanonicalName); + } + else + { + Refs.UpdateTarget("HEAD", branch.Tip.Id.Sha); + } return Head; } |