private void AddPackageRootFilesFromItems(ICollection <ProjectItemInstance> items, string projectFolder, string packageRootPath, ProjectPredictionReporter predictionReporter) { foreach (ProjectItemInstance item in items) { string relativePath = item.EvaluatedInclude; // If it's not a valid path, don't process it. if (relativePath.IndexOfAny(Path.GetInvalidPathChars()) != -1) { continue; } // Check whether the file is directly included from within the package root folder. string packageFileFullPath = Path.GetFullPath(Path.Combine(projectFolder, relativePath)); if (packageFileFullPath.StartsWith(packageRootPath, StringComparison.OrdinalIgnoreCase)) { predictionReporter.ReportInputFile(packageFileFullPath); continue; } // Check whether the file is referenced elsewhere but linked to be under the package root folder. string linkMetadata = item.GetMetadataValue("Link"); if (!string.IsNullOrEmpty(linkMetadata)) { string linkFullPath = Path.GetFullPath(Path.Combine(projectFolder, linkMetadata)); if (linkFullPath.StartsWith(packageRootPath, StringComparison.OrdinalIgnoreCase)) { predictionReporter.ReportInputFile(packageFileFullPath); continue; } } } }
private void ReportInputAndRelatedFiles( string referencePath, string projectDirectory, List <string> relatedFileExtensions, ProjectPredictionReporter predictionReporter) { var referenceFullPath = Path.GetFullPath(Path.Combine(projectDirectory, referencePath)); predictionReporter.ReportInputFile(referenceFullPath); // If the reference doesn't exist, it might be generated by the build. // In that case, we can't know for sure whether there will be related // files or not, so don't bother trying in that case. if (!File.Exists(referenceFullPath)) { return; } foreach (var ext in relatedFileExtensions) { var relatedFile = Path.ChangeExtension(referenceFullPath, ext); if (File.Exists(relatedFile)) { predictionReporter.ReportInputFile(relatedFile); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This predictor only applies to sqlproj files if (!projectInstance.FullPath.EndsWith(".sqlproj", StringComparison.OrdinalIgnoreCase)) { return; } foreach (ProjectItemInstance item in projectInstance.GetItems(BuildItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } foreach (ProjectItemInstance item in projectInstance.GetItems(PostDeployItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } foreach (ProjectItemInstance item in projectInstance.GetItems(PreDeployItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { var seenGraphNodes = new HashSet <ProjectGraphNode>(projectGraphNode.ProjectReferences); var graphNodesToProcess = new Queue <ProjectGraphNode>(projectGraphNode.ProjectReferences); while (graphNodesToProcess.Count > 0) { ProjectGraphNode currentNode = graphNodesToProcess.Dequeue(); // Predict the project file itself and all its imports. predictionReporter.ReportInputFile(currentNode.ProjectInstance.FullPath); foreach (string import in currentNode.ProjectInstance.ImportPaths) { predictionReporter.ReportInputFile(import); } // Recurse transitively foreach (ProjectGraphNode projectReference in currentNode.ProjectReferences) { if (seenGraphNodes.Add(projectReference)) { graphNodesToProcess.Enqueue(projectReference); } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { predictionReporter.ReportInputFile(projectInstance.FullPath); foreach (string importPath in projectInstance.ImportPaths) { predictionReporter.ReportInputFile(importPath); } }
public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { foreach (ProjectGraphNode dependency in projectGraphNode.ProjectReferences) { var dependencyDir = dependency.ProjectInstance.Directory; foreach (string item in _inputFiles) { predictionReporter.ReportInputFile(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _inputDirectories) { predictionReporter.ReportInputDirectory(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _outputFiles) { predictionReporter.ReportOutputFile(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _outputDirectories) { predictionReporter.ReportOutputDirectory(Path.GetFullPath(Path.Combine(dependencyDir, item))); } } }
private static void ReportCopyToPublishDirectoryItems( ProjectInstance projectInstance, string itemName, string publishDir, ProjectPredictionReporter predictionReporter) { foreach (ProjectItemInstance item in projectInstance.GetItems(itemName)) { var copyToPublishDirectoryValue = item.GetMetadataValue(CopyToPublishDirectoryMetadataName); if (copyToPublishDirectoryValue.Equals("Always", StringComparison.OrdinalIgnoreCase) || copyToPublishDirectoryValue.Equals("PreserveNewest", StringComparison.OrdinalIgnoreCase)) { // The item will be relative to the project instance passed in, not the current project instance, so make the path absolute. predictionReporter.ReportInputFile(Path.Combine(projectInstance.Directory, item.EvaluatedInclude)); if (!string.IsNullOrEmpty(publishDir)) { string targetPath = item.GetTargetPath(); if (!string.IsNullOrEmpty(targetPath)) { predictionReporter.ReportOutputFile(Path.Combine(publishDir, targetPath)); } } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { string ruleSetPath = projectInstance.GetPropertyValue(CodeAnalysisRuleSetPropertyName); if (string.IsNullOrWhiteSpace(ruleSetPath)) { // Bail out fast if no rulset is configured. return; } string ruleSetDirectoriesStr = projectInstance.GetPropertyValue(CodeAnalysisRuleSetDirectoriesPropertyName); List <string> ruleSetDirectories = string.IsNullOrWhiteSpace(ruleSetDirectoriesStr) ? _emptyList : ruleSetDirectoriesStr.SplitStringList(); HashSet <string> inputs = ParseRuleset( ruleSetPath, ruleSetDirectories, projectInstance.Directory, visitedRuleSets: null, isInCycle: false); foreach (string input in inputs) { predictionReporter.ReportInputFile(input); } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { foreach (ProjectItemInstance item in projectInstance.GetItems(PageItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(ApplicationIconPropertyName); if (!string.IsNullOrEmpty(assemblyOriginatorKeyFile)) { predictionReporter.ReportInputFile(assemblyOriginatorKeyFile); } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This predictor only applies to ccproj files if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase)) { return; } foreach (ProjectItemInstance item in projectInstance.GetItems(ServiceConfigurationItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } foreach (ProjectItemInstance item in projectInstance.GetItems(ServiceDefinitionItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } }
private void ReportInputsForItemType(ProjectPredictionReporter reporter, ProjectInstance projectInstance, string itemType) { ICollection <ProjectItemInstance> items = projectInstance.GetItems(itemType); if (items.Count == 0) { return; } foreach (ProjectItemInstance item in items) { reporter.ReportInputFile(item.EvaluatedInclude); } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // This predictor only applies to sfproj files if (!projectInstance.FullPath.EndsWith(".sfproj", StringComparison.OrdinalIgnoreCase)) { return; } if (projectGraphNode.ProjectReferences.Count == 0) { return; } string servicePackageRootFolder = projectInstance.GetPropertyValue(ServicePackageRootFolderPropertyName); if (string.IsNullOrEmpty(servicePackageRootFolder)) { return; } foreach (ProjectGraphNode projectReference in projectGraphNode.ProjectReferences) { // This emulates the behavior of the GetPackageRootFiles task. // We do not emulate the behavior of the FilterPackageFiles task as it requires parsing the service manifest // and the extra cost and complexity does not outweigh the slight overprediction. // For the same reason we are not doing output prediction. string projectFolder = Path.GetFullPath(Path.GetDirectoryName(projectReference.ProjectInstance.FullPath)); string fullPackageRootPath = Path.Combine(projectFolder, servicePackageRootFolder); if (fullPackageRootPath[fullPackageRootPath.Length - 1] != Path.DirectorySeparatorChar) { fullPackageRootPath += Path.DirectorySeparatorChar; } // Add files from none and content items under the package root path. // This is basically the same as the directory enumeration below, but there are some slight differences, so emulating // the odd behavior of GetPackageRootFiles is preferable to potentially being wrong. AddPackageRootFilesFromItems(projectReference.ProjectInstance.GetItems(NoneItemsPredictor.NoneItemName), projectFolder, fullPackageRootPath, predictionReporter); AddPackageRootFilesFromItems(projectReference.ProjectInstance.GetItems(ContentItemsPredictor.ContentItemName), projectFolder, fullPackageRootPath, predictionReporter); // Add files under the package root path. string[] packageRootFilesInFileSystem = Directory.GetFiles(fullPackageRootPath, "*", SearchOption.AllDirectories); foreach (string packageRootFileInFileSystem in packageRootFilesInFileSystem) { predictionReporter.ReportInputFile(packageRootFileInFileSystem); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { foreach (ProjectItemInstance item in projectInstance.GetItems(ClIncludeItemName)) { // ClInclude items aren't directly used by the build process, but they're usually read during compilation of a cpp file via #include // Because of this, they're merely a hint and might not actually be read, so check for file existence. string clIncludeFullPath = Path.Combine(projectInstance.Directory, item.EvaluatedInclude); if (File.Exists(clIncludeFullPath)) { predictionReporter.ReportInputFile(clIncludeFullPath); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { var availableItemNames = new HashSet <string>( projectInstance.GetItems(AvailableItemName).Select(item => item.EvaluatedInclude), StringComparer.OrdinalIgnoreCase); foreach (string availableItemName in availableItemNames) { foreach (ProjectItemInstance item in projectInstance.GetItems(availableItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This predictor only applies when StyleCop exists and is enabled. if (!projectInstance.Targets.ContainsKey(StyleCopTargetName) || projectInstance.GetPropertyValue(StyleCopEnabledPropertyName).Equals("false", StringComparison.OrdinalIgnoreCase)) { return; } // Find the StyleCop settings file as an input. If the override settings file is specified and valid, // it's used. Else fall back to finding the project settings file. Note that the validation or lack thereof // mimics what StyleCop actually does. string styleCopSettingsFile = TryGetOverrideSettingsFile(projectInstance, out string styleCopOverrideSettingsFile) ? styleCopOverrideSettingsFile : GetProjectSettingsFile(projectInstance.Directory); if (!string.IsNullOrEmpty(styleCopSettingsFile)) { predictionReporter.ReportInputFile(styleCopSettingsFile); } // For Completeness we should consider Compile items as well since they're passed to StyleCop, but in practice another predictor will take care of that. // StyleCop addins as input directories foreach (ProjectItemInstance item in projectInstance.GetItems(StyleCopAdditionalAddinPathsItemName)) { string addinPath = item.GetMetadataValue("FullPath"); string expandedAddinPath = Environment.ExpandEnvironmentVariables(addinPath); if (Directory.Exists(expandedAddinPath)) { predictionReporter.ReportInputDirectory(expandedAddinPath); } } // StyleCop violations file as an output string styleCopOutputFile = projectInstance.GetPropertyValue(StyleCopOutputFilePropertyName); if (!string.IsNullOrEmpty(styleCopOutputFile)) { predictionReporter.ReportOutputFile(styleCopOutputFile); } // When StyleCopCacheResults is true, a StyleCop.Cache file is written adjacent to the project. // Currently we want to avoid predicting this as predicting outputs to non-output directories generally leads to problems in the consumers of this library. // If the need for absolute completeness arises, it should be added and those consumers will just need to deal. }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This predictor only applies to ccproj files if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase)) { return; } /* * From Microsoft.WindowsAzure.targets in the CollectWorkerRoleFiles target: * <MSBuild * Projects="$(_WorkerRoleProject)" * Targets="SourceFilesProjectOutputGroup" * Properties="$(_WorkerRoleSetConfiguration);$(_WorkerRoleSetPlatform)" * ContinueOnError="false"> * <Output TaskParameter="TargetOutputs" ItemName="SourceFilesOutputGroup" /> * </MSBuild> * * <!-- Add the app config file from SourceFilesOutputGroup --> * <ItemGroup> * <WorkerFiles Include="@(SourceFilesOutputGroup)" Condition=" '%(SourceFilesOutputGroup.TargetPath)' == '$(WorkerEntryPoint).config' " > * <TargetPath>%(TargetPath)</TargetPath> * <RoleOwner>$(_WorkerRoleProject)</RoleOwner> * <RoleOwnerName>$(_WorkerRoleProjectName)</RoleOwnerName> * </WorkerFiles> * </ItemGroup> * * Effectively, it just finds project references' app.config files to copy. Note that in theory the app.config can be already named <assembly-name>.config, * but this should be uncommon so for now this is a gap we're willing to live with. * * TODO: There is a lot more logic adding WorkerFiles. However, they're generally all in the project reference's output directory or from nuget packages, * neither of which require as precise prediction. Perhaps when we have a better way to make predictions based on dependencies we can be more accurate here. */ foreach (var projectReferenceItem in projectInstance.GetItems(ProjectReferenceItemName)) { var projectReferenceRootDir = projectReferenceItem.GetMetadataValue("RootDir"); var projectReferenceDirectory = projectReferenceItem.GetMetadataValue("Directory"); var appConfigFile = projectReferenceRootDir + projectReferenceDirectory + AppConfigFileName; if (File.Exists(appConfigFile)) { predictionReporter.ReportInputFile(appConfigFile); } } }
private void ReportInputs(ProjectPredictionReporter reporter, ProjectItemInstance masmItem, HashSet <string> reportedIncludes) { reporter.ReportInputFile(masmItem.EvaluatedInclude); string[] includePaths = masmItem.GetMetadataValue(IncludePathsMetadata) .Split(IncludePathsSeparator, StringSplitOptions.RemoveEmptyEntries); // Avoid reporting paths that we've already reported for this project. foreach (string includePath in includePaths) { string trimmedPath = includePath.Trim(); if (!string.IsNullOrEmpty(trimmedPath) && reportedIncludes.Add(trimmedPath)) { reporter.ReportInputDirectory(trimmedPath); } } }
private static void ProcessFile( string sourceFile, string fileName, string[] destinationFolders, string destinationSubDirectory, ProjectPredictionReporter predictionReporter) { // Inputs predictionReporter.ReportInputFile(sourceFile); // Outputs foreach (string destination in destinationFolders) { string destinationFile = !string.IsNullOrEmpty(destinationSubDirectory) ? Path.Combine(destination, destinationSubDirectory, fileName) : Path.Combine(destination, fileName); predictionReporter.ReportOutputFile(destinationFile); } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // The key file is only an input when signing is enabled. var signAssembly = projectInstance.GetPropertyValue(SignAssemblyPropertyName); if (!signAssembly.Equals("true", StringComparison.OrdinalIgnoreCase)) { return; } var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(AssemblyOriginatorKeyFilePropertyName); if (!string.IsNullOrEmpty(assemblyOriginatorKeyFile)) { predictionReporter.ReportInputFile(assemblyOriginatorKeyFile); } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { string outDir = projectInstance.GetPropertyValue(OutDirPropertyName); foreach (ProjectItemInstance item in projectInstance.GetItems(ContentItemName)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); if (!string.IsNullOrEmpty(outDir) && item.ShouldCopyToOutputDirectory()) { string targetPath = item.GetTargetPath(); if (!string.IsNullOrEmpty(targetPath)) { predictionReporter.ReportOutputFile(Path.Combine(outDir, targetPath)); } } } }
private static void ReportCopyToOutputDirectoryItemsAsInputs( ProjectInstance projectInstance, string itemName, string outDir, ProjectPredictionReporter predictionReporter) { foreach (ProjectItemInstance item in projectInstance.GetItems(itemName)) { if (item.ShouldCopyToOutputDirectory()) { // The item will be relative to the project instance passed in, not the current project instance, so make the path absolute. predictionReporter.ReportInputFile(Path.Combine(projectInstance.Directory, item.EvaluatedInclude)); if (!string.IsNullOrEmpty(outDir)) { string targetPath = item.GetTargetPath(); if (!string.IsNullOrEmpty(targetPath)) { predictionReporter.ReportOutputFile(Path.Combine(outDir, targetPath)); } } } } }
public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { foreach (var item in _inputFiles) { predictionReporter.ReportInputFile(item); } foreach (var item in _inputDirectories) { predictionReporter.ReportInputDirectory(item); } foreach (var item in _outputFiles) { predictionReporter.ReportOutputFile(item); } foreach (var item in _outputDirectories) { predictionReporter.ReportOutputDirectory(item); } }
/// <summary> /// Parses the input and output files for copy tasks of given target. /// </summary> private static void ParseCopyTask( ProjectTargetInstance target, ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // Get all Copy tasks from targets. List <ProjectTaskInstance> tasks = target.Tasks .Where(task => string.Equals(task.Name, CopyTaskName, StringComparison.Ordinal)) .ToList(); if (tasks.Any() && projectInstance.EvaluateConditionCarefully(target.Condition)) { foreach (ProjectTaskInstance task in tasks) { if (projectInstance.EvaluateConditionCarefully(task.Condition)) { var inputs = new FileExpressionList( task.Parameters[CopyTaskSourceFiles], projectInstance, task); if (inputs.NumExpressions == 0) { continue; } foreach (var file in inputs.DedupedFiles) { predictionReporter.ReportInputFile(file); } bool hasDestinationFolder = task.Parameters.TryGetValue( CopyTaskDestinationFolder, out string destinationFolder); bool hasDestinationFiles = task.Parameters.TryGetValue( CopyTaskDestinationFiles, out string destinationFiles); if (hasDestinationFiles || hasDestinationFolder) { // Having both is an MSBuild violation, which it will complain about. if (hasDestinationFolder && hasDestinationFiles) { continue; } string destination = destinationFolder ?? destinationFiles; var outputs = new FileExpressionList(destination, projectInstance, task); // When using batch tokens, the user should specify exactly one total token, and it must appear in both the input and output. // Doing otherwise should be a BuildCop error. If not using batch tokens, then any number of other tokens is fine. if ((outputs.NumBatchExpressions == 1 && outputs.NumExpressions == 1 && inputs.NumBatchExpressions == 1 && inputs.NumExpressions == 1) || (outputs.NumBatchExpressions == 0 && inputs.NumBatchExpressions == 0)) { ProcessOutputs(inputs, outputs, hasDestinationFolder, predictionReporter); } else { // Ignore case we cannot handle. } } else { // Ignore malformed case. } } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This predictor only applies to sfproj files if (!projectInstance.FullPath.EndsWith(".sfproj", StringComparison.OrdinalIgnoreCase)) { return; } /* * From Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets in the FixUpServiceFabricApplicationManifest target: * <ItemGroup> * <_ServiceManifestFullPath Include="@(ProjectReference -> '%(RootDir)%(Directory)$(ServicePackageRootFolder)\ServiceManifest.xml')" /> * </ItemGroup> * * <FindServiceManifests ApplicationPackageRootFolder="$(ApplicationPackageRootFolder)"> * <Output TaskParameter="ServiceManifestFiles" ItemName="_ServiceManifestFullPath" /> * </FindServiceManifests> * * Then it runs a cleanup util on @(_ServiceManifestFullPath), making them all inputs. */ // FixUpServiceFabricApplicationManifest has a condition: '@(ProjectReference)' != '' AND '$(UpdateServiceFabricApplicationManifestEnabled)' == 'true' // Weirdly the target is skipped if there are no project references even if there are extra service manifests in the ApplicationPackageRootFolder var updateServiceFabricApplicationManifestEnabled = projectInstance.GetPropertyValue(UpdateServiceFabricApplicationManifestEnabledPropertyName); var projectReferenceItems = projectInstance.GetItems(ProjectReferenceItemName); if (projectReferenceItems.Count == 0 || !updateServiceFabricApplicationManifestEnabled.Equals("true", StringComparison.OrdinalIgnoreCase)) { return; } var servicePackageRootFolder = projectInstance.GetPropertyValue(ServicePackageRootFolderPropertyName); foreach (var projectReferenceItem in projectReferenceItems) { // Equivalent of '%(RootDir)%(Directory)$(ServicePackageRootFolder)\ServiceManifest.xml' var projectReferenceRootDir = projectReferenceItem.GetMetadataValue("RootDir"); var projectReferenceDirectory = projectReferenceItem.GetMetadataValue("Directory"); var serviceManifestFile = projectReferenceRootDir + projectReferenceDirectory + servicePackageRootFolder + Path.DirectorySeparatorChar + ServiceManifestFileName; predictionReporter.ReportInputFile(serviceManifestFile); } // The FindServiceManifests task simply enumerates the directories in $(ApplicationPackageRootFolder) looking for ServiceManifest.xml files. var applicationPackageRootFolder = projectInstance.GetPropertyValue(ApplicationPackageRootFolderPropertyName); if (!Path.IsPathRooted(applicationPackageRootFolder)) { applicationPackageRootFolder = Path.Combine(projectInstance.Directory, applicationPackageRootFolder); } foreach (string directory in Directory.EnumerateDirectories(applicationPackageRootFolder)) { string serviceManifestFile = Path.Combine(directory, ServiceManifestFileName); if (File.Exists(serviceManifestFile)) { predictionReporter.ReportInputFile(serviceManifestFile); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // This is based on NuGet.Build.Tasks.Pack.targets and GetPackOutputItemsTask // See: https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets // See: https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Build.Tasks.Pack/GetPackOutputItemsTask.cs var generatePackageOnBuild = projectInstance.GetPropertyValue(GeneratePackageOnBuildPropertyName); if (!generatePackageOnBuild.Equals("true", StringComparison.OrdinalIgnoreCase)) { return; } var packageId = projectInstance.GetPropertyValue(PackageIdPropertyName); var packageVersion = projectInstance.GetPropertyValue(PackageVersionPropertyName); var packageOutputPath = projectInstance.GetPropertyValue(PackageOutputPathPropertyName); var nuspecOutputPath = projectInstance.GetPropertyValue(NuspecOutputPathPropertyName); var includeSource = projectInstance.GetPropertyValue(IncludeSourcePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase); var includeSymbols = projectInstance.GetPropertyValue(IncludeSymbolsPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase); var outputFileNamesWithoutVersion = projectInstance.GetPropertyValue(OutputFileNamesWithoutVersionPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase); var symbolPackageFormat = projectInstance.GetPropertyValue(SymbolPackageFormatPropertyName); // PackageOutputPath defaults to OutputPath in the _CalculateInputsOutputsForPack target, not statically. if (string.IsNullOrEmpty(packageOutputPath)) { packageOutputPath = projectInstance.GetPropertyValue(OutputPathPropertyName); } // All params are effectively required if (!string.IsNullOrEmpty(packageId) && !string.IsNullOrEmpty(packageVersion) && !string.IsNullOrEmpty(packageOutputPath) && !string.IsNullOrEmpty(nuspecOutputPath) && !string.IsNullOrEmpty(symbolPackageFormat)) { var fileBaseName = outputFileNamesWithoutVersion ? packageId : $"{packageId}.{packageVersion}"; // Nuspec files can also be provided instead of generated, in which case we should treat it like an input, not an output. var nuspecFile = projectInstance.GetPropertyValue(NuspecFilePropertyName); predictionReporter.ReportOutputFile(Path.Combine(packageOutputPath, fileBaseName + ".nupkg")); if (string.IsNullOrEmpty(nuspecFile)) { predictionReporter.ReportOutputFile(Path.Combine(nuspecOutputPath, fileBaseName + ".nuspec")); } else { predictionReporter.ReportInputFile(nuspecFile); } if (includeSource || includeSymbols) { predictionReporter.ReportOutputFile(Path.Combine(packageOutputPath, fileBaseName + (symbolPackageFormat.Equals("snupkg", StringComparison.OrdinalIgnoreCase) ? ".snupkg" : ".symbols.nupkg"))); if (string.IsNullOrEmpty(nuspecFile)) { predictionReporter.ReportOutputFile(Path.Combine(nuspecOutputPath, fileBaseName + ".symbols.nuspec")); } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs( ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { List <string> configFiles = FindConfigFiles(projectInstance); foreach (string configFile in configFiles) { string configFileFullPath = Path.Combine(projectInstance.Directory, configFile); string configFileContent = File.ReadAllText(configFileFullPath); bool isTsConfig = Path.GetFileName(configFile).Equals(TsConfigFileName, PathComparer.Comparison); TsConfig tsConfig; try { tsConfig = JsonSerializer.Deserialize <TsConfig>(configFileContent, _jsonSerializerOptions); } catch (JsonException) { // Ignore invalid config files continue; } string configFileDir = Path.GetDirectoryName(configFileFullPath); tsConfig.ApplyDefaults(); if (tsConfig.Files != null) { foreach (string file in tsConfig.Files) { string fileFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, file)); predictionReporter.ReportInputFile(fileFullPath); } } // Reuse MSBuild's globbing logic as it should match what tsc does. if (tsConfig.Include != null) { var directoriesToEnumerate = new Queue <string>(); var includeGlobs = new MSBuildGlob[tsConfig.Include.Count]; for (var i = 0; i < tsConfig.Include.Count; i++) { string include = tsConfig.Include[i]; MSBuildGlob includeGlob = MSBuildGlob.Parse(configFileDir, include); directoriesToEnumerate.Enqueue(includeGlob.FixedDirectoryPart); includeGlobs[i] = includeGlob; } var excludeGlobs = new MSBuildGlob[tsConfig.Exclude.Count]; for (var i = 0; i < tsConfig.Exclude.Count; i++) { string exclude = tsConfig.Exclude[i]; // Handle the case where just a folder name is used as an exclude value if (exclude.IndexOf('*', StringComparison.Ordinal) == -1) { exclude += "/**"; } excludeGlobs[i] = MSBuildGlob.Parse(configFileDir, exclude); } var finalGlob = new MSBuildGlobWithGaps(new CompositeGlob(includeGlobs), excludeGlobs); var visitedDirectories = new HashSet <string>(PathComparer.Instance); while (directoriesToEnumerate.Count > 0) { string directoryToEnumerate = directoriesToEnumerate.Dequeue(); // In case the initial globs has parent/child relationships if (!visitedDirectories.Add(directoryToEnumerate)) { continue; } // Some globs might point to non-existent paths. if (!Directory.Exists(directoryToEnumerate)) { continue; } foreach (string file in Directory.EnumerateFiles(directoryToEnumerate, "*", SearchOption.TopDirectoryOnly)) { if (finalGlob.IsMatch(file)) { predictionReporter.ReportInputFile(file); } } foreach (string directory in Directory.EnumerateDirectories(directoryToEnumerate, "*", SearchOption.TopDirectoryOnly)) { directoriesToEnumerate.Enqueue(directory); } } } if (isTsConfig && tsConfig.CompilerOptions != null) { if (!string.IsNullOrEmpty(tsConfig.CompilerOptions.OutFile)) { string outFileFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, tsConfig.CompilerOptions.OutFile)); predictionReporter.ReportOutputFile(outFileFullPath); } if (!string.IsNullOrEmpty(tsConfig.CompilerOptions.OutDir)) { string outDirFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, tsConfig.CompilerOptions.OutDir)); predictionReporter.ReportOutputDirectory(outDirFullPath); } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // This predictor only applies to ccproj files if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase)) { return; } // Emulates the behavior of the PrepareRoleItems target, specifically for web roles. ICollection <ProjectItemInstance> projectReferences = projectInstance.GetItems(ProjectReferenceItemName); var webRoleProjects = new HashSet <string>(projectReferences.Count, StringComparer.OrdinalIgnoreCase); foreach (var projectReferenceItem in projectReferences) { if (projectReferenceItem.GetMetadataValue(RoleTypeMetadataName).Equals("Web", StringComparison.OrdinalIgnoreCase)) { string webRoleProjectFullPath = Path.GetFullPath(Path.Combine(projectInstance.Directory, projectReferenceItem.EvaluatedInclude)); webRoleProjects.Add(webRoleProjectFullPath); } } // The PipelineTransformPhase target will be called on all web role projects foreach (ProjectGraphNode projectReference in projectGraphNode.ProjectReferences) { ProjectInstance referencedProjectInstance = projectReference.ProjectInstance; if (!webRoleProjects.Contains(referencedProjectInstance.FullPath)) { continue; } // The CompileTypeScript target gets triggered as a dependent target, so add predictions for TypeScriptCompile items foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(TypeScriptCompileItemsPredictor.TypeScriptCompileItemName)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.Combine(referencedProjectInstance.Directory, item.EvaluatedInclude); predictionReporter.ReportInputFile(fullPath); } // The PipelineTransformPhase target builds up FilesForPackagingFromProject items in a bunch of different CollectFilesFrom* dependent targets. // Only the ones deemed important and not covered by other predictors will be handled here. // Emulates the CollectFilesFromContent target. Note that this target grabs all Content items regardless of whether they're marked as CopyToOutputDirectory foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(ContentItemsPredictor.ContentItemName)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.Combine(referencedProjectInstance.Directory, item.EvaluatedInclude); predictionReporter.ReportInputFile(fullPath); } // Emulates the CollectFilesFromReference target. foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(ReferenceItemsPredictor.ReferenceItemName)) { if (ReferenceItemsPredictor.TryGetReferenceItemFilePath(referencedProjectInstance, item, out string filePath)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.GetFullPath(Path.Combine(referencedProjectInstance.Directory, filePath)); predictionReporter.ReportInputFile(fullPath); } } } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter) { // Non-ClickOnce applications use $(Win32Manifest) as an input to CSC, and the _SetEmbeddedWin32ManifestProperties target sets $(Win32Manifest) = $(ApplicationManifest). // ClickOnce applications don't use $(Win32Manifest) but do use $(ApplicationManifest) as an input anyway, so just always consider it an input. string applicationManifest = projectInstance.GetPropertyValue(ApplicationManifestPropertyName); if (!string.IsNullOrEmpty(applicationManifest)) { predictionReporter.ReportInputFile(applicationManifest); } // ClickOnce applications if (projectInstance.GetPropertyValue(GenerateClickOnceManifestsPropertyName).Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) { // $(_DeploymentBaseManifest) is an input to the GenerateApplicationManifest target/task, which in the _SetExternalWin32ManifestProperties // target is defined as $(ApplicationManifest) if it's set, which we've already predicted as an input above. if (string.IsNullOrEmpty(applicationManifest)) { // If $(ApplicationManifest) isn't set, $(_DeploymentBaseManifest) is set to @(_DeploymentBaseManifestWithTargetPath), which in the AssignTargetPaths target // is set to @(BaseApplicationManifest) if any or @(None) items with the '.manifest' extension otherwise. var baseApplicationManifests = projectInstance.GetItems(BaseApplicationManifestItemName); if (baseApplicationManifests.Count > 0) { foreach (ProjectItemInstance item in baseApplicationManifests) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } } else { var none = projectInstance.GetItems(NoneItemName); foreach (ProjectItemInstance item in none) { if (item.EvaluatedInclude.EndsWith(ManifestExtension, StringComparison.OrdinalIgnoreCase)) { predictionReporter.ReportInputFile(item.EvaluatedInclude); } } } } // Application manifest var applicationManifestName = projectInstance.GetPropertyValue(OutputTypePropertyName).Equals("library", StringComparison.OrdinalIgnoreCase) ? "Native." + projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ManifestExtension : projectInstance.GetPropertyValue(TargetFileNamePropertyName) + ManifestExtension; predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + applicationManifestName); predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(OutDirPropertyName) + applicationManifestName); // Deployment manifest var deploymentManifestName = projectInstance.GetPropertyValue(HostInBrowserPropertyName).Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ? projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ".xbap" : projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ".application"; predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + deploymentManifestName); predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(OutDirPropertyName) + deploymentManifestName); // Intermediate Trust info file if (!string.IsNullOrEmpty(projectInstance.GetPropertyValue(TargetZonePropertyName))) { predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + projectInstance.GetPropertyValue(TargetFileNamePropertyName) + ".TrustInfo.xml"); } } }