From 822b7c0d2c96052cf3c78c9dc351d127f2e8dc91 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 22 Sep 2023 12:18:29 +0200 Subject: [PATCH 1/4] Use LibraryImport instead of DllImport --- .../Internal/Everything64Api.cs | 55 ++++++++++--------- .../RepoM.Plugin.EverythingFileSearch.csproj | 1 + 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs index a7a4688c..a1cdf7a4 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs +++ b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs @@ -8,37 +8,12 @@ namespace RepoM.Plugin.EverythingFileSearch.Internal; /// Wrapper for Everything. /// See for the SDK. -internal static class Everything64Api +internal static partial class Everything64Api { private static readonly object _lock = new(); private const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001; private const int EVERYTHING_REQUEST_PATH = 0x00000002; - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern void Everything_SetSearch(string lpSearchString); - - [DllImport("Everything64.dll")] - public static extern void Everything_SetMatchCase(bool bEnable); - - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern bool Everything_Query(bool bWait); - - [DllImport("Everything64.dll")] - public static extern uint Everything_GetNumResults(); - - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); - - [DllImport("Everything64.dll")] - public static extern void Everything_CleanUp(); - - [DllImport("Everything64.dll")] - public static extern uint Everything_GetMajorVersion(); - - // Everything 1.4 - [DllImport("Everything64.dll")] - public static extern void Everything_SetRequestFlags(uint dwRequestFlags); - public static IEnumerable Search(string query) { lock (_lock) @@ -88,7 +63,7 @@ public static bool IsInstalled() { try { - Everything_GetMajorVersion(); + _ = Everything_GetMajorVersion(); return true; } catch (Exception) @@ -109,4 +84,30 @@ private static void Ignore(Action action) // intentionally do nothing } } + + [LibraryImport("Everything64.dll", StringMarshalling = StringMarshalling.Utf16)] + private static partial void Everything_SetSearch(string lpSearchString); + + [LibraryImport("Everything64.dll")] + private static partial void Everything_SetMatchCase([MarshalAs(UnmanagedType.Bool)] bool bEnable); + + [LibraryImport("Everything64.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool Everything_Query([MarshalAs(UnmanagedType.Bool)] bool bWait); + + [LibraryImport("Everything64.dll")] + private static partial uint Everything_GetNumResults(); + + [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + private static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); + + [LibraryImport("Everything64.dll")] + private static partial void Everything_CleanUp(); + + [LibraryImport("Everything64.dll")] + private static partial uint Everything_GetMajorVersion(); + + // Everything 1.4 + [LibraryImport("Everything64.dll")] + private static partial void Everything_SetRequestFlags(uint dwRequestFlags); } \ No newline at end of file diff --git a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj index d7c3e13d..26b1d509 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj +++ b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj @@ -2,6 +2,7 @@ net7.0 + true From a0107a7ce6f5ea9b6426df5c5cfc2101a8945b38 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Thu, 28 Sep 2023 10:10:17 +0200 Subject: [PATCH 2/4] Revert "Use LibraryImport instead of DllImport" This reverts commit 822b7c0d2c96052cf3c78c9dc351d127f2e8dc91. --- .../Internal/Everything64Api.cs | 55 +++++++++---------- .../RepoM.Plugin.EverythingFileSearch.csproj | 1 - 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs index a1cdf7a4..a7a4688c 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs +++ b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs @@ -8,12 +8,37 @@ namespace RepoM.Plugin.EverythingFileSearch.Internal; /// Wrapper for Everything. /// See for the SDK. -internal static partial class Everything64Api +internal static class Everything64Api { private static readonly object _lock = new(); private const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001; private const int EVERYTHING_REQUEST_PATH = 0x00000002; + [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + public static extern void Everything_SetSearch(string lpSearchString); + + [DllImport("Everything64.dll")] + public static extern void Everything_SetMatchCase(bool bEnable); + + [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + public static extern bool Everything_Query(bool bWait); + + [DllImport("Everything64.dll")] + public static extern uint Everything_GetNumResults(); + + [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + public static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); + + [DllImport("Everything64.dll")] + public static extern void Everything_CleanUp(); + + [DllImport("Everything64.dll")] + public static extern uint Everything_GetMajorVersion(); + + // Everything 1.4 + [DllImport("Everything64.dll")] + public static extern void Everything_SetRequestFlags(uint dwRequestFlags); + public static IEnumerable Search(string query) { lock (_lock) @@ -63,7 +88,7 @@ public static bool IsInstalled() { try { - _ = Everything_GetMajorVersion(); + Everything_GetMajorVersion(); return true; } catch (Exception) @@ -84,30 +109,4 @@ private static void Ignore(Action action) // intentionally do nothing } } - - [LibraryImport("Everything64.dll", StringMarshalling = StringMarshalling.Utf16)] - private static partial void Everything_SetSearch(string lpSearchString); - - [LibraryImport("Everything64.dll")] - private static partial void Everything_SetMatchCase([MarshalAs(UnmanagedType.Bool)] bool bEnable); - - [LibraryImport("Everything64.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool Everything_Query([MarshalAs(UnmanagedType.Bool)] bool bWait); - - [LibraryImport("Everything64.dll")] - private static partial uint Everything_GetNumResults(); - - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - private static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); - - [LibraryImport("Everything64.dll")] - private static partial void Everything_CleanUp(); - - [LibraryImport("Everything64.dll")] - private static partial uint Everything_GetMajorVersion(); - - // Everything 1.4 - [LibraryImport("Everything64.dll")] - private static partial void Everything_SetRequestFlags(uint dwRequestFlags); } \ No newline at end of file diff --git a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj index 26b1d509..d7c3e13d 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj +++ b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj @@ -2,7 +2,6 @@ net7.0 - true From c3f9ad5914bdb7e5d30e910bcbc24aa1068db72d Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 29 Sep 2023 08:57:00 +0200 Subject: [PATCH 3/4] Use LibraryImport instead of DllImport --- src/RepoM.Api/Git/DefaultRepositoryMonitor.cs | 4 ++- .../Internal/Everything64Api.cs | 36 +++++++++---------- .../RepoM.Plugin.EverythingFileSearch.csproj | 1 + 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs b/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs index 341a636a..9eda94f7 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs @@ -11,6 +11,7 @@ namespace RepoM.Api.Git; using RepoM.Api.Git.AutoFetch; using RepoM.Api.IO; using RepoM.Core.Plugin.Repository; +using RepoM.Core.Plugin.RepositoryFinder; public class DefaultRepositoryMonitor : IRepositoryMonitor { @@ -72,8 +73,9 @@ public Task ScanForLocalRepositoriesAsync() var scannedPaths = 0; var paths = _pathProvider.GetPaths(); + IGitRepositoryFinder gitRepositoryFinder = _gitRepositoryFinderFactory.Create(); - IEnumerable tasks = paths.Select(path => Task.Run(() => _gitRepositoryFinderFactory.Create().Find(path, OnFoundNewRepository)) + IEnumerable tasks = paths.Select(path => Task.Run(() => gitRepositoryFinder.Find(path, OnFoundNewRepository)) .ContinueWith(_ => { if (Interlocked.Increment(ref scannedPaths) != paths.Length) diff --git a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs index a7a4688c..00186a91 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs +++ b/src/RepoM.Plugin.EverythingFileSearch/Internal/Everything64Api.cs @@ -8,36 +8,37 @@ namespace RepoM.Plugin.EverythingFileSearch.Internal; /// Wrapper for Everything. /// See for the SDK. -internal static class Everything64Api +internal static partial class Everything64Api { private static readonly object _lock = new(); private const int EVERYTHING_REQUEST_FILE_NAME = 0x00000001; private const int EVERYTHING_REQUEST_PATH = 0x00000002; - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern void Everything_SetSearch(string lpSearchString); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_SetSearchW", StringMarshalling = StringMarshalling.Utf16)] + private static partial void Everything_SetSearch(string lpSearchString); - [DllImport("Everything64.dll")] - public static extern void Everything_SetMatchCase(bool bEnable); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_SetMatchCase")] + private static partial void Everything_SetMatchCase([MarshalAs(UnmanagedType.Bool)] bool bEnable); - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern bool Everything_Query(bool bWait); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_QueryW")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool Everything_Query([MarshalAs(UnmanagedType.Bool)] bool bWait); - [DllImport("Everything64.dll")] - public static extern uint Everything_GetNumResults(); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_GetNumResults")] + private static partial uint Everything_GetNumResults(); [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] - public static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); + private static extern void Everything_GetResultFullPathName(uint nIndex, StringBuilder lpString, uint nMaxCount); - [DllImport("Everything64.dll")] - public static extern void Everything_CleanUp(); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_CleanUp")] + private static partial void Everything_CleanUp(); - [DllImport("Everything64.dll")] - public static extern uint Everything_GetMajorVersion(); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_GetMajorVersion")] + private static partial uint Everything_GetMajorVersion(); // Everything 1.4 - [DllImport("Everything64.dll")] - public static extern void Everything_SetRequestFlags(uint dwRequestFlags); + [LibraryImport("Everything64.dll", EntryPoint = "Everything_SetRequestFlags")] + private static partial void Everything_SetRequestFlags(uint dwRequestFlags); public static IEnumerable Search(string query) { @@ -88,8 +89,7 @@ public static bool IsInstalled() { try { - Everything_GetMajorVersion(); - return true; + return Everything_GetMajorVersion() > 0; } catch (Exception) { diff --git a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj index d7c3e13d..26b1d509 100644 --- a/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj +++ b/src/RepoM.Plugin.EverythingFileSearch/RepoM.Plugin.EverythingFileSearch.csproj @@ -2,6 +2,7 @@ net7.0 + true From 6466cba76f1f8febce6ac386c15f530896a2bc53 Mon Sep 17 00:00:00 2001 From: Coen van den Munckhof Date: Fri, 29 Sep 2023 09:31:29 +0200 Subject: [PATCH 4/4] add test --- src/RepoM.Api/Git/DefaultRepositoryMonitor.cs | 4 +- .../Git/DefaultRepositoryMonitorTests.cs | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/RepoM.Api.Tests/Git/DefaultRepositoryMonitorTests.cs diff --git a/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs b/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs index 9eda94f7..7e30207e 100644 --- a/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs +++ b/src/RepoM.Api/Git/DefaultRepositoryMonitor.cs @@ -56,11 +56,11 @@ public DefaultRepositoryMonitor( _pathProvider = pathProvider ?? throw new ArgumentNullException(nameof(pathProvider)); _repositoryStore = repositoryStore ?? throw new ArgumentNullException(nameof(repositoryStore)); _repositoryInformationAggregator = repositoryInformationAggregator ?? throw new ArgumentNullException(nameof(repositoryInformationAggregator)); - _repositoryObservers = new Dictionary(); - _repositoryIgnoreStore = repositoryIgnoreStore; + _repositoryIgnoreStore = repositoryIgnoreStore ?? throw new ArgumentNullException(nameof(repositoryIgnoreStore)); _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _autoFetchHandler = autoFetchHandler ?? throw new ArgumentNullException(nameof(autoFetchHandler)); + _repositoryObservers = new Dictionary(); _storeFlushTimer = new Timer(RepositoryStoreFlushTimerCallback, null, Timeout.Infinite, Timeout.Infinite); } diff --git a/tests/RepoM.Api.Tests/Git/DefaultRepositoryMonitorTests.cs b/tests/RepoM.Api.Tests/Git/DefaultRepositoryMonitorTests.cs new file mode 100644 index 00000000..e3978125 --- /dev/null +++ b/tests/RepoM.Api.Tests/Git/DefaultRepositoryMonitorTests.cs @@ -0,0 +1,73 @@ +namespace RepoM.Api.Tests.Git; + +using System; +using System.IO.Abstractions; +using System.Linq; +using System.Reflection; +using FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using RepoM.Api.Git; +using RepoM.Api.Git.AutoFetch; +using RepoM.Api.IO; +using Xunit; + +public class DefaultRepositoryMonitorTests +{ + [Fact] + public void Ctor_ShouldThrow_WhenArgumentNull() + { + // arrange + IPathProvider pathProvider = A.Dummy(); + IRepositoryReader repositoryReader = A.Dummy(); + IRepositoryDetectorFactory repositoryDetectorFactory = A.Dummy(); + IRepositoryObserverFactory repositoryObserverFactory = A.Dummy(); + IGitRepositoryFinderFactory gitRepositoryFinderFactory = A.Dummy(); + IRepositoryStore repositoryStore = A.Dummy(); + IRepositoryInformationAggregator repositoryInformationAggregator = A.Dummy(); + IAutoFetchHandler autoFetchHandler = A.Dummy(); + IRepositoryIgnoreStore repositoryIgnoreStore = A.Dummy(); + IFileSystem fileSystem = A.Dummy(); + ILogger logger = A.Dummy(); + + ConstructorInfo ctor = typeof(DefaultRepositoryMonitor).GetConstructors().Single(); + + var parameters = new object[] + { + pathProvider, + repositoryReader, + repositoryDetectorFactory, + repositoryObserverFactory, + gitRepositoryFinderFactory, + repositoryStore, + repositoryInformationAggregator, + autoFetchHandler, + repositoryIgnoreStore, + fileSystem, + logger, + }; + + var result = ctor.Invoke(parameters) as DefaultRepositoryMonitor; + result.Should().NotBeNull(); + + // act + for (int i = 0; i < parameters.Length; i++) + { + parameters[i] = null!; + Action act = () => + { + try + { + ctor.Invoke(parameters); + } + catch (TargetInvocationException e) + { + throw e.InnerException ?? e; + } + }; + + // assert + act.Should().Throw(); + } + } +} \ No newline at end of file