public virtual PatternMatchingResult Execute(DirectoryInfoBase directoryInfo) { var files = new List<FilePatternMatch>(); foreach (var includePattern in _includePatterns) { var matcher = new Matcher(); matcher.AddInclude(includePattern); matcher.AddExcludePatterns(_excludePatterns); var result = matcher.Execute(directoryInfo); if (result.Files.Any()) { files.AddRange(result.Files); } } return new PatternMatchingResult(files); }
public static IEnumerable <string> GetResultsInFullPath(this Matcher matcher, string directoryPath) { var matches = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath))).Files; var result = matches.Select(match => Path.GetFullPath(Path.Combine(directoryPath, match.Path))).ToArray(); return(result); }
public static IEnumerable <(string Path, string Stem)> GetFileList(string basedir, string[] includes, string[] excludes, bool ignoreCase) { var matcher = new Microsoft.Extensions.FileSystemGlobbing.Matcher(ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture); if (excludes != null) { foreach (var exclude in excludes) { matcher.AddExclude(exclude); } } if (includes != null && includes.Length != 0) { foreach (var include in includes) { matcher.AddInclude(include); } } else { matcher.AddInclude("**/*"); } var di = new DirectoryInfo(basedir); var diwrapper = new DirectoryInfoWrapper(di); var result = matcher.Execute(diwrapper); if (!result.HasMatches) { return(Array.Empty <(string, string)>()); } else { return(result.Files.Select(x => (x.Path, x.Stem))); } }
public bool Build() { var projectFilesFinder = new Matcher(); // Resolve all the project names var projectFilesToBuild = new List<string>(); foreach (var pattern in _buildOptions.ProjectPatterns) { if (pattern.Contains("*")) { // Requires globbing projectFilesFinder.AddInclude(NormalizeGlobbingPattern(pattern)); } else { projectFilesToBuild.Add(pattern); } } var rootDirectory = Directory.GetCurrentDirectory(); var patternSearchFolder = new DirectoryInfoWrapper(new DirectoryInfo(rootDirectory)); var globbingProjects = projectFilesFinder.Execute(patternSearchFolder).Files.Select(file => Path.Combine(rootDirectory, file.Path)); projectFilesToBuild.AddRange(globbingProjects); var sw = Stopwatch.StartNew(); var globalSucess = true; foreach (var project in projectFilesToBuild) { var buildSuccess = BuildInternal(project); globalSucess &= buildSuccess; } _buildOptions.Reports.Information.WriteLine($"Total build time elapsed: { sw.Elapsed }"); _buildOptions.Reports.Information.WriteLine($"Total projects built: { projectFilesToBuild.Count }"); return globalSucess; }
// Initially based on code from Reliak.FileSystemGlobbingExtensions (https://github.com/reliak/Reliak.FileSystemGlobbingExtensions) public static IEnumerable<IFile> GetFiles(IDirectory directory, IEnumerable<string> patterns) { Matcher matcher = new Matcher(StringComparison.Ordinal); // Expand braces IEnumerable<string> expandedPatterns = patterns .SelectMany(ExpandBraces) .Select(f => f.Replace("\\{", "{").Replace("\\}", "}")); // Unescape braces // Add the patterns, any that start with ! are exclusions foreach (string expandedPattern in expandedPatterns) { bool isExclude = expandedPattern[0] == '!'; string finalPattern = isExclude ? expandedPattern.Substring(1) : expandedPattern; finalPattern = finalPattern .Replace("\\!", "!") // Unescape negation .Replace("\\", "/"); // Normalize slashes // No support for absolute paths if (System.IO.Path.IsPathRooted(finalPattern)) { throw new ArgumentException($"Rooted globbing patterns are not supported ({expandedPattern})", nameof(patterns)); } // Add exclude or include pattern to matcher if (isExclude) { matcher.AddExclude(finalPattern); } else { matcher.AddInclude(finalPattern); } } DirectoryInfoBase directoryInfo = new DirectoryInfo(directory); PatternMatchingResult result = matcher.Execute(directoryInfo); return result.Files.Select(match => directory.GetFile(match.Path)); }
/// <summary> /// Enumerate all the PowerShell (ps1, psm1, psd1) files in the workspace in a recursive manner. /// </summary> /// <returns>An enumerator over the PowerShell files found in the workspace.</returns> public IEnumerable <string> EnumeratePSFiles( string[] excludeGlobs, string[] includeGlobs, int maxDepth, bool ignoreReparsePoints ) { if (WorkspacePath == null || !Directory.Exists(WorkspacePath)) { yield break; } var matcher = new Microsoft.Extensions.FileSystemGlobbing.Matcher(); foreach (string pattern in includeGlobs) { matcher.AddInclude(pattern); } foreach (string pattern in excludeGlobs) { matcher.AddExclude(pattern); } var fsFactory = new WorkspaceFileSystemWrapperFactory( WorkspacePath, maxDepth, Utils.IsNetCore ? s_psFileExtensionsCoreFramework : s_psFileExtensionsFullFramework, ignoreReparsePoints, logger ); var fileMatchResult = matcher.Execute(fsFactory.RootDirectory); foreach (FilePatternMatch item in fileMatchResult.Files) { yield return(Path.Combine(WorkspacePath, item.Path)); } }
internal static IEnumerable<PhysicalPackageFile> CollectAdditionalFiles(DirectoryInfoBase rootDirectory, IEnumerable<PackIncludeEntry> projectFileGlobs, string projectFilePath, IList<DiagnosticMessage> diagnostics) { foreach (var entry in projectFileGlobs) { // Evaluate the globs on the right var matcher = new Matcher(); matcher.AddIncludePatterns(entry.SourceGlobs); var results = matcher.Execute(rootDirectory); var files = results.Files.ToList(); // Check for illegal characters if (string.IsNullOrEmpty(entry.Target)) { diagnostics.Add(new DiagnosticMessage( DiagnosticMonikers.NU1003, $"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. The target '{entry.Target}' is invalid, " + "targets must either be a file name or a directory suffixed with '/'. " + "The root directory of the package can be specified by using a single '/' character.", projectFilePath, DiagnosticMessageSeverity.Error, entry.Line, entry.Column)); continue; } if (entry.Target.Split('/').Any(s => s.Equals(".") || s.Equals(".."))) { diagnostics.Add(new DiagnosticMessage( DiagnosticMonikers.NU1004, $"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " + $"The target '{entry.Target}' contains path-traversal characters ('.' or '..'). " + "These characters are not permitted in target paths.", projectFilePath, DiagnosticMessageSeverity.Error, entry.Line, entry.Column)); continue; } // Check the arity of the left if (entry.Target.EndsWith("/")) { var dir = entry.Target.Substring(0, entry.Target.Length - 1).Replace('/', Path.DirectorySeparatorChar); foreach (var file in files) { yield return new PhysicalPackageFile() { SourcePath = Path.Combine(rootDirectory.FullName, PathUtility.GetPathWithDirectorySeparator(file.Path)), TargetPath = Path.Combine(dir, PathUtility.GetPathWithDirectorySeparator(file.Stem)) }; } } else { // It's a file. If the glob matched multiple things, we're sad :( if (files.Count > 1) { // Arity mismatch! string sourceValue = entry.SourceGlobs.Length == 1 ? $"\"{entry.SourceGlobs[0]}\"" : ("[" + string.Join(",", entry.SourceGlobs.Select(v => $"\"{v}\"")) + "]"); diagnostics.Add(new DiagnosticMessage( DiagnosticMonikers.NU1005, $"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " + $"The target '{entry.Target}' refers to a single file, but the pattern {sourceValue} " + "produces multiple files. To mark the target as a directory, suffix it with '/'.", projectFilePath, DiagnosticMessageSeverity.Error, entry.Line, entry.Column)); } else { yield return new PhysicalPackageFile() { SourcePath = Path.Combine(rootDirectory.FullName, files[0].Path), TargetPath = PathUtility.GetPathWithDirectorySeparator(entry.Target) }; } } } }
public IEnumerable<IFileInfo> ListFiles(string path, Matcher matcher) { var directory = GetDirectoryInfo(path); if (!directory.Exists) { return Enumerable.Empty<IFileInfo>(); } return matcher.Execute(new DirectoryInfoWrapper(directory)) .Files .Select(result => GetFileInfo(Combine(directory.FullName, result.Path))); }
/// <summary> /// Matches the files passed in with the patterns in the matcher without going to disk. /// </summary> /// <param name="matcher">The matcher that holds the patterns and pattern matching type.</param> /// <param name="rootDir">The root directory for the matcher to match the files from.</param> /// <param name="files">The files to run the matcher against.</param> /// <returns>The match results.</returns> public static PatternMatchingResult Match(this Matcher matcher, string rootDir, IEnumerable <string>?files) { ThrowHelper.ThrowIfNull(matcher); return(matcher.Execute(new InMemoryDirectoryInfo(rootDir, files))); }
private async Task OnFileChanged(object sender, System.IO.FileSystemEventArgs e) { // Skip directory change events and when rpc has ben disconnected if (!e.IsDirectoryChanged() && _rpc != null) { // Create something to match with var item = new InMemoryDirectoryInfo(_root, new string[] { e.FullPath }); // See if this matches one of our patterns. if (_matcher.Execute(item).HasMatches) { // Send out the event to the language server var renamedArgs = e as System.IO.RenamedEventArgs; var didChangeParams = new DidChangeWatchedFilesParams(); // Visual Studio actually does a rename when saving. The rename is from a file ending with '~' if (renamedArgs == null || renamedArgs.OldFullPath.EndsWith("~")) { renamedArgs = null; didChangeParams.Changes = new FileEvent[] { new FileEvent() }; didChangeParams.Changes[0].Uri = new Uri(e.FullPath); switch (e.ChangeType) { case WatcherChangeTypes.Created: didChangeParams.Changes[0].FileChangeType = FileChangeType.Created; break; case WatcherChangeTypes.Deleted: didChangeParams.Changes[0].FileChangeType = FileChangeType.Deleted; break; case WatcherChangeTypes.Changed: didChangeParams.Changes[0].FileChangeType = FileChangeType.Changed; break; case WatcherChangeTypes.Renamed: didChangeParams.Changes[0].FileChangeType = FileChangeType.Changed; break; default: didChangeParams.Changes = Array.Empty <FileEvent>(); break; } } else { // file renamed var deleteEvent = new FileEvent(); deleteEvent.FileChangeType = FileChangeType.Deleted; deleteEvent.Uri = new Uri(renamedArgs.OldFullPath); var createEvent = new FileEvent(); createEvent.FileChangeType = FileChangeType.Created; createEvent.Uri = new Uri(renamedArgs.FullPath); didChangeParams.Changes = new FileEvent[] { deleteEvent, createEvent }; } if (didChangeParams.Changes.Any()) { await _rpc.NotifyWithParameterObjectAsync(Methods.WorkspaceDidChangeWatchedFiles.Name, didChangeParams); if (renamedArgs != null) { var textDocumentIdentifier = new TextDocumentIdentifier(); textDocumentIdentifier.Uri = new Uri(renamedArgs.OldFullPath); var closeParam = new DidCloseTextDocumentParams(); closeParam.TextDocument = textDocumentIdentifier; await _rpc.NotifyWithParameterObjectAsync(Methods.TextDocumentDidClose.Name, closeParam); var textDocumentItem = new TextDocumentItem(); textDocumentItem.Uri = new Uri(renamedArgs.FullPath); var openParam = new DidOpenTextDocumentParams(); openParam.TextDocument = textDocumentItem; await _rpc.NotifyWithParameterObjectAsync(Methods.TextDocumentDidOpen.Name, openParam); } } } } }