Add Configuration.Find(regexp)

This commit is contained in:
Keith Dahlby 2013-11-19 16:19:41 -06:00
Родитель 123bd64e59
Коммит 3cf04dd724
6 изменённых файлов: 107 добавлений и 7 удалений

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

@ -226,6 +226,35 @@ namespace LibGit2Sharp.Tests
}
}
[Fact]
public void CanFindInLocalConfig()
{
using (var repo = new Repository(StandardTestRepoPath))
{
var matches = repo.Config.Find("unit");
Assert.NotNull(matches);
Assert.Equal(new[] { "unittests.intsetting", "unittests.longsetting" },
matches.Select(m => m.Key).ToArray());
}
}
[Fact]
public void CanFindInGlobalConfig()
{
string configPath = CreateConfigurationWithDummyUser(Constants.Signature);
var options = new RepositoryOptions { GlobalConfigurationLocation = configPath };
using (var repo = new Repository(StandardTestRepoPath, options))
{
var matches = repo.Config.Find(@"\.name", ConfigurationLevel.Global);
Assert.NotNull(matches);
Assert.Equal(new[] { "user.name" },
matches.Select(m => m.Key).ToArray());
}
}
[Fact]
public void CanSetBooleanValue()
{

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

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
@ -235,6 +236,23 @@ namespace LibGit2Sharp
}
}
/// <summary>
/// Find configuration entries matching <paramref name="regexp"/>.
/// </summary>
/// <param name="regexp">A regular expression.</param>
/// <param name="level">The configuration file into which the key should be searched for.</param>
/// <returns>Matching entries.</returns>
public virtual IEnumerable<ConfigurationEntry<string>> Find(string regexp,
ConfigurationLevel level = ConfigurationLevel.Local)
{
Ensure.ArgumentNotNullOrEmptyString(regexp, "regexp");
using (ConfigurationSafeHandle h = RetrieveConfigurationHandle(level, true))
{
return Proxy.git_config_iterator_glob(h, regexp, BuildConfigEntry).ToList();
}
}
private ConfigurationSafeHandle RetrieveConfigurationHandle(ConfigurationLevel level, bool throwIfStoreHasNotBeenFound)
{
ConfigurationSafeHandle handle = null;
@ -278,14 +296,16 @@ namespace LibGit2Sharp
private IEnumerable<ConfigurationEntry<string>> BuildConfigEntries()
{
return Proxy.git_config_foreach(configHandle, entryPtr =>
{
var entry = (GitConfigEntry)Marshal.PtrToStructure(entryPtr, typeof(GitConfigEntry));
return Proxy.git_config_foreach(configHandle, BuildConfigEntry);
}
return new ConfigurationEntry<string>(LaxUtf8Marshaler.FromNative(entry.namePtr),
LaxUtf8Marshaler.FromNative(entry.valuePtr),
(ConfigurationLevel)entry.level);
});
private static ConfigurationEntry<string> BuildConfigEntry(IntPtr entryPtr)
{
var entry = (GitConfigEntry)Marshal.PtrToStructure(entryPtr, typeof(GitConfigEntry));
return new ConfigurationEntry<string>(LaxUtf8Marshaler.FromNative(entry.namePtr),
LaxUtf8Marshaler.FromNative(entry.valuePtr),
(ConfigurationLevel)entry.level);
}
internal Signature BuildSignatureFromGlobalConfiguration(DateTimeOffset now, bool shouldThrowIfNotFound)

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

@ -0,0 +1,11 @@
namespace LibGit2Sharp.Core.Handles
{
internal class ConfigurationIteratorSafeHandle : SafeHandleBase
{
protected override bool ReleaseHandleImpl()
{
Proxy.git_config_iterator_free(handle);
return true;
}
}
}

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

@ -343,6 +343,20 @@ namespace LibGit2Sharp.Core
config_foreach_callback callback,
IntPtr payload);
[DllImport(libgit2)]
internal static extern int git_config_iterator_glob_new(
out ConfigurationIteratorSafeHandle iter,
ConfigurationSafeHandle cfg,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string regexp);
[DllImport(libgit2)]
internal static extern int git_config_next(
out IntPtr entry,
ConfigurationIteratorSafeHandle iter);
[DllImport(libgit2)]
internal static extern void git_config_iterator_free(IntPtr iter);
// Ordinarily we would decorate the `url` parameter with the StrictUtf8Marshaler like we do everywhere
// else, but apparently doing a native->managed callback with the 64-bit version of CLR 2.0 can
// sometimes vomit when using a custom IMarshaler. So yeah, don't do that. If you need the url,

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

@ -530,6 +530,31 @@ namespace LibGit2Sharp.Core
return git_foreach(resultSelector, c => NativeMethods.git_config_foreach(config, (e, p) => c(e, p), IntPtr.Zero));
}
public static IEnumerable<ConfigurationEntry<string>> git_config_iterator_glob(
ConfigurationSafeHandle config,
string regexp,
Func<IntPtr, ConfigurationEntry<string>> resultSelector)
{
return git_iterator(
(out ConfigurationIteratorSafeHandle iter) =>
NativeMethods.git_config_iterator_glob_new(out iter, config, regexp),
(ConfigurationIteratorSafeHandle iter, out SafeHandleBase handle, out int res) =>
{
handle = null;
IntPtr entry;
res = NativeMethods.git_config_next(out entry, iter);
return new { EntryPtr = entry };
},
(handle, payload) => resultSelector(payload.EntryPtr)
);
}
public static void git_config_iterator_free(IntPtr iter)
{
NativeMethods.git_config_iterator_free(iter);
}
#endregion
#region git_diff_

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

@ -75,6 +75,7 @@
<Compile Include="RefSpecCollection.cs" />
<Compile Include="Core\EncodingMarshaler.cs" />
<Compile Include="Core\Handles\BranchIteratorSafeHandle.cs" />
<Compile Include="Core\Handles\ConfigurationIteratorSafeHandle.cs" />
<Compile Include="Core\PushTransferProgressCallbacks.cs" />
<Compile Include="Core\PackbuilderCallbacks.cs" />
<Compile Include="PushOptions.cs" />