Exemplo n.º 1
0
        public FileWatcherConfiguration(string watchPath, string destinationPath, string[] excludedPathsGlob)
        {
            this.watchPath         = watchPath.Trim();
            this.destinationPath   = destinationPath.Trim();
            this.excludedPathsGlob = new Glob[excludedPathsGlob.Length];

            for (int i = 0; i < excludedPathsGlob.Length; ++i)
            {
                GlobOptions options = new GlobOptions();
                options.Evaluation.CaseInsensitive = true;
                this.excludedPathsGlob[i]          = Glob.Parse(excludedPathsGlob[i], options);
            }
        }
Exemplo n.º 2
0
        public static bool ShouldMutateProject(Project project, Config config)
        {
            if (config.ProjectFilters == null ||
                !config.ProjectFilters.Any())
            {
                return(true);
            }

            var relativePath = RelativeFilePath(project.FilePath, config);

            return(config.ProjectFilters
                   .Any(f => Glob.Parse(f).IsMatch(project.Name) || Glob.Parse(f).IsMatch(relativePath)));
        }
Exemplo n.º 3
0
        public IEnumerable <ContentItem> GetContentItems(string version, string type, string pattern)
        {
            var glob = Glob.Parse(pattern);

            if (_contentItems.TryGetValue(version, out var versionCollection))
            {
                if (versionCollection.TryGetValue(type, out var typeCollection))
                {
                    return(typeCollection.Where(t => glob.IsMatch(t.File.Path)));
                }
            }

            return(Enumerable.Empty <ContentItem>());
        }
Exemplo n.º 4
0
        public void FilterDirectory_enumerate_files_by_extension()
        {
            var e = Fixture1Enumerator();

            string[] results = Glob.FilterDirectory(Glob.Parse("**/*.csv"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();

            Assert.Equal(new [] {
                "/a/c.csv",
                "/a/e/l.csv",
            }, results, FileNameComparison);
        }
Exemplo n.º 5
0
        public IEnumerable <string> EnumerateFileSystemEntries(string directoryName, string pattern, SearchOption searchOption)
        {
            RecordDirectoryScan(directoryName, pattern, searchOption);
            Glob g = Glob.Parse(searchOption != SearchOption.AllDirectories ? "**/" + pattern : pattern);

            foreach (string entry in _files.Keys.Union(_directories).Where(x => x.StartsWith(directoryName, StringComparison.Ordinal) || x.StartsWith(directoryName, StringComparison.Ordinal) && (x[directoryName.Length] == Path.DirectorySeparatorChar || x[directoryName.Length] == Path.AltDirectorySeparatorChar)))
            {
                string p = entry.Replace('\\', '/').TrimStart('/');
                if (g.IsMatch(p))
                {
                    yield return(entry);
                }
            }
        }
Exemplo n.º 6
0
        public void SetupData()
        {
            _testMatchingStringsList = new List <string>(NumberOfMatches);
            //_testNonMatchingStringsList = new List<string>(NumberOfMatches);
            _glob = Glob.Parse(GlobPattern);
            var generator = new GlobMatchStringGenerator(_glob.Tokens);

            for (int i = 0; i < 1000; i++)
            {
                var matchString = generator.GenerateRandomMatch();
                _testMatchingStringsList.Add(matchString);
                //_testNonMatchingStringsList.Add(generator.GenerateRandomNonMatch());
            }
        }
Exemplo n.º 7
0
        public void FilterDirectory_enumerate_root_directory_child_by_name()
        {
            var e = Fixture1Enumerator();

            string[] results = Glob.FilterDirectory(Glob.Parse("a/*.txt"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();

            Assert.Equal(new [] {
                "/a/b.txt",
                "/a/d.txt",
            }, results, FileNameComparison);
        }
Exemplo n.º 8
0
        public void FilterDirectory_enumerate_by_wildcard_recursive_similar_names()
        {
            var e = Fixture2Enumerator();

            // Should exclude the ~a dire
            string[] results = Glob.FilterDirectory(Glob.Parse("src/**/a/*.txt"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();
            Assert.Equal(new [] {
                "/src/a/bon.txt",
                "/src/a/bot.txt",
            }, results, FileNameComparison);
        }
Exemplo n.º 9
0
            public static IEnumerable <ScenarioItem> Default()
            {
                yield return(new ScenarioItem
                {
                    Glob = Glob.Parse("*.cs"),
                    Input = new[]
                    {
                        @"program.cs",
                        @"program.txt"
                    },
                    Output = new[]
                    {
                        @"program.cs"
                    }
                });

                yield return(new ScenarioItem
                {
                    Glob = Glob.Parse("**.cs"),
                    Input = new[]
                    {
                        @"program.cs",
                        @"program.txt",
                        @"properties\assembly.cs",
                        @"properties\assembly.info"
                    },
                    Output = new[]
                    {
                        @"program.cs",
                        @"properties\assembly.cs"
                    }
                });

                yield return(new ScenarioItem
                {
                    Glob = Glob.Parse("program.*"),
                    Input = new[]
                    {
                        @"program.cs",
                        @"program.txt",
                        @"properties\assembly.cs",
                        @"properties\assembly.info"
                    },
                    Output = new[]
                    {
                        @"program.cs",
                        @"program.txt"
                    }
                });
            }
Exemplo n.º 10
0
        /// <summary>
        /// Checks whether subject matches a list of glob patterns.
        /// </summary>
        /// <param name="items"></param>
        /// <param name="subject"></param>
        /// <returns></returns>
        public static bool MatchesAny(this IEnumerable <string> items, string subject)
        {
            foreach (var pattern in items)
            {
                var glob = Glob.Parse(pattern);

                if (glob.IsMatch(subject))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 11
0
        public static Type GetDrawable(ImportNamespaceInfo import, string localName)
        {
            lock (_lock)
            {
                if (!_loadedTypes.TryGetValue(import.AssemblyName, out var typeDict))
                {
                    typeDict = _loadedTypes[import.AssemblyName] = Assembly
                                                                   .Load(import.AssemblyName)
                                                                   .GetExportedTypes()
                                                                   .Where(t => t.IsClass &&
                                                                          t.IsSubclassOf(typeof(Drawable)))
                                                                   .ToArray();
                }

                var pattern       = Glob.Parse(import.ImportPattern);
                var matchingTypes = typeDict
                                    .Where(t => pattern.IsMatch(t.FullName) &&
                                           localName.Equals(t.Name))
                                    .ToArray();

                if (matchingTypes.Length == 1)
                {
                    var matchingType = matchingTypes[0];

                    // Ensure type is not abstract
                    if (matchingType.IsAbstract)
                    {
                        throw new MarkupException($"Drawable '{matchingType}' is abstract and cannot be used.");
                    }

                    // Ensure type can be created
                    if (!matchingType.GetConstructors().Any(c => c.GetParameters().All(p => p.IsOptional)))
                    {
                        throw new MarkupException($"Drawable '{matchingType}' does not have a suitable constructor.");
                    }

                    return(matchingType);
                }

                if (matchingTypes.Length == 0)
                {
                    throw new KeyNotFoundException($"Type '{localName}' could not be found in assembly '{import.AssemblyName}'.");
                }

                throw new AmbiguousMatchException(
                          $"Drawable '{localName}' is ambiguous between the following types: " +
                          string.Join(", ", matchingTypes.Select(t => t.FullName))
                          );
            }
        }
Exemplo n.º 12
0
        public bool IsMarkedToExport(string objective, ITimetableInput timetableInput)
        {
            var whitelist = GetWhitelist(timetableInput);

            foreach (var pattern in whitelist)
            {
                var glob = Glob.Parse(pattern);
                if (glob.IsMatch(objective))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 13
0
        public IEnumerable <string> FindFiles(string pattern)
        {
            //pattern = pattern.TrimStart('/');
            //var files = Enumerable.Empty<string>();
            Glob glob = Glob.Parse(pattern,
                                   new GlobOptions {
                Evaluation = new EvaluationOptions {
                    CaseInsensitive = true
                }
            });

            var matches = Files.Keys.Where(x => glob.IsMatch(x));

            return(matches);
        }
Exemplo n.º 14
0
        private static bool ShouldMutateAccordingToFilters(Document document, Config config)
        {
            if (config.SourceFileFilters == null ||
                !config.SourceFileFilters.Any())
            {
                return(true);
            }

            var relativePath = RelativeFilePath(document.FilePath, config);

            var matchesAnyFilter = config.SourceFileFilters
                                   .Any(f => Glob.Parse(f).IsMatch(relativePath));

            return(matchesAnyFilter);
        }
Exemplo n.º 15
0
        public void FilterDirectory_enumerate_literal_directory()
        {
            var e    = Fixture1Enumerator();
            var glob = Glob.Parse("a/e/**/*.txt");

            string[] results = Glob.FilterDirectory(Glob.Parse("a/e/**/*.txt"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();

            Assert.Equal(new [] {
                "/a/e/f/g/h.txt",
                "/a/e/f/g/i.txt",
            }, results, FileNameComparison);
        }
Exemplo n.º 16
0
        protected override async Task Execute(FieldUser sender, TOption option)
        {
            var templateManager = sender.Service.TemplateManager;
            var templateStrings = templateManager.GetAll <TString>().ToList();
            var templateID      = option.TemplateID;

            if (!string.IsNullOrEmpty(option.Search))
            {
                var glob    = Glob.Parse(option.Search, _globOptions);
                var results = templateStrings
                              .Where(p => glob.IsMatch(p.Name))
                              .ToList();

                if (!results.Any())
                {
                    results = templateStrings
                              .Where(p => p.Name.ToLower().Contains(option.Search.ToLower()))
                              .ToList();
                }

                if (results.Any())
                {
                    templateID = await sender.Prompt <int>(target => target.AskMenu(
                                                               $"Here are the results for '{option.Search}'",
                                                               results.ToDictionary(
                                                                   r => r.ID,
                                                                   r => $"{r.Name} ({r.ID})"
                                                                   )
                                                               ));
                }
            }

            if (templateID == null)
            {
                return;
            }

            var template = templateManager.Get <TTemplate>(templateID.Value);

            if (template == null)
            {
                await sender.Message($"Unable to find template of ID: {templateID}");

                return;
            }

            await ExecuteAfter(sender, template, option);
        }
Exemplo n.º 17
0
        private static void Command_ExplodeAll(string pattern = "*")
        {
            var globOptions    = new GlobOptions(); globOptions.Evaluation.CaseInsensitive = true;
            var playersVehicle = Game.LocalPlayer.Character.CurrentVehicle;

            foreach (var vehicle in World.GetAllVehicles())
            {
                if (vehicle.Exists() && (!playersVehicle.Exists() || vehicle != playersVehicle) && !vehicle.IsExplosionProof)
                {
                    if (Glob.Parse(pattern, globOptions).IsMatch(vehicle.Model.Name))
                    {
                        vehicle.Explode();
                    }
                }
            }
        }
Exemplo n.º 18
0
        public void FilterDirectory_Regex_enumerate_top_level_files()
        {
            var e = Fixture1Enumerator();

            string[] results = Glob.FilterDirectory(Glob.Parse("*.*"),
                                                    "/a",
                                                    e.FileExists,
                                                    e).ToArray();

            Assert.True(Glob.Parse("*.*").ToRegex().IsMatch("/a/b.txt"));
            Assert.Equal(new [] {
                "/a/b.txt",
                "/a/c.csv",
                "/a/d.txt",
            }, results, FileNameComparison);
        }
Exemplo n.º 19
0
        public void VerifyLeadGlobPathSpanning()
        {
            Glob g = Glob.Parse("**/file");

            Assert.True(g.IsMatch("file"));
            Assert.True(g.IsMatch("a/file"));
            Assert.True(g.IsMatch("a/b/file"));
            Assert.True(g.IsMatch("a/b/c/file"));
            Assert.False(g.IsMatch("other"));
            Assert.False(g.IsMatch("a/other"));
            Assert.False(g.IsMatch("a/b/other"));
            Assert.False(g.IsMatch("a/b/c/other"));
            Assert.False(g.IsMatch("file/stuff"));
            Assert.False(g.IsMatch("file.txt"));
            Assert.False(g.IsMatch("thefile"));
        }
Exemplo n.º 20
0
        /// <inheritdoc/>
        public override async Task <IFtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(command.Argument))
            {
                var taskStates    = _backgroundTransferWorker.GetStates();
                var statusMessage = new StringBuilder();
                statusMessage.AppendFormat(
                    "Server functional, {0} open connections",
                    _server.Statistics.ActiveConnections);
                if (taskStates.Count != 0)
                {
                    statusMessage.AppendFormat(", {0} active background transfers", taskStates.Count);
                }

                return(new FtpResponse(211, statusMessage.ToString()));
            }

            var mask = command.Argument;

            if (!mask.EndsWith("*"))
            {
                mask += "*";
            }

            var fsFeature = Connection.Features.Get <IFileSystemFeature>();

            var globOptions = new GlobOptions();

            globOptions.Evaluation.CaseInsensitive = fsFeature.FileSystem.FileSystemEntryComparer.Equals("a", "A");

            var glob = Glob.Parse(mask, globOptions);

            var formatter = new LongListFormatter();

            var entries = await fsFeature.FileSystem.GetEntriesAsync(fsFeature.CurrentDirectory, cancellationToken)
                          .ConfigureAwait(false);

            var lines = entries.Where(x => glob.IsMatch(x.Name))
                        .Select(x => formatter.Format(x, x.Name))
                        .ToList();

            return(new FtpResponseList(
                       211,
                       $"STAT {command.Argument}",
                       "STAT",
                       lines));
        }
Exemplo n.º 21
0
        /// <summary>
        /// Returns a filtered list of files. It only returns all files that belong to the most recent
        /// period. The period is supposed to be part of the path an HTML-file (any directory must have
        /// a Px-pattern (x meaning a number).
        /// </summary>
        /// <param name="files">List of absolutes paths of all files.</param>
        /// <param name="path">Path of the root directory for timetable exports.</param>
        /// <returns></returns>
        private string[] FilterLastPeriod(string[] files, string path)
        {
            if (files == null || files.Length == 0)
            {
                return(files);
            }

            var sortedFiles = files
                              .Select(x => Path.GetRelativePath(path, x))
                              .OrderByDescending(x => x, StringComparison.OrdinalIgnoreCase.WithNaturalSort());
            var mostDescendingFile = sortedFiles.FirstOrDefault();

            var    parts           = mostDescendingFile.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); // This may break on other OS than Windows
            string periodDirectory = null;

            var regexpDetectPeriodDirectory = new Regex("^P([0-9]+)$");

            foreach (var part in parts)
            {
                if (regexpDetectPeriodDirectory.IsMatch(part))
                {
                    periodDirectory = part;
                    break;
                }
            }

            if (periodDirectory == null)
            {
                logger.LogError($"Did not find any period directory (e.g. P10, P2, ...) in the most descending file {mostDescendingFile}.");
            }

            logger.LogDebug($"{periodDirectory} seems to be the most recent period.");

            var filesInPeriod = new List <string>();

            var globDetectCurrentPeriod = Glob.Parse($"**/{periodDirectory}/**/*");

            foreach (var file in sortedFiles)
            {
                if (globDetectCurrentPeriod.IsMatch(file))
                {
                    filesInPeriod.Add(Path.Combine(path, file));
                }
            }

            return(filesInPeriod.ToArray());
        }
Exemplo n.º 22
0
        /// <summary>
        /// Gets absolute normalized path for a target matching <paramref name="sourcePathGlob"/>.
        /// </summary>
        protected static IReadOnlyList <string> GetTargetForSource(ICreationEffects2 creationEffects, string sourcePathGlob, string outputBasePath)
        {
            Glob          g       = Glob.Parse(sourcePathGlob);
            List <string> results = new List <string>();

            if (creationEffects.FileChanges != null)
            {
                foreach (IFileChange2 change in creationEffects.FileChanges)
                {
                    if (g.IsMatch(change.SourceRelativePath))
                    {
                        results.Add(Path.GetFullPath(change.TargetRelativePath, outputBasePath));
                    }
                }
            }
            return(results);
        }
Exemplo n.º 23
0
        public bool IsIgnorable(string filePath)
        {
            if (IgnorableFiles?.Any() == true)
            {
                foreach (var ignorable in IgnorableFiles)
                {
                    var glob    = Glob.Parse(ignorable);
                    var isMatch = glob.IsMatch(filePath);
                    if (isMatch)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 24
0
        public virtual ICollection <string> Execute(string path)
        {
            RootPath = Path.GetFullPath(path);

            if (!Directory.Exists(RootPath))
            {
                throw new DirectoryNotFoundException($"Directory not exists: '{RootPath}'");
            }

            IEnumerable <string> entries = Directory.EnumerateFileSystemEntries(RootPath, "*", SearchOption.AllDirectories);

            ICollection <string> includePatterns = PreparePatterns(RootPath, _includePatterns);
            ICollection <string> excludePatterns = PreparePatterns(RootPath, _excludePatterns);

            var includedEntries = new Collection <string>();

            foreach (string entry in entries)
            {
                if (includePatterns.Any(x => Glob.Parse(x, _globOptions).IsMatch(entry)))
                {
                    includedEntries.Add(entry);
                }
            }

            var excludedEntries = new Collection <string>();

            foreach (string entry in entries)
            {
                if (excludePatterns.Any(x => Glob.Parse(x, _globOptions).IsMatch(entry)))
                {
                    excludedEntries.Add(entry);
                }
            }

            var results = new Collection <string>();

            foreach (string entry in includedEntries)
            {
                if (!excludedEntries.Any(x => x.Contains(entry)))
                {
                    results.Add(entry);
                }
            }

            return(results);
        }
Exemplo n.º 25
0
        public static IEnumerable <string> GetFilesByGlobPattern(this string baseDirectory, string globPattern, out Glob outGlob)
        {
            var baseDirectoryGlobPattern = Path.GetFullPath(Path.Combine(baseDirectory, globPattern));
            var fileNames = new List <string>();

            if (string.Equals(".", globPattern))
            {
                globPattern = Path.GetFullPath(Path.Combine(baseDirectory, "*.*"));
            }
            else if (Directory.Exists(baseDirectoryGlobPattern))
            {
                globPattern = Path.GetFullPath(Path.Combine(baseDirectoryGlobPattern, "*.*"));
            }
            else if (File.Exists(baseDirectoryGlobPattern))
            {
                globPattern = Path.GetFullPath(baseDirectoryGlobPattern);
            }
            else if (globPattern.Contains(" "))
            {
                baseDirectoryGlobPattern = baseDirectory;

                fileNames.AddRange(globPattern
                                   .Split(" ", StringSplitOptions.RemoveEmptyEntries)
                                   .Select(x => Path.IsPathRooted(x)
                        ? Path.GetFullPath(x)
                        : Path.GetFullPath(Path.Combine(baseDirectoryGlobPattern, x)))
                                   .Where(x => !Directory.Exists(x)));

                globPattern = string.Empty;
            }

            var glob = Path.IsPathRooted(globPattern)
                ? Glob.Parse(globPattern)
                : Glob.Parse(baseDirectoryGlobPattern);

            var basePathFromGlob = Path.GetDirectoryName(glob.BuildBasePathFromGlob(baseDirectory));

            outGlob = glob;

            return(Directory
                   .GetFiles(basePathFromGlob, "*.*", SearchOption.AllDirectories)
                   .Where(filename =>
                          filename.EndsWith(".nupkg", StringComparison.OrdinalIgnoreCase) ||
                          filename.EndsWith(".snupkg", StringComparison.OrdinalIgnoreCase))
                   .Where(filename => fileNames.Contains(filename, StringComparer.Ordinal) || glob.IsMatch(filename)));
        }
Exemplo n.º 26
0
        public void FilterDirectory_enumerate_by_bracket_choice_recursive()
        {
            // TODO [a-z].txt could be used
            var e = Fixture1Enumerator();

            string[] results = Glob.FilterDirectory(Glob.Parse("**/[bhi].txt"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();
            Assert.Equal("([^/\\:]+/)*/(b|h|i)\\.txt$", Glob.Parse("**/[bhi].txt").ToRegex().ToString());
            Assert.True(Glob.Parse("**/[bhi].txt").IsMatch("/a/e/f/g/h.txt"));
            Assert.Equal(new [] {
                "/a/b.txt",
                "/a/e/f/g/h.txt",
                "/a/e/f/g/i.txt",
            }, results, FileNameComparison);
        }
Exemplo n.º 27
0
        public static string[] GetIncludeFiles(string projectPath, string itemType)
        {
            var result        = new List <string>();
            var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");

            var globOptions = new GlobOptions();

            globOptions.Evaluation.CaseInsensitive = false;

            var root = ProjectRootElement.Open(projectPath);

            Debug.Assert(root != null);

            foreach (var itemGroup in root.ItemGroups)
            {
                if (itemGroup.Condition.Length != 0)
                {
                    continue;
                }

                foreach (var item in itemGroup.Items)
                {
                    if (item.ItemType != itemType)
                    {
                        continue;
                    }

                    string normalizedInclude = item.Include.NormalizePath();

                    var glob = Glob.Parse(normalizedInclude, globOptions);

                    // TODO Check somehow if path has no blob to avoid the following loop...

                    foreach (var existingFile in existingFiles)
                    {
                        if (glob.IsMatch(existingFile))
                        {
                            result.Add(existingFile);
                        }
                    }
                }
            }

            return(result.ToArray());
        }
Exemplo n.º 28
0
        public void FilterDirectory_enumerate_files_in_multiglob()
        {
            var e = Fixture1Enumerator();

            string[] results = Glob.FilterDirectory(Glob.Parse("**/*.csv;**/*.txt"),
                                                    "/",
                                                    e.FileExists,
                                                    e).ToArray();

            Assert.SetEqual(new [] {
                "/a/b.txt",
                "/a/c.csv",
                "/a/d.txt",
                "/a/e/f/g/h.txt",
                "/a/e/f/g/i.txt",
                "/a/e/l.csv",
            }, results, FileNameComparison);
        }
Exemplo n.º 29
0
        /// <inheritdoc/>
        public override async Task <FtpResponse> Process(FtpCommand command, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(command.Argument))
            {
                var taskStates    = _backgroundTransferWorker.GetStates();
                var statusMessage = new StringBuilder();
                statusMessage.AppendFormat("Server functional, {0} open connections", _server.Statistics.ActiveConnections);
                if (taskStates.Count != 0)
                {
                    statusMessage.AppendFormat(", {0} active background transfers", taskStates.Count);
                }

                return(new FtpResponse(211, statusMessage.ToString()));
            }

            var mask = command.Argument;

            if (!mask.EndsWith("*"))
            {
                mask += "*";
            }

            var globOptions = new GlobOptions();

            globOptions.Evaluation.CaseInsensitive = Data.FileSystem.FileSystemEntryComparer.Equals("a", "A");

            var glob = Glob.Parse(mask, globOptions);

            var formatter = new LongListFormatter();
            await Connection.WriteAsync($"211-STAT {command.Argument}", cancellationToken).ConfigureAwait(false);

            var entries = await Data.FileSystem.GetEntriesAsync(Data.CurrentDirectory, cancellationToken)
                          .ConfigureAwait(false);

            foreach (var entry in entries.Where(x => glob.IsMatch(x.Name)))
            {
                var line = formatter.Format(entry, entry.Name);
                Connection.Log?.LogDebug(line);
                await Connection.WriteAsync($" {line}", cancellationToken).ConfigureAwait(false);
            }

            return(new FtpResponse(211, "STAT"));
        }
Exemplo n.º 30
0
        public void GlobCollection1(GlobOptions options)
        {
            using var directory = TemporaryDirectory.Create();
            directory.CreateEmptyFile("d1/d2/f1.txt");
            directory.CreateEmptyFile("d1/d2/f2.txt");
            directory.CreateEmptyFile("d1/f3.txt");
            directory.CreateEmptyFile("d3/f4.txt");

            var glob = new GlobCollection(
                Glob.Parse("**/*.txt", options),
                Glob.Parse("!d1/*.txt", options));

            TestEvaluate(directory, glob, new[]
            {
                "d1/d2/f1.txt",
                "d1/d2/f2.txt",
                "d3/f4.txt",
            });
        }