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:
-rw-r--r--LibGit2Sharp.Tests/CheckoutFixture.cs162
-rw-r--r--LibGit2Sharp/Configuration.cs11
-rw-r--r--LibGit2Sharp/Repository.cs29
-rw-r--r--LibGit2Sharp/RepositoryExtensions.cs4
4 files changed, 200 insertions, 6 deletions
diff --git a/LibGit2Sharp.Tests/CheckoutFixture.cs b/LibGit2Sharp.Tests/CheckoutFixture.cs
index b01ef319..8bdca0a8 100644
--- a/LibGit2Sharp.Tests/CheckoutFixture.cs
+++ b/LibGit2Sharp.Tests/CheckoutFixture.cs
@@ -44,6 +44,14 @@ namespace LibGit2Sharp.Tests
// Working directory should not be dirty
Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(master.Tip.Id, reflogEntry.From);
+ Assert.Equal(branch.Tip.Id, reflogEntry.To);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal(string.Format("checkout: moving from master to {0}", branchName), reflogEntry.Message);
}
}
@@ -74,6 +82,14 @@ namespace LibGit2Sharp.Tests
// Working directory should not be dirty
Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(master.Tip.Id, reflogEntry.From);
+ Assert.Equal(repo.Branches[branchName].Tip.Id, reflogEntry.To);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal(string.Format("checkout: moving from master to {0}", branchName), reflogEntry.Message);
}
}
@@ -111,6 +127,14 @@ namespace LibGit2Sharp.Tests
Assert.Equal("(no branch)", detachedHead.CanonicalName);
Assert.False(master.IsCurrentRepositoryHead);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(master.Tip.Id, reflogEntry.From);
+ Assert.Equal(commitSha, reflogEntry.To.Sha);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal(string.Format("checkout: moving from master to {0}", commitPointer), reflogEntry.Message);
}
}
@@ -572,6 +596,14 @@ namespace LibGit2Sharp.Tests
// Verify that HEAD is detached.
Assert.Equal(repo.Refs["HEAD"].TargetIdentifier, repo.Branches["origin/master"].Tip.Sha);
Assert.True(repo.Info.IsHeadDetached);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(master.Tip.Id, reflogEntry.From);
+ Assert.Equal(repo.Branches["origin/master"].Tip.Id, reflogEntry.To);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal("checkout: moving from master to origin/master", reflogEntry.Message);
}
}
@@ -601,6 +633,136 @@ namespace LibGit2Sharp.Tests
}
}
+ [Theory]
+ [InlineData("a447ba2ca8")]
+ [InlineData("refs/tags/lw")]
+ [InlineData("e90810^{}")]
+ public void CheckoutFromDetachedHead(string commitPointer)
+ {
+ string path = CloneStandardTestRepo();
+ using (var repo = new Repository(path))
+ {
+ // Set the working directory to the current head
+ ResetAndCleanWorkingDirectory(repo);
+ Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ var commitSha = repo.Lookup(commitPointer).Sha;
+
+ Branch initialHead = repo.Checkout("6dcf9bf");
+
+ repo.Checkout(commitPointer);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(initialHead.Tip.Id, reflogEntry.From);
+ Assert.Equal(commitSha, reflogEntry.To.Sha);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal(string.Format("checkout: moving from {0} to {1}", initialHead.Tip.Sha, commitPointer), reflogEntry.Message);
+ }
+ }
+
+ [Fact]
+ public void CheckoutBranchFromDetachedHead()
+ {
+ string path = CloneStandardTestRepo();
+ using (var repo = new Repository(path))
+ {
+ // Set the working directory to the current head
+ ResetAndCleanWorkingDirectory(repo);
+ Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ Branch initialHead = repo.Checkout("6dcf9bf");
+
+ Assert.True(repo.Info.IsHeadDetached);
+
+ Branch newHead = repo.Checkout(repo.Branches["master"]);
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(initialHead.Tip.Id, reflogEntry.From);
+ Assert.Equal(newHead.Tip.Id, reflogEntry.To);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal(string.Format("checkout: moving from {0} to {1}", initialHead.Tip.Sha, newHead.Name), reflogEntry.Message);
+ }
+ }
+
+
+ [Fact(Skip = "Current libgit2 revparse implementation only returns the object being pointed at, not the reference pointing at it.")]
+ public void CheckoutPreviousCheckedOutBranch()
+ {
+ string path = CloneStandardTestRepo();
+ using (var repo = new Repository(path))
+ {
+ // Set the working directory to the current head
+ ResetAndCleanWorkingDirectory(repo);
+ Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ Branch previousHead = repo.Checkout("i-do-numbers");
+ Branch newHead = repo.Checkout("diff-test-cases");
+
+ //Go back to previous branch checked out
+ repo.Checkout(@"@{-1}");
+
+ // Assert reflog entry is created
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.Equal(newHead.Tip.Id, reflogEntry.From);
+ Assert.Equal(previousHead.Tip.Id, reflogEntry.To);
+ Assert.NotNull(reflogEntry.Commiter.Email);
+ Assert.NotNull(reflogEntry.Commiter.Name);
+ Assert.Equal("checkout: moving from diff-test-cases to i-do-numbers", reflogEntry.Message);
+ }
+ }
+
+ [Fact]
+ public void CheckoutCurrentReference()
+ {
+ string path = CloneStandardTestRepo();
+ using (var repo = new Repository(path))
+ {
+ Branch master = repo.Branches["master"];
+ Assert.True(master.IsCurrentRepositoryHead);
+
+ ResetAndCleanWorkingDirectory(repo);
+ Assert.False(repo.Index.RetrieveStatus().IsDirty);
+
+ var reflogEntriesCount = repo.Refs.Log(repo.Refs.Head).Count();
+
+ // Checkout branch
+ repo.Checkout(master);
+
+ Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count());
+
+ // Checkout in detached mode
+ repo.Checkout(master.Tip.Sha);
+
+ Assert.True(repo.Info.IsHeadDetached);
+ var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
+ Assert.True(reflogEntry.To == reflogEntry.From);
+ Assert.Equal(string.Format("checkout: moving from master to {0}", master.Tip.Sha), reflogEntry.Message);
+
+ // Checkout detached "HEAD" => nothing should happen
+ reflogEntriesCount = repo.Refs.Log(repo.Refs.Head).Count();
+
+ repo.Checkout(repo.Head);
+
+ Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count());
+
+ // Checkout attached "HEAD" => nothing should happen
+ repo.Checkout("master");
+ reflogEntriesCount = repo.Refs.Log(repo.Refs.Head).Count();
+
+ repo.Checkout(repo.Head);
+
+ Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count());
+
+ repo.Checkout("HEAD");
+
+ Assert.Equal(reflogEntriesCount, repo.Refs.Log(repo.Refs.Head).Count());
+ }
+ }
+
[Fact]
public void CheckoutLowerCasedHeadThrows()
{
diff --git a/LibGit2Sharp/Configuration.cs b/LibGit2Sharp/Configuration.cs
index 1942ec8c..c47be960 100644
--- a/LibGit2Sharp/Configuration.cs
+++ b/LibGit2Sharp/Configuration.cs
@@ -288,17 +288,20 @@ namespace LibGit2Sharp
});
}
- internal Signature BuildSignatureFromGlobalConfiguration(DateTimeOffset now)
+ internal Signature BuildSignatureFromGlobalConfiguration(DateTimeOffset now, bool shouldThrowIfNotFound)
{
var name = Get<string>("user.name");
var email = Get<string>("user.email");
- if ((name == null) || (email == null))
+ if (shouldThrowIfNotFound && ((name == null) || (email == null)))
{
- throw new LibGit2SharpException("Can not find Name and Email settings of the current user in Git configuration.");
+ throw new LibGit2SharpException("Can not find Name or Email setting of the current user in Git configuration.");
}
- return new Signature(name.Value, email.Value, now);
+ return new Signature(
+ name != null ? name.Value : "unknown",
+ email != null ? email.Value : string.Format("{0}@{1}", Environment.UserName, Environment.UserDomainName),
+ now);
}
}
}
diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs
index 39cd5f1b..a14a61e3 100644
--- a/LibGit2Sharp/Repository.cs
+++ b/LibGit2Sharp/Repository.cs
@@ -586,11 +586,17 @@ namespace LibGit2Sharp
return Checkout(branch, checkoutOptions, onCheckoutProgress);
}
+ var previousHeadName = Info.IsHeadDetached ? Head.Tip.Sha : Head.Name;
+
Commit commit = LookupCommit(committishOrBranchSpec);
CheckoutTree(commit.Tree, checkoutOptions, onCheckoutProgress);
// Update HEAD.
Refs.UpdateTarget("HEAD", commit.Id.Sha);
+ if (committishOrBranchSpec != "HEAD")
+ {
+ LogCheckout(previousHeadName, commit.Id, committishOrBranchSpec);
+ }
return Head;
}
@@ -633,6 +639,9 @@ namespace LibGit2Sharp
"The tip of branch '{0}' is null. There's nothing to checkout.", branch.Name));
}
+ var branchIsCurrentRepositoryHead = branch.IsCurrentRepositoryHead;
+ var previousHeadName = Info.IsHeadDetached ? Head.Tip.Sha : Head.Name;
+
CheckoutTree(branch.Tip.Tree, checkoutOptions, onCheckoutProgress);
// Update HEAD.
@@ -647,9 +656,29 @@ namespace LibGit2Sharp
Refs.UpdateTarget("HEAD", branch.Tip.Id.Sha);
}
+ if (!branchIsCurrentRepositoryHead)
+ {
+ LogCheckout(previousHeadName, branch);
+ }
+
return Head;
}
+ private void LogCheckout(string previousHeadName, Branch newHead)
+ {
+ LogCheckout(previousHeadName, newHead.Tip.Id, newHead.Name);
+ }
+
+ private void LogCheckout(string previousHeadName, ObjectId newHeadTip, string newHeadSpec)
+ {
+ // Compute reflog message
+ string reflogMessage = string.Format("checkout: moving from {0} to {1}", previousHeadName, newHeadSpec);
+
+ // Log checkout
+ Signature author = Config.BuildSignatureFromGlobalConfiguration(DateTimeOffset.Now, false);
+ Refs.Log(Refs.Head).Append(newHeadTip, author, reflogMessage);
+ }
+
/// <summary>
/// Internal implementation of Checkout that expects the ID of the checkout target
/// to already be in the form of a canonical branch name or a commit ID.
diff --git a/LibGit2Sharp/RepositoryExtensions.cs b/LibGit2Sharp/RepositoryExtensions.cs
index 42919412..c653e9fe 100644
--- a/LibGit2Sharp/RepositoryExtensions.cs
+++ b/LibGit2Sharp/RepositoryExtensions.cs
@@ -173,7 +173,7 @@ namespace LibGit2Sharp
/// <returns>The generated <see cref = "LibGit2Sharp.Commit" />.</returns>
public static Commit Commit(this IRepository repository, string message, bool amendPreviousCommit = false)
{
- Signature author = repository.Config.BuildSignatureFromGlobalConfiguration(DateTimeOffset.Now);
+ Signature author = repository.Config.BuildSignatureFromGlobalConfiguration(DateTimeOffset.Now, true);
return repository.Commit(message, author, amendPreviousCommit);
}
@@ -191,7 +191,7 @@ namespace LibGit2Sharp
/// <returns>The generated <see cref = "LibGit2Sharp.Commit" />.</returns>
public static Commit Commit(this IRepository repository, string message, Signature author, bool amendPreviousCommit = false)
{
- Signature committer = repository.Config.BuildSignatureFromGlobalConfiguration(DateTimeOffset.Now);
+ Signature committer = repository.Config.BuildSignatureFromGlobalConfiguration(DateTimeOffset.Now, true);
return repository.Commit(message, author, committer, amendPreviousCommit);
}