Skip to content

Commit b8b946b

Browse files
committed
create a RepositorySafeHandle to ensure that handles are always released.
1 parent 99acd3c commit b8b946b

File tree

8 files changed

+51
-52
lines changed

8 files changed

+51
-52
lines changed

LibGit2Sharp/Commit.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public List<Commit> Parents
5656
{
5757
var oid = Id.Oid;
5858
IntPtr obj;
59-
var res = NativeMethods.git_object_lookup(out obj, repo.RepoPtr, ref oid, GitObjectType.Commit);
59+
var res = NativeMethods.git_object_lookup(out obj, repo.Handle, ref oid, GitObjectType.Commit);
6060
Ensure.Success(res);
6161

6262
try

LibGit2Sharp/CommitCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public class CommitEnumerator : IEnumerator<Commit>
119119
public CommitEnumerator(Repository repo)
120120
{
121121
this.repo = repo;
122-
int res = NativeMethods.git_revwalk_new(out walker, repo.RepoPtr);
122+
int res = NativeMethods.git_revwalk_new(out walker, repo.Handle);
123123
Ensure.Success(res);
124124
}
125125

LibGit2Sharp/LibGit2Sharp.Net35.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<Compile Include="Repository.cs">
7171
<SubType>Code</SubType>
7272
</Compile>
73+
<Compile Include="RepositorySafeHandle.cs" />
7374
<Compile Include="Signature.cs" />
7475
<Compile Include="SymbolicReference.cs" />
7576
<Compile Include="Tag.cs" />

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<Compile Include="Reference.cs" />
6969
<Compile Include="ReferenceCollection.cs" />
7070
<Compile Include="Repository.cs" />
71+
<Compile Include="RepositorySafeHandle.cs" />
7172
<Compile Include="Signature.cs" />
7273
<Compile Include="SymbolicReference.cs" />
7374
<Compile Include="Tag.cs" />
@@ -86,9 +87,7 @@
8687
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
8788
</Content>
8889
</ItemGroup>
89-
<ItemGroup>
90-
<Folder Include="Core\" />
91-
</ItemGroup>
90+
<ItemGroup />
9291
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
9392
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
9493
<PropertyGroup>

LibGit2Sharp/NativeMethods.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal unsafe class UnSafeNativeMethods
88
private const string libgit2 = "git2.dll";
99

1010
[DllImport(libgit2)]
11-
public static extern int git_reference_listall(git_strarray* array, IntPtr repo, GitReferenceType flags);
11+
public static extern int git_reference_listall(git_strarray* array, RepositorySafeHandle repo, GitReferenceType flags);
1212

1313
[DllImport(libgit2)]
1414
public static extern void git_strarray_free(git_strarray* array);
@@ -35,7 +35,7 @@ internal class NativeMethods
3535
public static extern IntPtr git_commit_committer(IntPtr commit);
3636

3737
[DllImport(libgit2, SetLastError = true)]
38-
public static extern int git_commit_create_o(out GitOid oid, IntPtr repo, string updateRef, IntPtr author, IntPtr committer, string message, IntPtr tree, int parentCount, IntPtr parents);
38+
public static extern int git_commit_create_o(out GitOid oid, RepositorySafeHandle repo, string updateRef, IntPtr author, IntPtr committer, string message, IntPtr tree, int parentCount, IntPtr parents);
3939

4040
[DllImport(libgit2, SetLastError = true)]
4141
[return: MarshalAs(UnmanagedType.AnsiBStr)]
@@ -61,7 +61,7 @@ internal class NativeMethods
6161
public static extern IntPtr git_object_id(IntPtr obj);
6262

6363
[DllImport(libgit2, SetLastError = true)]
64-
public static extern int git_object_lookup(out IntPtr obj, IntPtr repo, ref GitOid id, GitObjectType type);
64+
public static extern int git_object_lookup(out IntPtr obj, RepositorySafeHandle repo, ref GitOid id, GitObjectType type);
6565

6666
[DllImport(libgit2, SetLastError = true)]
6767
public static extern GitObjectType git_object_type(IntPtr obj);
@@ -82,16 +82,16 @@ internal class NativeMethods
8282
public static extern int git_oid_mkstr(out GitOid oid, string str);
8383

8484
[DllImport(libgit2, SetLastError = true)]
85-
public static extern int git_reference_create_oid(out IntPtr reference, IntPtr repo, string name, ref GitOid oid);
85+
public static extern int git_reference_create_oid(out IntPtr reference, RepositorySafeHandle repo, string name, ref GitOid oid);
8686

8787
[DllImport(libgit2, SetLastError = true)]
88-
public static extern int git_reference_create_symbolic(out IntPtr reference, IntPtr repo, string name, string target);
88+
public static extern int git_reference_create_symbolic(out IntPtr reference, RepositorySafeHandle repo, string name, string target);
8989

9090
[DllImport(libgit2, SetLastError = true)]
9191
public static extern int git_reference_delete(IntPtr reference);
9292

9393
[DllImport(libgit2)]
94-
public static extern int git_reference_lookup(out IntPtr reference, IntPtr repo, string name);
94+
public static extern int git_reference_lookup(out IntPtr reference, RepositorySafeHandle repo, string name);
9595

9696
[DllImport(libgit2)]
9797
[return: MarshalAs(UnmanagedType.AnsiBStr)]
@@ -111,22 +111,22 @@ internal class NativeMethods
111111
public static extern GitReferenceType git_reference_type(IntPtr reference);
112112

113113
[DllImport(libgit2, SetLastError = true)]
114-
public static extern IntPtr git_repository_database(IntPtr repository);
114+
public static extern IntPtr git_repository_database(RepositorySafeHandle repository);
115115

116116
[DllImport(libgit2, SetLastError = true)]
117117
public static extern void git_repository_free(IntPtr repository);
118118

119119
[DllImport(libgit2, SetLastError = true)]
120-
public static extern int git_repository_init(out IntPtr repository, string path, bool isBare);
120+
public static extern int git_repository_init(out RepositorySafeHandle repository, string path, bool isBare);
121121

122122
[DllImport(libgit2, SetLastError = true)]
123-
public static extern int git_repository_open(out IntPtr repository, string path);
123+
public static extern int git_repository_open(out RepositorySafeHandle repository, string path);
124124

125125
[DllImport(libgit2)]
126126
public static extern void git_revwalk_free(IntPtr walker);
127127

128128
[DllImport(libgit2)]
129-
public static extern int git_revwalk_new(out IntPtr walker, IntPtr repo);
129+
public static extern int git_revwalk_new(out IntPtr walker, RepositorySafeHandle repo);
130130

131131
[DllImport(libgit2)]
132132
public static extern int git_revwalk_next(out GitOid oid, IntPtr walker);

LibGit2Sharp/ReferenceCollection.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public Reference this[string name]
3737

3838
public IEnumerator<Reference> GetEnumerator()
3939
{
40-
return GitReferenceHelper.List(this, repo.RepoPtr, GitReferenceType.ListAll).GetEnumerator();
40+
return GitReferenceHelper.List(this, repo.Handle, GitReferenceType.ListAll).GetEnumerator();
4141
}
4242

4343
IEnumerator IEnumerable.GetEnumerator()
@@ -65,7 +65,7 @@ public Reference Create(string name, string target)
6565
}
6666

6767
IntPtr reference;
68-
var res = NativeMethods.git_reference_create_symbolic(out reference, repo.RepoPtr, name, target);
68+
var res = NativeMethods.git_reference_create_symbolic(out reference, repo.Handle, name, target);
6969
Ensure.Success(res);
7070

7171
return Reference.CreateFromPtr(reference, repo);
@@ -83,7 +83,7 @@ public Reference Create(string name, ObjectId target)
8383

8484
var oid = target.Oid;
8585
IntPtr reference;
86-
var res = NativeMethods.git_reference_create_oid(out reference, repo.RepoPtr, name, ref oid);
86+
var res = NativeMethods.git_reference_create_oid(out reference, repo.Handle, name, ref oid);
8787
Ensure.Success(res);
8888

8989
return Reference.CreateFromPtr(reference, repo);
@@ -108,7 +108,7 @@ public Reference Resolve(string name)
108108
Ensure.ArgumentNotNullOrEmptyString(name, "name");
109109

110110
IntPtr reference;
111-
var res = NativeMethods.git_reference_lookup(out reference, repo.RepoPtr, name);
111+
var res = NativeMethods.git_reference_lookup(out reference, repo.Handle, name);
112112
Ensure.Success(res);
113113

114114
return Reference.CreateFromPtr(reference, repo);
@@ -118,7 +118,7 @@ public Reference Resolve(string name)
118118

119119
private static unsafe class GitReferenceHelper
120120
{
121-
public static List<Reference> List(ReferenceCollection owner, IntPtr repo, GitReferenceType types)
121+
public static List<Reference> List(ReferenceCollection owner, RepositorySafeHandle repo, GitReferenceType types)
122122
{
123123
UnSafeNativeMethods.git_strarray strArray;
124124
var res = UnSafeNativeMethods.git_reference_listall(&strArray, repo, types);

LibGit2Sharp/Repository.cs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class Repository : IDisposable
1313
private readonly BranchCollection branches;
1414
private readonly CommitCollection commits;
1515
private readonly ReferenceCollection refs;
16-
private readonly IntPtr repo = IntPtr.Zero;
16+
private readonly RepositorySafeHandle handle;
1717

1818
private bool disposed;
1919

@@ -37,9 +37,12 @@ public Repository(string path)
3737
Path = path;
3838
PosixPath = path.Replace(System.IO.Path.DirectorySeparatorChar, posixDirectorySeparatorChar);
3939

40-
var res = NativeMethods.git_repository_open(out repo, PosixPath);
40+
RepositorySafeHandle tempHandle;
41+
var res = NativeMethods.git_repository_open(out tempHandle, PosixPath);
4142
Ensure.Success(res);
4243

44+
handle = tempHandle;
45+
4346
commits = new CommitCollection(this);
4447
refs = new ReferenceCollection(this);
4548
branches = new BranchCollection(this);
@@ -57,17 +60,17 @@ public static string Init(string path, bool bare = false)
5760

5861
var posixPath = path.Replace(System.IO.Path.DirectorySeparatorChar, posixDirectorySeparatorChar);
5962

60-
IntPtr repo;
63+
RepositorySafeHandle repo;
6164
var res = NativeMethods.git_repository_init(out repo, posixPath, bare);
6265
Ensure.Success(res);
63-
NativeMethods.git_repository_free(repo);
66+
repo.Dispose();
6467

6568
return path;
6669
}
6770

68-
internal IntPtr RepoPtr
71+
internal RepositorySafeHandle Handle
6972
{
70-
get { return repo; }
73+
get { return handle; }
7174
}
7275

7376
/// <summary>
@@ -115,35 +118,14 @@ public void Dispose()
115118

116119
#endregion
117120

118-
private void Dispose(bool disposing)
121+
protected virtual void Dispose(bool disposing)
119122
{
120-
// Check to see if Dispose has already been called.
121-
if (!disposed)
123+
if(handle != null && !handle.IsInvalid)
122124
{
123-
// If disposing equals true, dispose all managed
124-
// and unmanaged resources.
125-
if (disposing)
126-
{
127-
// Dispose managed resources.
128-
}
129-
130-
// Call the appropriate methods to clean up
131-
// unmanaged resources here.
132-
NativeMethods.git_repository_free(repo);
133-
134-
// Note disposing has been done.
135-
disposed = true;
125+
handle.Dispose();
136126
}
137127
}
138128

139-
~Repository()
140-
{
141-
// Do not re-create Dispose clean-up code here.
142-
// Calling Dispose(false) is optimal in terms of
143-
// readability and maintainability.
144-
Dispose(false);
145-
}
146-
147129
/// <summary>
148130
/// Tells if the specified <see cref = "GitOid" /> exists in the repository.
149131
///
@@ -156,7 +138,7 @@ public bool HasObject(ObjectId id)
156138
{
157139
Ensure.ArgumentNotNull(id, "id");
158140

159-
var odb = NativeMethods.git_repository_database(repo);
141+
var odb = NativeMethods.git_repository_database(handle);
160142
var oid = id.Oid;
161143
return NativeMethods.git_odb_exists(odb, ref oid);
162144
}
@@ -183,7 +165,7 @@ private GitObject Lookup(ObjectId id, GitObjectType type = GitObjectType.Any, bo
183165

184166
var oid = id.Oid;
185167
IntPtr obj;
186-
var res = NativeMethods.git_object_lookup(out obj, repo, ref oid, type);
168+
var res = NativeMethods.git_object_lookup(out obj, handle, ref oid, type);
187169
if (res == (int)GitErrorCode.GIT_ENOTFOUND)
188170
{
189171
if (throwIfNotFound)

LibGit2Sharp/RepositorySafeHandle.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.Win32.SafeHandles;
2+
3+
namespace LibGit2Sharp
4+
{
5+
public class RepositorySafeHandle : SafeHandleZeroOrMinusOneIsInvalid
6+
{
7+
public RepositorySafeHandle() : base(true)
8+
{
9+
}
10+
11+
protected override bool ReleaseHandle()
12+
{
13+
NativeMethods.git_repository_free(handle);
14+
return true;
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)