From 40c989cf9e50486eb5265e21db8c7d62dc2f4763 Mon Sep 17 00:00:00 2001 From: Renato Lima Date: Sun, 28 Mar 2021 02:46:26 -0300 Subject: [PATCH] Fix .mockignore behavior to use and override parent folders settings (Closes #75) --- .../Providers/TemplateFileProvider.cs | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/src/Mockaco/Templating/Providers/TemplateFileProvider.cs b/src/Mockaco/Templating/Providers/TemplateFileProvider.cs index d3c705e..3952b80 100644 --- a/src/Mockaco/Templating/Providers/TemplateFileProvider.cs +++ b/src/Mockaco/Templating/Providers/TemplateFileProvider.cs @@ -23,20 +23,21 @@ public sealed class TemplateFileProvider : ITemplateProvider, IDisposable private const string DefaultTemplateSearchPattern = "*.json"; private readonly ILogger _logger; - + private readonly IMemoryCache _memoryCache; private PhysicalFileProvider _fileProvider; private CancellationTokenSource _resetCacheToken = new CancellationTokenSource(); public TemplateFileProvider(IOptionsMonitor options, IWebHostEnvironment webHostEnvironment, IMemoryCache memoryCache, ILogger logger) - { + { _memoryCache = memoryCache; _logger = logger; SetMockRootPath(options.CurrentValue.Path); KeepWatchingForFileChanges(); - options.OnChange(options => { + options.OnChange(options => + { SetMockRootPath(options.Path); ResetCacheAndNotifyChange(); }); @@ -46,22 +47,22 @@ private void SetMockRootPath(string path) { try { - if(_fileProvider?.Root.Equals(path) == true) + if (_fileProvider?.Root.Equals(path) == true) { return; } - var fullPath = Path.IsPathRooted(path) - ? path + var fullPath = Path.IsPathRooted(path) + ? path : Path.Combine(Directory.GetCurrentDirectory(), path); - + var fileProvider = new PhysicalFileProvider(fullPath, ExclusionFilters.Hidden | ExclusionFilters.System); _fileProvider?.Dispose(); _fileProvider = fileProvider; _logger.LogInformation("Mock path: {fullPath}", fullPath); - } + } catch (Exception ex) { _logger.LogError(ex, "Error setting mock root path"); @@ -80,14 +81,14 @@ private void ResetCacheAndNotifyChange() private void KeepWatchingForFileChanges() { - if(_fileProvider == null) + if (_fileProvider == null) { return; } var jsonChangeToken = _fileProvider.Watch($"**/{DefaultTemplateSearchPattern}"); jsonChangeToken.RegisterChangeCallback(TemplateFileModified, default); - + var mockIgnoreChangeToken = _fileProvider.Watch($"**/*{MockIgnoreFileName}"); mockIgnoreChangeToken.RegisterChangeCallback(TemplateFileModified, default); } @@ -102,7 +103,7 @@ private void TemplateFileModified(object state) public IEnumerable GetTemplates() { return _memoryCache.GetOrCreate( - nameof(TemplateFileProvider), + nameof(TemplateFileProvider) + nameof(GetTemplates), e => { e.RegisterPostEvictionCallback(PostEvictionCallback); @@ -119,7 +120,7 @@ private void PostEvictionCallback(object key, object value, EvictionReason reaso private IEnumerable LoadTemplatesFromDirectory() { - if(_fileProvider == null) + if (_fileProvider == null) { yield break; } @@ -133,7 +134,7 @@ private IEnumerable LoadTemplatesFromDirectory() if (ShouldIgnoreFile(file)) { - _logger.LogDebug("{relativeFilePath} ignored using a {MockIgnoreFileName} file", relativeFilePath, MockIgnoreFileName); + _logger.LogDebug("{relativeFilePath} ignored by a {MockIgnoreFileName} file", relativeFilePath, MockIgnoreFileName); continue; } @@ -157,24 +158,45 @@ private IEnumerable LoadTemplatesFromDirectory() private bool ShouldIgnoreFile(FileInfo file) { - var mockIgnorePath = Path.Combine(file.DirectoryName, MockIgnoreFileName); + var ignores = GetIgnoreList(file.Directory); + + return ignores.IsIgnored(file); + } + + private IgnoreList GetIgnoreList(DirectoryInfo directoryInfo) + { + var relativePath = Path.GetRelativePath(_fileProvider.Root, directoryInfo.FullName); + var pathSegments = relativePath.Split(Path.DirectorySeparatorChar); + + var ignoreList = new IgnoreList(); + + var currentCombinedPath = _fileProvider.Root; - if (!File.Exists(mockIgnorePath)) + TryIncludeIgnoreListFrom(currentCombinedPath, ignoreList); + + foreach (var pathSegment in pathSegments) { - return false; + currentCombinedPath = Path.Combine(currentCombinedPath, pathSegment); + + TryIncludeIgnoreListFrom(currentCombinedPath, ignoreList); } - var ignores = WrapWithFileExceptionHandling(mockIgnorePath, () => - { - return new IgnoreList(mockIgnorePath); - }); + return ignoreList; + } + + private void TryIncludeIgnoreListFrom(string currentCombinedPath, IgnoreList ignoreList) + { + var mockIgnorePath = Path.Combine(currentCombinedPath, MockIgnoreFileName); - if (ignores == default) + if (File.Exists(mockIgnorePath)) { - return false; - } + WrapWithFileExceptionHandling(mockIgnorePath, () => + { + ignoreList.AddRules(mockIgnorePath); - return ignores.IsIgnored(file); + return ignoreList; + }); + } } private T WrapWithFileExceptionHandling(string path, Func action) @@ -184,8 +206,7 @@ private T WrapWithFileExceptionHandling(string path, Func action) try { return Policy.Handle() - .WaitAndRetry(sleepDurations: new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }, - onRetry: (ex, _) => log(ex)) + .WaitAndRetry(sleepDurations: new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }) .Execute(action); } catch (Exception ex)