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> /// Attempts to get a rule corresponding to the path /// </summary> public bool TryGetRule(AbsolutePath path, out DirectoryMembershipFingerprinterRule rule) { if (!m_rules.TryGetValue(path, out rule)) { if (m_parent != null) { return(m_parent.TryGetRule(path, out rule)); } return(false); } return(true); }
private static DirectoryMembershipFingerprinterRuleSet Deserialize(BuildXLReader reader, DirectoryMembershipFingerprinterRuleSet parent) { int ruleCount = reader.ReadInt32Compact(); List <DirectoryMembershipFingerprinterRule> rules = new List <DirectoryMembershipFingerprinterRule>(ruleCount); for (int i = 0; i < ruleCount; i++) { rules.Add(DirectoryMembershipFingerprinterRule.Deserialize(reader)); } List <string> searchPathEnumerationTools = null; if (reader.ReadBoolean()) { var count = reader.ReadInt32Compact(); searchPathEnumerationTools = new List <string>(); for (int i = 0; i < count; i++) { var tool = reader.ReadString(); searchPathEnumerationTools.Add(tool); } } DirectoryMembershipFingerprinterRuleSet result; Dictionary <ModuleId, DirectoryMembershipFingerprinterRuleSet> moduleRuleSets = null; if (reader.ReadBoolean()) { moduleRuleSets = new Dictionary <ModuleId, DirectoryMembershipFingerprinterRuleSet>(); result = new DirectoryMembershipFingerprinterRuleSet(rules, moduleRuleSets, searchPathEnumerationTools, parent); var count = reader.ReadInt32Compact(); for (int i = 0; i < count; i++) { var moduleId = reader.ReadModuleId(); var moduleRuleSet = Deserialize(reader, result); result.m_moduleRuleSets.Add(moduleId, moduleRuleSet); } } else { result = new DirectoryMembershipFingerprinterRuleSet(rules, moduleRuleSets, searchPathEnumerationTools, parent); } return(result); }
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); }