123 lines
5.5 KiB
C#
123 lines
5.5 KiB
C#
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.Extensions.FileSystemGlobbing;
|
|
using Microsoft.Extensions.JsonParser.Sources;
|
|
|
|
namespace Microsoft.DotNet.ProjectModel.Files
|
|
{
|
|
public class PatternGroup
|
|
{
|
|
private readonly List<PatternGroup> _excludeGroups = new List<PatternGroup>();
|
|
private readonly Matcher _matcher = new Matcher();
|
|
|
|
internal PatternGroup(IEnumerable<string> includePatterns)
|
|
{
|
|
IncludeLiterals = Enumerable.Empty<string>();
|
|
IncludePatterns = includePatterns;
|
|
ExcludePatterns = Enumerable.Empty<string>();
|
|
_matcher.AddIncludePatterns(IncludePatterns);
|
|
}
|
|
|
|
internal PatternGroup(IEnumerable<string> includePatterns, IEnumerable<string> excludePatterns, IEnumerable<string> includeLiterals)
|
|
{
|
|
IncludeLiterals = includeLiterals;
|
|
IncludePatterns = includePatterns;
|
|
ExcludePatterns = excludePatterns;
|
|
|
|
_matcher.AddIncludePatterns(IncludePatterns);
|
|
_matcher.AddExcludePatterns(ExcludePatterns);
|
|
}
|
|
|
|
internal static PatternGroup Build(JsonObject rawProject,
|
|
string projectDirectory,
|
|
string projectFilePath,
|
|
string name,
|
|
IEnumerable<string> fallbackIncluding = null,
|
|
IEnumerable<string> additionalIncluding = null,
|
|
IEnumerable<string> additionalExcluding = null,
|
|
bool includePatternsOnly = false,
|
|
ICollection<DiagnosticMessage> warnings = null)
|
|
{
|
|
string includePropertyName = name;
|
|
additionalIncluding = additionalIncluding ?? Enumerable.Empty<string>();
|
|
var includePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, includePropertyName, defaultPatterns: fallbackIncluding)
|
|
.Concat(additionalIncluding)
|
|
.Distinct();
|
|
|
|
if (includePatternsOnly)
|
|
{
|
|
return new PatternGroup(includePatterns);
|
|
}
|
|
|
|
additionalExcluding = additionalExcluding ?? Enumerable.Empty<string>();
|
|
var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Exclude")
|
|
.Concat(additionalExcluding)
|
|
.Distinct();
|
|
|
|
var includeLiterals = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Files", literalPath: true)
|
|
.Distinct();
|
|
|
|
return new PatternGroup(includePatterns, excludePatterns, includeLiterals);
|
|
}
|
|
|
|
public IEnumerable<string> IncludeLiterals { get; }
|
|
|
|
public IEnumerable<string> IncludePatterns { get; }
|
|
|
|
public IEnumerable<string> ExcludePatterns { get; }
|
|
|
|
public IEnumerable<PatternGroup> ExcludePatternsGroup { get { return _excludeGroups; } }
|
|
|
|
public PatternGroup ExcludeGroup(PatternGroup group)
|
|
{
|
|
_excludeGroups.Add(group);
|
|
|
|
return this;
|
|
}
|
|
|
|
public IEnumerable<string> SearchFiles(string rootPath)
|
|
{
|
|
// literal included files are added at the last, but the search happens early
|
|
// so as to make the process fail early in case there is missing file. fail early
|
|
// helps to avoid unnecessary globing for performance optimization
|
|
var literalIncludedFiles = new List<string>();
|
|
foreach (var literalRelativePath in IncludeLiterals)
|
|
{
|
|
var fullPath = Path.GetFullPath(Path.Combine(rootPath, literalRelativePath));
|
|
|
|
if (!File.Exists(fullPath))
|
|
{
|
|
throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath));
|
|
}
|
|
|
|
// TODO: extract utility like NuGet.PathUtility.GetPathWithForwardSlashes()
|
|
literalIncludedFiles.Add(fullPath.Replace('\\', '/'));
|
|
}
|
|
|
|
// globing files
|
|
var globbingResults = _matcher.GetResultsInFullPath(rootPath);
|
|
|
|
// if there is no results generated in globing, skip excluding other groups
|
|
// for performance optimization.
|
|
if (globbingResults.Any())
|
|
{
|
|
foreach (var group in _excludeGroups)
|
|
{
|
|
globbingResults = globbingResults.Except(group.SearchFiles(rootPath));
|
|
}
|
|
}
|
|
|
|
return globbingResults.Concat(literalIncludedFiles).Distinct();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("Pattern group: Literals [{0}] Includes [{1}] Excludes [{2}]", string.Join(", ", IncludeLiterals), string.Join(", ", IncludePatterns), string.Join(", ", ExcludePatterns));
|
|
}
|
|
}
|
|
}
|