Permalink
Browse files

Make Refs.Add() accept a revparse specification

  • Loading branch information...
1 parent 4819b80 commit 41364ef221d834378614a0b3b5c01ef7194d8cfe @nulltoken nulltoken committed Aug 27, 2012
Showing with 59 additions and 7 deletions.
  1. +18 −0 LibGit2Sharp.Tests/ReferenceFixture.cs
  2. +41 −7 LibGit2Sharp/ReferenceCollection.cs
@@ -34,6 +34,24 @@ public void CanAddADirectReference()
}
[Fact]
+ public void CanAddADirectReferenceFromRevParseSpec()
+ {
+ const string name = "refs/heads/extendedShaSyntaxRulz";
+
+ TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo();
+ using (var repo = new Repository(path.RepositoryPath))
+ {
+ var newRef = (DirectReference)repo.Refs.Add(name, "master^1^2");
+ Assert.NotNull(newRef);
+ Assert.Equal(name, newRef.CanonicalName);
+ Assert.NotNull(newRef.Target);
+ Assert.Equal("c47800c7266a2be04c571c04d5a6614691ea99bd", newRef.Target.Sha);
+ Assert.Equal(newRef.Target.Sha, newRef.TargetIdentifier);
+ Assert.NotNull(repo.Refs[name]);
+ }
+ }
+
+ [Fact]
public void CanAddASymbolicReference()
{
const string name = "refs/heads/unit_test";
@@ -65,28 +65,62 @@ IEnumerator IEnumerable.GetEnumerator()
#endregion
+ private enum RefState
+ {
+ Exists,
+ DoesNotExistButLooksValid,
+ DoesNotLookValid,
+ }
+
+ private RefState TryResolveReference(out Reference reference, string canonicalName)
+ {
+ try
+ {
+ //TODO: Maybe would it be better to rather rely on git_reference_normalize_name()
+ //This would be much more straightforward and less subject to fail for the wrong reason.
+
+ reference = repo.Refs[canonicalName];
+
+ if (reference != null)
+ {
+ return RefState.Exists;
+ }
+
+ return RefState.DoesNotExistButLooksValid;
+ }
+ catch (LibGit2SharpException)
+ {
+ reference = null;
+ return RefState.DoesNotLookValid;
+ }
+ }
+
/// <summary>
/// Creates a direct or symbolic reference with the specified name and target
/// </summary>
/// <param name = "name">The name of the reference to create.</param>
- /// <param name = "target">The target which can be either a sha or the canonical name of another reference.</param>
+ /// <param name = "canonicalRefNameOrObjectish">The target which can be either the canonical name of a branch reference or a revparse spec.</param>
/// <param name = "allowOverwrite">True to allow silent overwriting a potentially existing reference, false otherwise.</param>
/// <returns>A new <see cref = "Reference" />.</returns>
- public virtual Reference Add(string name, string target, bool allowOverwrite = false)
+ public virtual Reference Add(string name, string canonicalRefNameOrObjectish, bool allowOverwrite = false)
{
Ensure.ArgumentNotNullOrEmptyString(name, "name");
- Ensure.ArgumentNotNullOrEmptyString(target, "target");
+ Ensure.ArgumentNotNullOrEmptyString(canonicalRefNameOrObjectish, "canonicalRefNameOrObjectish");
- ObjectId id;
Func<string, bool, ReferenceSafeHandle> referenceCreator;
- if (ObjectId.TryParse(target, out id))
+ Reference reference;
+ RefState refState = TryResolveReference(out reference, canonicalRefNameOrObjectish);
+
+ var gitObject = repo.Lookup(canonicalRefNameOrObjectish, GitObjectType.Any, LookUpOptions.None);
+
+ if (refState == RefState.Exists || (refState == RefState.DoesNotExistButLooksValid && gitObject == null))
{
- referenceCreator = (n, o) => CreateDirectReference(n, id, o);
+ referenceCreator = (n, o) => CreateSymbolicReference(n, canonicalRefNameOrObjectish, o);
}
else
{
- referenceCreator = (n, o) => CreateSymbolicReference(n, target, o);
+ referenceCreator = (n, o) => CreateDirectReference(n, gitObject.Id, o);
}
using (ReferenceSafeHandle handle = referenceCreator(name, allowOverwrite))

0 comments on commit 41364ef

Please sign in to comment.