|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#if FEATURE_FILE_TRACKER
using System;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
#nullable disable
namespace Microsoft.Build.Utilities
{
internal static class CanonicalTrackedFilesHelper
{
internal const int MaxLogCount = 100;
/// <summary>
/// Check that the given composite root contains all entries in the composite sub root
/// </summary>
/// <param name="compositeRoot">The root to look for all sub roots in</param>
/// <param name="compositeSubRoot">The root that is comprised of subroots to look for</param>
/// <returns></returns>
internal static bool RootContainsAllSubRootComponents(string compositeRoot, string compositeSubRoot)
{
// If the two are identical, then clearly all keys are present
if (string.Equals(compositeRoot, compositeSubRoot, StringComparison.OrdinalIgnoreCase))
{
return true;
}
// look for each sub key in the main composite key
string[] rootComponents = compositeSubRoot.Split(MSBuildConstants.PipeChar);
foreach (string subRoot in rootComponents)
{
// we didn't find this subkey, so bail out
if (!compositeRoot.Contains(subRoot))
{
return false;
}
}
return true;
}
/// <summary>
/// This method checks that the specified files exist. During the scan the
/// most recent file write time of all the outputs is remembered. It will be
/// the basis for up to date comparisons.
/// </summary>
/// <param name="files">The files being checked for existence.</param>
/// <param name="log">The TaskLoggingHelper used to log the nonexistent files.</param>
/// <param name="outputNewestFilename">Name of the most recently modified file.</param>
/// <param name="outputNewestTime">Timestamp of the most recently modified file.</param>
/// <returns>True if all members of 'files' exist, false otherwise</returns>
internal static bool FilesExistAndRecordNewestWriteTime(ICollection<ITaskItem> files, TaskLoggingHelper log, out DateTime outputNewestTime, out string outputNewestFilename)
=> FilesExistAndRecordRequestedWriteTime(files, log, true /* return information about the newest file */, out outputNewestTime, out outputNewestFilename);
/// <summary>
/// This method checks that the specified files exist. During the scan the
/// least recent file write time of all the outputs is remembered. It will be
/// the basis for up to date comparisons.
/// </summary>
/// <param name="files">The files being checked for existence.</param>
/// <param name="log">The TaskLoggingHelper used to log the nonexistent files.</param>
/// <param name="outputOldestFilename">Name of the least recently modified file.</param>
/// <param name="outputOldestTime">Timestamp of the least recently modified file.</param>
/// <returns>True if all members of 'files' exist, false otherwise</returns>
internal static bool FilesExistAndRecordOldestWriteTime(ICollection<ITaskItem> files, TaskLoggingHelper log, out DateTime outputOldestTime, out string outputOldestFilename)
=> FilesExistAndRecordRequestedWriteTime(files, log, false /* return information about the oldest file */, out outputOldestTime, out outputOldestFilename);
private static bool FilesExistAndRecordRequestedWriteTime(ICollection<ITaskItem> files, TaskLoggingHelper log, bool getNewest, out DateTime requestedTime, out string requestedFilename)
{
bool allExist = true;
requestedTime = getNewest ? DateTime.MinValue : DateTime.MaxValue;
requestedFilename = string.Empty;
// No output files for the source were tracked
// safely assume that this is because we didn't track them because they weren't compiled
if (files == null || files.Count == 0)
{
allExist = false;
}
else
{
foreach (ITaskItem item in files)
{
DateTime lastWriteTime = NativeMethodsShared.GetLastWriteFileUtcTime(item.ItemSpec);
// If the file does not exist
if (lastWriteTime == DateTime.MinValue)
{
FileTracker.LogMessageFromResources(log, MessageImportance.Low, "Tracking_OutputDoesNotExist", item.ItemSpec);
allExist = false;
break;
}
if ((getNewest && lastWriteTime > requestedTime) || (!getNewest && lastWriteTime < requestedTime))
{
requestedTime = lastWriteTime;
requestedFilename = item.ItemSpec;
}
}
}
return allExist;
}
}
}
#endif
|