Skip to content

Commit 05d0118

Browse files
authored
Merge pull request #1897 from tyrielv/tyrielv/avoid-git-config-process
Replace some git config calls with libgit2
2 parents 8ccb768 + 80f5df6 commit 05d0118

File tree

15 files changed

+298
-59
lines changed

15 files changed

+298
-59
lines changed

GVFS/FastFetch/FastFetchLibGit2Repo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public FastFetchLibGit2Repo(ITracer tracer, string repoPath)
1818
public virtual bool TryCopyBlobToFile(string sha, IEnumerable<PathWithMode> destinations, out long bytesWritten)
1919
{
2020
IntPtr objHandle;
21-
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.SuccessCode)
21+
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.ResultCode.Success)
2222
{
2323
bytesWritten = 0;
2424
EventMetadata metadata = new EventMetadata();

GVFS/GVFS.Common/Enlistment.cs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,31 +109,5 @@ public virtual GitProcess CreateGitProcess()
109109
{
110110
return new GitProcess(this);
111111
}
112-
113-
public bool GetTrustPackIndexesConfig()
114-
{
115-
var gitProcess = this.CreateGitProcess();
116-
bool trustPackIndexes = true;
117-
if (gitProcess.TryGetFromConfig(GVFSConstants.GitConfig.TrustPackIndexes, forceOutsideEnlistment: false, out var valueString)
118-
&& bool.TryParse(valueString, out var trustPackIndexesConfig))
119-
{
120-
trustPackIndexes = trustPackIndexesConfig;
121-
}
122-
123-
return trustPackIndexes;
124-
}
125-
126-
public bool GetStatusHydrationConfig()
127-
{
128-
var gitProcess = this.CreateGitProcess();
129-
130-
if (gitProcess.TryGetFromConfig(GVFSConstants.GitConfig.ShowHydrationStatus, forceOutsideEnlistment: false, out var valueString)
131-
&& bool.TryParse(valueString, out var statusHydrationConfig))
132-
{
133-
return statusHydrationConfig;
134-
}
135-
136-
return GVFSConstants.GitConfig.ShowHydrationStatusDefault;
137-
}
138112
}
139113
}

GVFS/GVFS.Common/GVFSConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static class GitConfig
4242
/* Intended to be a temporary config to allow testing of distrusting pack indexes from cache server
4343
* before it is enabled by default. */
4444
public const string TrustPackIndexes = GVFSPrefix + "trust-pack-indexes";
45+
public const bool TrustPackIndexesDefault = true;
4546

4647
public const string ShowHydrationStatus = GVFSPrefix + "show-hydration-status";
4748
public const bool ShowHydrationStatusDefault = false;

GVFS/GVFS.Common/Git/GitObjects.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public virtual void DeleteTemporaryFiles()
153153
}
154154
}
155155

156-
public virtual bool TryDownloadPrefetchPacks(GitProcess gitProcess, long latestTimestamp, out List<string> packIndexes)
156+
public virtual bool TryDownloadPrefetchPacks(GitProcess gitProcess, long latestTimestamp, bool trustPackIndexes, out List<string> packIndexes)
157157
{
158158
EventMetadata metadata = CreateEventMetadata();
159159
metadata.Add("latestTimestamp", latestTimestamp);
@@ -166,7 +166,6 @@ public virtual bool TryDownloadPrefetchPacks(GitProcess gitProcess, long latestT
166166
* pack file and an index file that do not match.
167167
* Eventually we will make this the default, but it has a high performance cost for the first prefetch after
168168
* cloning a large repository, so it must be explicitly enabled for now. */
169-
bool trustPackIndexes = this.Enlistment.GetTrustPackIndexesConfig();
170169
metadata.Add("trustPackIndexes", trustPackIndexes);
171170

172171
long requestId = HttpRequestor.GetNewRequestId();

GVFS/GVFS.Common/Git/GitRepo.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public GVFSLock GVFSLock
5151
private set;
5252
}
5353

54+
internal LibGit2RepoInvoker LibGit2RepoInvoker
55+
{
56+
get { return this.libgit2RepoInvoker; }
57+
}
58+
5459
public void CloseActiveRepo()
5560
{
5661
this.libgit2RepoInvoker?.DisposeSharedRepo();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace GVFS.Common.Git
8+
{
9+
public class LibGit2Exception : Exception
10+
{
11+
public LibGit2Exception(string message) : base(message)
12+
{
13+
}
14+
15+
public LibGit2Exception(string message, Exception innerException) : base(message, innerException)
16+
{
17+
}
18+
}
19+
}

GVFS/GVFS.Common/Git/LibGit2Repo.cs

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public LibGit2Repo(ITracer tracer, string repoPath)
1717
Native.Init();
1818

1919
IntPtr repoHandle;
20-
if (Native.Repo.Open(out repoHandle, repoPath) != Native.SuccessCode)
20+
if (Native.Repo.Open(out repoHandle, repoPath) != Native.ResultCode.Success)
2121
{
2222
string reason = Native.GetLastError();
2323
string message = "Couldn't open repo at " + repoPath + ": " + reason;
@@ -45,7 +45,7 @@ protected LibGit2Repo()
4545
public Native.ObjectTypes? GetObjectType(string sha)
4646
{
4747
IntPtr objHandle;
48-
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.SuccessCode)
48+
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.ResultCode.Success)
4949
{
5050
return null;
5151
}
@@ -63,7 +63,7 @@ protected LibGit2Repo()
6363
public virtual string GetTreeSha(string commitish)
6464
{
6565
IntPtr objHandle;
66-
if (Native.RevParseSingle(out objHandle, this.RepoHandle, commitish) != Native.SuccessCode)
66+
if (Native.RevParseSingle(out objHandle, this.RepoHandle, commitish) != Native.ResultCode.Success)
6767
{
6868
return null;
6969
}
@@ -99,7 +99,7 @@ public virtual bool CommitAndRootTreeExists(string commitish, out string treeSha
9999
public virtual bool ObjectExists(string sha)
100100
{
101101
IntPtr objHandle;
102-
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.SuccessCode)
102+
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.ResultCode.Success)
103103
{
104104
return false;
105105
}
@@ -111,7 +111,7 @@ public virtual bool ObjectExists(string sha)
111111
public virtual bool TryCopyBlob(string sha, Action<Stream, long> writeAction)
112112
{
113113
IntPtr objHandle;
114-
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.SuccessCode)
114+
if (Native.RevParseSingle(out objHandle, this.RepoHandle, sha) != Native.ResultCode.Success)
115115
{
116116
return false;
117117
}
@@ -157,7 +157,7 @@ public virtual string[] GetMissingSubTrees(string treeSha)
157157
{
158158
List<string> missingSubtreesList = new List<string>();
159159
IntPtr treeHandle;
160-
if (Native.RevParseSingle(out treeHandle, this.RepoHandle, treeSha) != Native.SuccessCode
160+
if (Native.RevParseSingle(out treeHandle, this.RepoHandle, treeSha) != Native.ResultCode.Success
161161
|| treeHandle == IntPtr.Zero)
162162
{
163163
return Array.Empty<string>();
@@ -187,6 +187,68 @@ public virtual string[] GetMissingSubTrees(string treeSha)
187187
return missingSubtreesList.ToArray();
188188
}
189189

190+
/// <summary>
191+
/// Get a config value from the repo's git config.
192+
/// </summary>
193+
/// <param name="name">Name of the config entry</param>
194+
/// <returns>The config value, or null if not found.</returns>
195+
public virtual string GetConfigString(string name)
196+
{
197+
IntPtr configHandle;
198+
if (Native.Config.GetConfig(out configHandle, this.RepoHandle) != Native.ResultCode.Success)
199+
{
200+
throw new LibGit2Exception($"Failed to get config handle: {Native.GetLastError()}");
201+
}
202+
try
203+
{
204+
string value;
205+
Native.ResultCode resultCode = Native.Config.GetString(out value, configHandle, name);
206+
if (resultCode == Native.ResultCode.NotFound)
207+
{
208+
return null;
209+
}
210+
else if (resultCode != Native.ResultCode.Success)
211+
{
212+
throw new LibGit2Exception($"Failed to get config value for '{name}': {Native.GetLastError()}");
213+
}
214+
215+
return value;
216+
}
217+
finally
218+
{
219+
Native.Config.Free(configHandle);
220+
}
221+
}
222+
223+
public virtual bool? GetConfigBool(string name)
224+
{
225+
IntPtr configHandle;
226+
if (Native.Config.GetConfig(out configHandle, this.RepoHandle) != Native.ResultCode.Success)
227+
{
228+
throw new LibGit2Exception($"Failed to get config handle: {Native.GetLastError()}");
229+
}
230+
try
231+
{
232+
bool value;
233+
Native.ResultCode resultCode = Native.Config.GetBool(out value, configHandle, name);
234+
if (resultCode == Native.ResultCode.NotFound)
235+
{
236+
return null;
237+
}
238+
else if (resultCode != Native.ResultCode.Success)
239+
{
240+
throw new LibGit2Exception($"Failed to get config value for '{name}': {Native.GetLastError()}");
241+
}
242+
243+
return value;
244+
}
245+
finally
246+
{
247+
Native.Config.Free(configHandle);
248+
}
249+
250+
}
251+
190252
/// <summary>
191253
/// Determine if the given index of a tree is a subtree and if it is missing.
192254
/// If it is a missing subtree, return the SHA of the subtree.
@@ -242,7 +304,11 @@ protected virtual void Dispose(bool disposing)
242304

243305
public static class Native
244306
{
245-
public const uint SuccessCode = 0;
307+
public enum ResultCode : int
308+
{
309+
Success = 0,
310+
NotFound = -3,
311+
}
246312

247313
public const string Git2NativeLibName = GVFSConstants.LibGit2LibraryName;
248314

@@ -265,7 +331,7 @@ public static GitOid IntPtrToGitOid(IntPtr oidPtr)
265331
public static extern int Shutdown();
266332

267333
[DllImport(Git2NativeLibName, EntryPoint = "git_revparse_single")]
268-
public static extern uint RevParseSingle(out IntPtr objectHandle, IntPtr repoHandle, string oid);
334+
public static extern ResultCode RevParseSingle(out IntPtr objectHandle, IntPtr repoHandle, string oid);
269335

270336
public static string GetLastError()
271337
{
@@ -293,12 +359,27 @@ private struct GitError
293359
public static class Repo
294360
{
295361
[DllImport(Git2NativeLibName, EntryPoint = "git_repository_open")]
296-
public static extern uint Open(out IntPtr repoHandle, string path);
362+
public static extern ResultCode Open(out IntPtr repoHandle, string path);
297363

298364
[DllImport(Git2NativeLibName, EntryPoint = "git_repository_free")]
299365
public static extern void Free(IntPtr repoHandle);
300366
}
301367

368+
public static class Config
369+
{
370+
[DllImport(Git2NativeLibName, EntryPoint = "git_repository_config")]
371+
public static extern ResultCode GetConfig(out IntPtr configHandle, IntPtr repoHandle);
372+
373+
[DllImport(Git2NativeLibName, EntryPoint = "git_config_get_string")]
374+
public static extern ResultCode GetString(out string value, IntPtr configHandle, string name);
375+
376+
[DllImport(Git2NativeLibName, EntryPoint = "git_config_get_bool")]
377+
public static extern ResultCode GetBool(out bool value, IntPtr configHandle, string name);
378+
379+
[DllImport(Git2NativeLibName, EntryPoint = "git_config_free")]
380+
public static extern void Free(IntPtr configHandle);
381+
}
382+
302383
public static class Object
303384
{
304385
[DllImport(Git2NativeLibName, EntryPoint = "git_object_type")]

GVFS/GVFS.Common/Git/LibGit2RepoInvoker.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ public class LibGit2RepoInvoker : IDisposable
1313
private volatile int activeCallers;
1414
private LibGit2Repo sharedRepo;
1515

16+
public LibGit2RepoInvoker(ITracer tracer, string repoPath)
17+
: this(tracer, () => new LibGit2Repo(tracer, repoPath))
18+
{
19+
}
20+
1621
public LibGit2RepoInvoker(ITracer tracer, Func<LibGit2Repo> createRepo)
1722
{
1823
this.tracer = tracer;
@@ -82,6 +87,17 @@ public void InitializeSharedRepo()
8287
this.GetSharedRepo()?.ObjectExists("30380be3963a75e4a34e10726795d644659e1129");
8388
}
8489

90+
public bool GetConfigBoolOrDefault(string key, bool defaultValue)
91+
{
92+
bool? value = defaultValue;
93+
if (this.TryInvoke(repo => repo.GetConfigBool(key), out value))
94+
{
95+
return value ?? defaultValue;
96+
}
97+
98+
return defaultValue;
99+
}
100+
85101
private LibGit2Repo GetSharedRepo()
86102
{
87103
lock (this.sharedRepoLock)

GVFS/GVFS.Common/GitStatusCache.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ private void RebuildStatusCacheIfNeeded(bool ignoreBackoff)
341341

342342
private void UpdateHydrationSummary()
343343
{
344-
bool enabled = TEST_EnableHydrationSummaryOverride ?? this.context.Enlistment.GetStatusHydrationConfig();
344+
bool enabled = TEST_EnableHydrationSummaryOverride
345+
?? this.context.Repository.LibGit2RepoInvoker.GetConfigBoolOrDefault(GVFSConstants.GitConfig.ShowHydrationStatus, GVFSConstants.GitConfig.ShowHydrationStatusDefault);
345346
if (!enabled)
346347
{
347348
return;

GVFS/GVFS.Common/Maintenance/PrefetchStep.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ public bool TryPrefetchCommitsAndTrees(out string error, GitProcess gitProcess =
5656
return false;
5757
}
5858

59-
if (!this.GitObjects.TryDownloadPrefetchPacks(gitProcess, maxGoodTimeStamp, out packIndexes))
59+
var trustPackIndexes = this.Context.Repository.LibGit2RepoInvoker.GetConfigBoolOrDefault(GVFSConstants.GitConfig.TrustPackIndexes, GVFSConstants.GitConfig.TrustPackIndexesDefault);
60+
61+
if (!this.GitObjects.TryDownloadPrefetchPacks(gitProcess, maxGoodTimeStamp, trustPackIndexes, out packIndexes))
6062
{
6163
error = "Failed to download prefetch packs";
6264
return false;

0 commit comments

Comments
 (0)