internal MsbuildWriter(IReadOnlyList <MsbuildFile> msbuildFiles, Context context) { m_msbuildFiles = msbuildFiles; m_context = context; m_rootExpander = new RootExpander(m_context.PathTable); m_rootExpander.Add(m_context.EnlistmentRoot, "$(EnlistmentRoot)"); m_rootExpander.Add(m_context.SolutionRoot, "$(SolutionRoot)"); m_stringReplacements = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); m_stringReplacements.Add(m_context.EnlistmentRootStr, "$(EnlistmentRoot)\\"); m_stringReplacements.Add(m_context.SolutionRootStr, "$(SolutionRoot)\\"); }
public override int Analyze() { var rootExpander = new RootExpander(PathTable); HashSet <ContentHash> hashes = new HashSet <ContentHash>(); hashes.Add(ContentHashingUtilities.ZeroHash); HashSet <FileArtifact> files = new HashSet <FileArtifact>(); foreach (var root in Roots) { rootExpander.Add(AbsolutePath.Create(PathTable, root.Key), root.Value); } Func <AbsolutePath, string> expandRoot = absPath => absPath.ToString(PathTable, rootExpander); var orderedPips = CachedGraph.PipGraph.RetrievePipReferencesOfType(PipType.Process) .Where(lazyPip => TargetSemiStableHash == null || TargetSemiStableHash == lazyPip.SemiStableHash) .Select(lazyPip => (Process)lazyPip.HydratePip()) .ToLookup(process => process.Provenance.Token.Path) .OrderBy(grouping => grouping.Key.ToString(PathTable, rootExpander)) .ToList(); using (var fingerprintStream = File.Create(DumpFilePath, bufferSize: 64 << 10 /* 64 KB */)) using (var hashWriter = new StreamWriter(DumpFilePath + ".hashes.txt")) { using ( var fingerprintArchive = CompressFile ? new ZipArchive(fingerprintStream, ZipArchiveMode.Create) : null) { using ( var writer = XmlWriter.Create( CompressFile ? fingerprintArchive.CreateEntry("dump.xml", CompressionLevel.Fastest).Open() : fingerprintStream, new XmlWriterSettings() { Indent = true })) { int doneProcesses = 0; var t = new Timer( o => { var done = doneProcesses; Console.WriteLine("Processes Done: {0} of {1}", done, orderedPips.Count); }, null, 5000, 5000); try { writer.WriteStartElement("ProcessDump"); writer.WriteAttributeString("Count", orderedPips.Count.ToString(CultureInfo.InvariantCulture)); foreach (var specPipGroup in orderedPips) { writer.WriteStartElement("SpecFile"); writer.WriteAttributeString("Path", specPipGroup.Key.ToString(PathTable, rootExpander)); foreach (var pip in specPipGroup) { doneProcesses++; writer.WriteStartElement("Process"); writer.WriteAttributeString("Name", pip.Executable.Path.ToString(PathTable, rootExpander)); writer.WriteAttributeString("CMD", RenderProcessArguments(pip)); writer.WriteElementString("Description", pip.GetDescription(PipGraph.Context)); writer.WriteStartElement("EnvironmentVariables"); foreach (var environmentVariable in pip.EnvironmentVariables) { writer.WriteStartElement("Environment"); writer.WriteAttributeString("Name", environmentVariable.Name.ToString(PathTable.StringTable)); if (environmentVariable.Value.IsValid) { writer.WriteAttributeString("Value", environmentVariable.Value.ToString(expandRoot, PathTable.StringTable, PipData.MaxMonikerRenderer)); } else { writer.WriteAttributeString("Value", "Unset"); } writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("Dependencies"); foreach (var input in pip.Dependencies) { writer.WriteStartElement("Item"); writer.WriteAttributeString("Path", input.Path.ToString(PathTable, rootExpander)); writer.WriteAttributeString("Hash", m_fileHashes.GetOrAdd(input, ContentHashingUtilities.ZeroHash).Item.Value.ToString()); writer.WriteAttributeString("RewriteCount", input.RewriteCount.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("DirectoryDependencies"); foreach (var input in pip.DirectoryDependencies) { writer.WriteStartElement("Item"); writer.WriteAttributeString("Path", input.Path.ToString(PathTable, rootExpander)); var kind = PipTable.GetSealDirectoryKind(PipGraph.GetSealedDirectoryNode(input).ToPipId()); writer.WriteAttributeString("Kind", kind.ToString()); // Print directory dependency file details when dumping a specific process if (TargetSemiStableHash != null && (kind == SealDirectoryKind.Full || kind == SealDirectoryKind.Partial)) { foreach (var file in PipGraph.ListSealedDirectoryContents(input)) { writer.WriteStartElement("Item"); writer.WriteAttributeString("Path", file.Path.ToString(PathTable, rootExpander)); writer.WriteAttributeString("Hash", m_fileHashes.GetOrAdd(file, ContentHashingUtilities.ZeroHash).Item.Value.ToString()); writer.WriteAttributeString("RewriteCount", file.RewriteCount.ToString()); writer.WriteEndElement(); } } else if (m_contents.TryGetValue(input, out var contents)) { m_observedInputs.TryGetValue(pip.PipId.Value, out var observedInputs); foreach (var file in contents) { // skip the files that were not accessed if (observedInputs != null && !observedInputs.Contains(file.Path)) { continue; } writer.WriteStartElement("Item"); writer.WriteAttributeString("Path", file.Path.ToString(PathTable, rootExpander)); writer.WriteAttributeString("Hash", m_fileHashes.GetOrAdd(file, ContentHashingUtilities.ZeroHash).Item.Value.ToString()); writer.WriteAttributeString("RewriteCount", file.RewriteCount.ToString()); writer.WriteEndElement(); } } writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("Outputs"); foreach (var input in pip.FileOutputs) { writer.WriteStartElement("Item"); if (input.RewriteCount > 1) { writer.WriteAttributeString("RewriteCount", input.RewriteCount.ToString()); } writer.WriteString(input.Path.ToString(PathTable, rootExpander)); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("DirectoryOutputs"); foreach (var output in pip.DirectoryOutputs) { writer.WriteStartElement("Directory"); { writer.WriteAttributeString("Path", output.Path.ToString(PathTable, rootExpander)); if (m_contents.TryGetValue(output, out var contents)) { writer.WriteStartElement("Contents"); { foreach (var file in contents) { writer.WriteStartElement("Item"); if (file.RewriteCount > 1) { writer.WriteAttributeString("RewriteCount", file.RewriteCount.ToString()); } writer.WriteString(file.Path.ToString(PathTable, rootExpander)); writer.WriteEndElement(); } } writer.WriteEndElement(); } } writer.WriteEndElement(); } writer.WriteEndElement(); if (pip.TempDirectory.IsValid) { writer.WriteElementString("TempDirectory", pip.TempDirectory.ToString(PathTable, rootExpander)); } writer.WriteStartElement("AdditionalTempDirectories"); foreach (var item in pip.AdditionalTempDirectories) { writer.WriteElementString("Item", item.ToString(PathTable, rootExpander)); } writer.WriteEndElement(); writer.WriteEndElement(); // Process } writer.WriteEndElement(); // SpecFile } writer.WriteEndElement(); // ProcessDump } finally { // kill and wait for the status timer to die... using (var e = new AutoResetEvent(false)) { t.Dispose(e); e.WaitOne(); } } } } } return(0); }