зеркало из https://github.com/github/libgit2sharp.git
Replace usage of IntPtr holding references to references with ReferenceSafeHandle
This commit is contained in:
Родитель
6cd37c3cd5
Коммит
412010c931
|
@ -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))
|
||||
{
|
||||
reference = new SymbolicReference { CanonicalName = name, Target = null, TargetIdentifier = targetIdentifier };
|
||||
if (resolvedHandle == null)
|
||||
{
|
||||
reference = new SymbolicReference { CanonicalName = name, Target = null, TargetIdentifier = targetIdentifier };
|
||||
break;
|
||||
}
|
||||
|
||||
var targetRef = BuildFromPtr<DirectReference>(resolvedHandle, repo);
|
||||
reference = new SymbolicReference { CanonicalName = name, Target = targetRef, TargetIdentifier = targetIdentifier };
|
||||
break;
|
||||
}
|
||||
|
||||
Ensure.Success(res);
|
||||
|
||||
var targetRef = BuildFromPtrAndRelease<DirectReference>(resolveRef, 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);
|
||||
using (ReferenceSafeHandle handle = referenceCreator(name, allowOverwrite))
|
||||
{
|
||||
return Reference.BuildFromPtr<Reference>(handle, repo);
|
||||
}
|
||||
}
|
||||
|
||||
private int CreateSymbolicReference(string name, string target, bool allowOverwrite, out IntPtr reference)
|
||||
private ReferenceSafeHandle CreateSymbolicReference(string name, string target, bool allowOverwrite)
|
||||
{
|
||||
return NativeMethods.git_reference_create_symbolic(out reference, repo.Handle, name, target, allowOverwrite);
|
||||
ReferenceSafeHandle handle;
|
||||
Ensure.Success(NativeMethods.git_reference_create_symbolic(out handle, repo.Handle, name, target, allowOverwrite));
|
||||
return handle;
|
||||
}
|
||||
|
||||
private int CreateDirectReference(string name, ObjectId targetId, bool allowOverwrite, out IntPtr reference)
|
||||
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,10 +132,15 @@ namespace LibGit2Sharp
|
|||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
|
||||
IntPtr reference = RetrieveReferencePtr(name);
|
||||
|
||||
int res = NativeMethods.git_reference_delete(reference);
|
||||
Ensure.Success(res);
|
||||
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();
|
||||
|
||||
Ensure.Success(res);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -146,21 +155,23 @@ namespace LibGit2Sharp
|
|||
Ensure.ArgumentNotNullOrEmptyString(currentName, "currentName");
|
||||
Ensure.ArgumentNotNullOrEmptyString(newName, "newName");
|
||||
|
||||
IntPtr referencePtr = RetrieveReferencePtr(currentName);
|
||||
using (ReferenceSafeHandle handle = RetrieveReferencePtr(currentName))
|
||||
{
|
||||
int res = NativeMethods.git_reference_rename(handle, newName, allowOverwrite);
|
||||
Ensure.Success(res);
|
||||
|
||||
int res = NativeMethods.git_reference_rename(referencePtr, 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,49 +189,53 @@ namespace LibGit2Sharp
|
|||
return Create("HEAD", target, true);
|
||||
}
|
||||
|
||||
IntPtr reference = RetrieveReferencePtr(name);
|
||||
int res;
|
||||
|
||||
ObjectId id;
|
||||
bool isObjectIdentifier = ObjectId.TryParse(target, out id);
|
||||
|
||||
GitReferenceType type = NativeMethods.git_reference_type(reference);
|
||||
switch (type)
|
||||
using (ReferenceSafeHandle referencePtr = RetrieveReferencePtr(name))
|
||||
{
|
||||
case GitReferenceType.Oid:
|
||||
if (!isObjectIdentifier)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
int res;
|
||||
|
||||
case GitReferenceType.Symbolic:
|
||||
if (isObjectIdentifier)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
ObjectId id;
|
||||
bool isObjectIdentifier = ObjectId.TryParse(target, out id);
|
||||
|
||||
default:
|
||||
throw new LibGit2Exception(string.Format(CultureInfo.InvariantCulture, "Reference '{0}' has an unexpected type ('{1}').", name, Enum.GetName(typeof(GitReferenceType), type)));
|
||||
GitReferenceType type = NativeMethods.git_reference_type(referencePtr);
|
||||
switch (type)
|
||||
{
|
||||
case GitReferenceType.Oid:
|
||||
if (!isObjectIdentifier)
|
||||
{
|
||||
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(referencePtr, ref oid);
|
||||
break;
|
||||
|
||||
case GitReferenceType.Symbolic:
|
||||
if (isObjectIdentifier)
|
||||
{
|
||||
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(referencePtr, target);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LibGit2Exception(string.Format(CultureInfo.InvariantCulture, "Reference '{0}' has an unexpected type ('{1}').", name, Enum.GetName(typeof(GitReferenceType), type)));
|
||||
}
|
||||
|
||||
Ensure.Success(res);
|
||||
|
||||
return Reference.BuildFromPtr<Reference>(referencePtr, repo);
|
||||
}
|
||||
|
||||
Ensure.Success(res);
|
||||
|
||||
return Reference.BuildFromPtrAndRelease<Reference>(reference, 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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче