public DirectoryFingerprint?TryComputeDirectoryFingerprint( AbsolutePath directoryPath, CacheablePipInfo cachePipInfo, Func <EnumerationRequest, PathExistence?> tryEnumerateDirectory, bool cacheableFingerprint, DirectoryMembershipFingerprinterRule rule, DirectoryMembershipHashedEventData eventData) { Contract.Requires(directoryPath.IsValid); if (cacheableFingerprint) { Contract.Assert(!eventData.IsSearchPath); string enumerateFilter = eventData.EnumeratePatternRegex ?? RegexDirectoryMembershipFilter.AllowAllRegex; // Filesystem fingerprints and fingerprints from the full graph may be cached if the filter is AllowAll. return(m_fingerprints.GetOrAdd((directoryPath, enumerateFilter), Lazy.Create( () => TryComputeDirectoryFingerprintInternal( directoryPath, cachePipInfo, tryEnumerateDirectory, rule, eventData))).Value); } eventData.PipId = cachePipInfo.PipId; return(TryComputeDirectoryFingerprintInternal( directoryPath, cachePipInfo, tryEnumerateDirectory, rule, eventData)); }
/// <summary> /// Constructor /// </summary> public EnumerationRequest( ObjectCache <AbsolutePath, Lazy <DirectoryEnumerationResult> > cachedDirectoryContents, AbsolutePath directoryPath, CacheablePipInfo pipInfo, Action <AbsolutePath, string> handleEntry) { Contract.Requires(cachedDirectoryContents != null); Contract.Requires(handleEntry != null); Contract.Requires(pipInfo != null); Contract.Requires(directoryPath.IsValid); CachedDirectoryContents = cachedDirectoryContents; DirectoryPath = directoryPath; PipInfo = pipInfo; HandleEntry = handleEntry; }
private DirectoryFingerprint?TryComputeDirectoryFingerprintInternal( AbsolutePath directoryPath, CacheablePipInfo process, Func <EnumerationRequest, PathExistence?> tryEnumerateDirectory, DirectoryMembershipFingerprinterRule rule, DirectoryMembershipHashedEventData eventData) { var expandedDirectoryPath = directoryPath.ToString(m_context.PathTable); // Log a message if a rule to disable filesystem enumeration is being used if (rule != null && rule.DisableFilesystemEnumeration) { lock (m_pipGraphRuleSpecialCasesLogged) { if (m_pipGraphRuleSpecialCasesLogged.Add(directoryPath)) { Logger.Log.DirectoryFingerprintExercisedRule(m_loggingContext, rule.Name, expandedDirectoryPath); } } } DirectoryFingerprint result; PathExistence? existence; int numMembers = 0; using (var pooledList = Pools.GetStringList()) { var directoryMembers = new List <AbsolutePath>(); var fileNames = pooledList.Instance; // Actually perform the enumeration and compute the fingerprint Action <AbsolutePath, string> handleEntry = (path, fileName) => { if (rule != null && !rule.DisableFilesystemEnumeration) { if (rule.ShouldIgnoreFileWhenEnumerating(fileName)) { Logger.Log.DirectoryFingerprintExercisedRule(m_loggingContext, rule.Name, path.ToString(m_context.PathTable)); return; } } fileNames.Add(fileName); directoryMembers.Add(path); }; existence = tryEnumerateDirectory(new EnumerationRequest(CachedDirectoryContents, directoryPath, process, handleEntry)); if (existence == null) { return(null); } numMembers = fileNames.Count; // we sort members here, so they are stored in the same order they are added to a fingerprint in CalculateDirectoryFingerprint directoryMembers.Sort(m_context.PathTable.ExpandedPathComparer); eventData.Members = directoryMembers; result = CalculateDirectoryFingerprint(fileNames); } switch (existence) { case PathExistence.ExistsAsDirectory: case PathExistence.ExistsAsFile: // The file can be a directory symlink or junction, in which case it is classified as a file. break; case PathExistence.Nonexistent: // We return an all-zero fingerprint for a non-existent path. // This is equivalent to the static-graph case (see ComputeDirectoryFingerprintFromPipGraph) // since enumerating nonexistent-on-disk path in the path table is valid (though doing so returns an empty result). Contract.Assume(result.Hash == ContentHashingUtilities.ZeroHash); break; default: throw Contract.AssertFailure("Unhandled PathExistence"); } eventData.DirectoryFingerprint = result; m_executionLog?.DirectoryMembershipHashed(eventData); if (eventData.IsStatic) { Logger.Log.DirectoryFingerprintComputedFromGraph( m_loggingContext, expandedDirectoryPath, result.ToString(), numMembers, process.Description); } else { Logger.Log.DirectoryFingerprintComputedFromFilesystem( m_loggingContext, expandedDirectoryPath, result.ToString(), numMembers); } return(result); }