dotnet-installer/src/Microsoft.DotNet.ProjectModel/Files/PatternGroup.cs

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));
}
}
}