Replace usage of IntPtr holding references to references with ReferenceSafeHandle

This commit is contained in:
nulltoken 2012-03-29 15:51:43 +02:00
Родитель 6cd37c3cd5
Коммит 412010c931
3 изменённых файлов: 112 добавлений и 95 удалений

Просмотреть файл

@ -224,7 +224,7 @@ namespace LibGit2Sharp.Core
[DllImport(libgit2)]
public static extern int git_reference_create_oid(
out IntPtr reference,
out ReferenceSafeHandle reference,
RepositorySafeHandle repo,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name,
ref GitOid oid,
@ -232,54 +232,54 @@ namespace LibGit2Sharp.Core
[DllImport(libgit2)]
public static extern int git_reference_create_symbolic(
out IntPtr reference,
out ReferenceSafeHandle reference,
RepositorySafeHandle repo,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string target,
[MarshalAs(UnmanagedType.Bool)] bool force);
[DllImport(libgit2)]
public static extern int git_reference_delete(IntPtr reference);
public static extern int git_reference_delete(ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern void git_reference_free(IntPtr reference);
[DllImport(libgit2)]
public static extern int git_reference_lookup(
out IntPtr reference,
out ReferenceSafeHandle reference,
RepositorySafeHandle repo,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name);
[DllImport(libgit2)]
[return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]
public static extern string git_reference_name(IntPtr reference);
public static extern string git_reference_name(ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern OidSafeHandle git_reference_oid(IntPtr reference);
public static extern OidSafeHandle git_reference_oid(ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern int git_reference_rename(
IntPtr reference,
ReferenceSafeHandle reference,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string newName,
[MarshalAs(UnmanagedType.Bool)] bool force);
[DllImport(libgit2)]
public static extern int git_reference_resolve(out IntPtr resolvedReference, IntPtr reference);
public static extern int git_reference_resolve(out ReferenceSafeHandle resolvedReference, ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern int git_reference_set_oid(IntPtr reference, ref GitOid id);
public static extern int git_reference_set_oid(ReferenceSafeHandle reference, ref GitOid id);
[DllImport(libgit2)]
public static extern int git_reference_set_target(
IntPtr reference,
ReferenceSafeHandle reference,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string target);
[DllImport(libgit2)]
[return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]
public static extern string git_reference_target(IntPtr reference);
public static extern string git_reference_target(ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern GitReferenceType git_reference_type(IntPtr reference);
public static extern GitReferenceType git_reference_type(ReferenceSafeHandle reference);
[DllImport(libgit2)]
public static extern void git_remote_free(IntPtr remote);

Просмотреть файл

@ -19,46 +19,33 @@ namespace LibGit2Sharp
/// </summary>
public string CanonicalName { get; protected set; }
internal static T BuildFromPtrAndRelease<T>(IntPtr ptr, Repository repo) where T : Reference
internal static T BuildFromPtr<T>(ReferenceSafeHandle handle, Repository repo) where T : Reference
{
var reference = BuildFromPtr<T>(ptr, repo);
NativeMethods.git_reference_free(ptr);
return reference;
}
private static T BuildFromPtr<T>(IntPtr ptr, Repository repo) where T : Reference
{
if (ptr == IntPtr.Zero)
{
return default(T);
}
string name = NativeMethods.git_reference_name(ptr);
GitReferenceType type = NativeMethods.git_reference_type(ptr);
GitReferenceType type = NativeMethods.git_reference_type(handle);
string name = NativeMethods.git_reference_name(handle);
Reference reference;
switch (type)
{
case GitReferenceType.Symbolic:
IntPtr resolveRef;
var targetIdentifier = NativeMethods.git_reference_target(ptr);
int res = NativeMethods.git_reference_resolve(out resolveRef, ptr);
string targetIdentifier = NativeMethods.git_reference_target(handle);
if (res == (int)GitErrorCode.GIT_ENOTFOUND)
using (ReferenceSafeHandle resolvedHandle = PeelToDirectReference(handle))
{
if (resolvedHandle == null)
{
reference = new SymbolicReference { CanonicalName = name, Target = null, TargetIdentifier = targetIdentifier };
break;
}
Ensure.Success(res);
var targetRef = BuildFromPtrAndRelease<DirectReference>(resolveRef, repo);
var targetRef = BuildFromPtr<DirectReference>(resolvedHandle, repo);
reference = new SymbolicReference { CanonicalName = name, Target = targetRef, TargetIdentifier = targetIdentifier };
break;
}
case GitReferenceType.Oid:
ObjectId targetOid = NativeMethods.git_reference_oid(ptr).MarshalAsObjectId();
ObjectId targetOid = NativeMethods.git_reference_oid(handle).MarshalAsObjectId();
var targetBuilder = new Lazy<GitObject>(() => repo.Lookup(targetOid));
reference = new DirectReference(targetBuilder) { CanonicalName = name, TargetIdentifier = targetOid.Sha };
@ -71,6 +58,21 @@ namespace LibGit2Sharp
return reference as T;
}
private static ReferenceSafeHandle PeelToDirectReference(ReferenceSafeHandle handle)
{
ReferenceSafeHandle resolvedHandle;
int res = NativeMethods.git_reference_resolve(out resolvedHandle, handle);
if (res == (int)GitErrorCode.GIT_ENOTFOUND)
{
return null;
}
Ensure.Success(res);
return resolvedHandle;
}
/// <summary>
/// Recursively peels the target of the reference until a direct reference is encountered.
/// </summary>

Просмотреть файл

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
namespace LibGit2Sharp
{
@ -71,36 +72,39 @@ namespace LibGit2Sharp
Ensure.ArgumentNotNullOrEmptyString(target, "target");
ObjectId id;
IntPtr reference;
int res;
Func<string, bool, ReferenceSafeHandle> referenceCreator;
if (ObjectId.TryParse(target, out id))
{
res = CreateDirectReference(name, id, allowOverwrite, out reference);
referenceCreator = (n, o) => CreateDirectReference(n, id, o);
}
else
{
res = CreateSymbolicReference(name, target, allowOverwrite, out reference);
referenceCreator = (n, o) => CreateSymbolicReference(n, target, o);
}
Ensure.Success(res);
return Reference.BuildFromPtrAndRelease<Reference>(reference, repo);
}
private int CreateSymbolicReference(string name, string target, bool allowOverwrite, out IntPtr reference)
using (ReferenceSafeHandle handle = referenceCreator(name, allowOverwrite))
{
return NativeMethods.git_reference_create_symbolic(out reference, repo.Handle, name, target, allowOverwrite);
return Reference.BuildFromPtr<Reference>(handle, repo);
}
}
private int CreateDirectReference(string name, ObjectId targetId, bool allowOverwrite, out IntPtr reference)
private ReferenceSafeHandle CreateSymbolicReference(string name, string target, bool allowOverwrite)
{
ReferenceSafeHandle handle;
Ensure.Success(NativeMethods.git_reference_create_symbolic(out handle, repo.Handle, name, target, allowOverwrite));
return handle;
}
private ReferenceSafeHandle CreateDirectReference(string name, ObjectId targetId, bool allowOverwrite)
{
targetId = Unabbreviate(targetId);
GitOid oid = targetId.Oid;
return NativeMethods.git_reference_create_oid(out reference, repo.Handle, name, ref oid, allowOverwrite);
ReferenceSafeHandle handle;
Ensure.Success(NativeMethods.git_reference_create_oid(out handle, repo.Handle, name, ref oid, allowOverwrite));
return handle;
}
private ObjectId Unabbreviate(ObjectId targetId)
@ -128,11 +132,16 @@ namespace LibGit2Sharp
{
Ensure.ArgumentNotNullOrEmptyString(name, "name");
IntPtr reference = RetrieveReferencePtr(name);
using (ReferenceSafeHandle handle = RetrieveReferencePtr(name))
{
int res = NativeMethods.git_reference_delete(handle);
//TODO Make git_reference_delete() set the ref pointer to NULL and remove the following line
handle.SetHandleAsInvalid();
int res = NativeMethods.git_reference_delete(reference);
Ensure.Success(res);
}
}
/// <summary>
/// Rename an existing reference with a new name
@ -146,21 +155,23 @@ namespace LibGit2Sharp
Ensure.ArgumentNotNullOrEmptyString(currentName, "currentName");
Ensure.ArgumentNotNullOrEmptyString(newName, "newName");
IntPtr referencePtr = RetrieveReferencePtr(currentName);
int res = NativeMethods.git_reference_rename(referencePtr, newName, allowOverwrite);
using (ReferenceSafeHandle handle = RetrieveReferencePtr(currentName))
{
int res = NativeMethods.git_reference_rename(handle, newName, allowOverwrite);
Ensure.Success(res);
return Reference.BuildFromPtrAndRelease<Reference>(referencePtr, repo);
return Reference.BuildFromPtr<Reference>(handle, repo);
}
}
internal T Resolve<T>(string name) where T : Reference
{
Ensure.ArgumentNotNullOrEmptyString(name, "name");
IntPtr reference = RetrieveReferencePtr(name, false);
return Reference.BuildFromPtrAndRelease<T>(reference, repo);
using (ReferenceSafeHandle referencePtr = RetrieveReferencePtr(name, false))
{
return referencePtr == null ? null : Reference.BuildFromPtr<T>(referencePtr, repo);
}
}
/// <summary>
@ -178,13 +189,14 @@ namespace LibGit2Sharp
return Create("HEAD", target, true);
}
IntPtr reference = RetrieveReferencePtr(name);
using (ReferenceSafeHandle referencePtr = RetrieveReferencePtr(name))
{
int res;
ObjectId id;
bool isObjectIdentifier = ObjectId.TryParse(target, out id);
GitReferenceType type = NativeMethods.git_reference_type(reference);
GitReferenceType type = NativeMethods.git_reference_type(referencePtr);
switch (type)
{
case GitReferenceType.Oid:
@ -192,8 +204,9 @@ namespace LibGit2Sharp
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The reference specified by {0} is an Oid reference, you must provide a sha as the target.", name), "target");
}
GitOid oid = id.Oid;
res = NativeMethods.git_reference_set_oid(reference, ref oid);
res = NativeMethods.git_reference_set_oid(referencePtr, ref oid);
break;
case GitReferenceType.Symbolic:
@ -201,7 +214,8 @@ namespace LibGit2Sharp
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The reference specified by {0} is a Symbolic reference, you must provide a reference canonical name as the target.", name), "target");
}
res = NativeMethods.git_reference_set_target(reference, target);
res = NativeMethods.git_reference_set_target(referencePtr, target);
break;
default:
@ -210,17 +224,18 @@ namespace LibGit2Sharp
Ensure.Success(res);
return Reference.BuildFromPtrAndRelease<Reference>(reference, repo);
return Reference.BuildFromPtr<Reference>(referencePtr, repo);
}
}
private IntPtr RetrieveReferencePtr(string referenceName, bool shouldThrowIfNotFound = true)
private ReferenceSafeHandle RetrieveReferencePtr(string referenceName, bool shouldThrowIfNotFound = true)
{
IntPtr reference;
ReferenceSafeHandle reference;
int res = NativeMethods.git_reference_lookup(out reference, repo.Handle, referenceName);
if (!shouldThrowIfNotFound && res == (int)GitErrorCode.GIT_ENOTFOUND)
{
return IntPtr.Zero;
return null;
}
Ensure.Success(res);