private void DumpPip(Pip pip, AnalysisInput analysisInput, string dumpPath) { var dumpPipAnalyzer = new DumpPipAnalyzer(analysisInput, dumpPath, pip.SemiStableHash, directory: default, true, false);
private string GetRunningPipsMessage(string standardStatus, string perfInfo) { lock (m_runningPipsLock) { if (m_buildViewModel == null) { return(null); } var context = m_buildViewModel.Context; Contract.Assert(context != null); if (m_runningPips == null) { m_runningPips = new Dictionary <PipId, PipInfo>(); } DateTime thisCollection = DateTime.UtcNow; // Use the viewer's interface to fetch the info about which pips are currently running. foreach (var pip in m_buildViewModel.RetrieveExecutingProcessPips()) { PipInfo runningInfo; if (!m_runningPips.TryGetValue(pip.PipId, out runningInfo)) { // This is a new pip that wasn't running the last time the currently running pips were queried Pip p = pip.HydratePip(); runningInfo = new PipInfo() { PipDescription = p.GetShortDescription(context), FirstSeen = DateTime.UtcNow, }; m_runningPips.Add(pip.PipId, runningInfo); } runningInfo.LastSeen = DateTime.UtcNow; } // Build up a string based on the snapshot of what pips are being running using (var pooledWrapper = Pools.StringBuilderPool.GetInstance()) { StringBuilder sb = pooledWrapper.Instance; sb.Append(TimeSpanToString(TimeDisplay.Seconds, DateTime.UtcNow - BaseTime)); sb.Append(' '); sb.Append(standardStatus); if (!string.IsNullOrWhiteSpace(perfInfo)) { sb.Append(". " + perfInfo); } // Display the log file location if there have been errors logged. This allows the user to open the // log files while the build is running to see errors that have scrolled off the console var errors = Interlocked.Read(ref m_errorsLogged); if (errors > 0 && m_logsDirectory != null) { sb.AppendLine(); sb.AppendFormat(Strings.App_Errors_LogsDirectory, errors, m_logsDirectory); } int pipCount = 0; foreach (var item in m_runningPips.ToArray().OrderBy(kvp => kvp.Value.FirstSeen)) { if (item.Value.LastSeen < thisCollection) { // If the pip was last seen before this collection it is no longer running and should be removed m_runningPips.Remove(item.Key); } else { pipCount++; if (pipCount <= m_maxStatusPips) { // Otherwise include it in the string string info = string.Format(CultureInfo.InvariantCulture, " {0} {1}", TimeSpanToString(TimeDisplay.Seconds, item.Value.LastSeen - item.Value.FirstSeen), item.Value.PipDescription); // Don't have a trailing newline for the last message; if (sb.Length > 0) { sb.AppendLine(); } sb.Append(info); } } } if (pipCount > m_maxStatusPips) { sb.AppendLine(); sb.AppendFormat(Strings.ConsoleListener_AdditionalPips, pipCount - m_maxStatusPips); } return(sb.ToString()); } } }
/// <summary> /// Checks if a pip is a service related pip. /// </summary> /// <param name="pip"></param> /// <returns></returns> public static bool IsServiceRelatedPip(Pip pip) => ServiceKind(pip) != ServicePipKind.None;
private string GetSealDescription(Pip pip) { SealDirectory seal = (SealDirectory)pip; return($"[{seal.Kind}] {GetDescription(pip)}"); }
private bool ArePipsConcurrent(Pip a, Pip b) { return((a.PipId.Value >= m_concurrentStart && a.PipId.Value <= m_concurrentStop) && (b.PipId.Value >= m_concurrentStart && b.PipId.Value <= m_concurrentStop)); }
private static async Task <PipResult> Execute(BuildXLContext context, FileContentTable fileContentTable, IConfiguration config, Pip pip, (string substSource, string substTarget)?subst)
private string Describe(Pip pip) { return(pip.GetShortDescription(m_analyzer.CachedGraph.Context)); }
private bool CreateLogPathAndRun(Pip pip, PipGraph graph) { DumpPipLiteAnalysisUtilities.CreateLoggingDirectory(m_logPath, LoggingContext); return(DumpPipLiteAnalysisUtilities.DumpPip(pip, m_logPath, Context.PathTable, Context.StringTable, Context.SymbolTable, graph, LoggingContext)); }
private string GetDumpFilePath(Pip pip) { return(Path.Combine(m_logPath, $"{pip.FormattedSemiStableHash}.json")); }
/// <summary> /// Adds the output files of the pip to the set /// </summary> protected static void AddOutputs(Pip pip, HashSet <FileOrDirectoryArtifact> outputs) { ForEachOutput(outputs, pip, (outputs2, output) => outputs2.Add(output)); }
private void LogAzureDevOpsIssue(EventWrittenEventArgs eventData, string eventType) { var builder = new StringBuilder(); builder.Append("##vso[task.logIssue type="); builder.Append(eventType); var message = eventData.Message; var args = eventData.Payload == null?CollectionUtilities.EmptyArray <object>() : eventData.Payload.ToArray(); string body; // see if this event provides provenance info if (message.StartsWith(EventConstants.ProvenancePrefix, StringComparison.Ordinal)) { Contract.Assume(args.Length >= 3, "Provenance prefix contains 3 formatting tokens."); // file builder.Append(";sourcepath="); builder.Append(args[0]); //line builder.Append(";linenumber="); builder.Append(args[1]); //column builder.Append(";columnnumber="); builder.Append(args[2]); //code builder.Append(";code=DX"); builder.Append(eventData.EventId.ToString("D4")); } var newArgs = args; // construct a short message for ADO console if ((eventData.EventId == (int)LogEventId.PipProcessError) || (eventData.EventId == (int)SharedLogEventId.DistributionWorkerForwardedError && (int)args[1] == (int)LogEventId.PipProcessError)) { var pipProcessError = new PipProcessErrorEventFields(eventData.Payload, eventData.EventId != (int)LogEventId.PipProcessError); args[0] = Pip.FormatSemiStableHash(pipProcessError.PipSemiStableHash); args[1] = pipProcessError.ShortPipDescription; args[2] = pipProcessError.PipSpecPath; args[3] = pipProcessError.ExitCode; args[4] = pipProcessError.OptionalMessage; args[5] = pipProcessError.OutputToLog; args[6] = pipProcessError.MessageAboutPathsToLog; args[7] = pipProcessError.PathsToLog; message = "[{0}, {1}, {2}] - failed with exit code {3}, {4}\r\n{5}\r\n{6}\r\n{7}"; } else if (eventData.EventId == (int)SharedLogEventId.DistributionWorkerForwardedError || eventData.EventId == (int)SharedLogEventId.DistributionWorkerForwardedWarning) { message = "{0}"; } body = string.Format(CultureInfo.CurrentCulture, message, args); builder.Append(";]"); // substitute newlines in the message var encodedBody = body.Replace("\r\n", $"%0D%0A##[{eventType}]") .Replace("\r", $"%0D##[{eventType}]") .Replace("\n", $"%0A##[{eventType}]"); builder.Append(encodedBody); m_console.WriteOutputLine(MessageLevel.Info, builder.ToString()); }
private void WriteStaticPipDetails(Pip pip, PipExecutionContext context) { Contract.Requires(pip != null); Contract.Requires(pip.PipType != PipType.HashSourceFile); m_writer.WritePropertyName("pipId"); m_writer.WriteValue(pip.PipId.Value); if (pip.SemiStableHash != 0) { m_writer.WritePropertyName("stableId"); // The X16 format agrees with e.g. PipDC41BEE27D4187E2 which is the most user-visible presently. // See Pip.GetDescription m_writer.WriteValue(pip.SemiStableHash.ToString("X16", CultureInfo.InvariantCulture)); } if (pip.Provenance != null) { m_writer.WritePropertyName("provenance"); m_writer.WriteStartObject(); { m_writer.WritePropertyName("value"); m_writer.WriteValue(pip.Provenance.OutputValueSymbol.ToString(context.SymbolTable)); m_writer.WritePropertyName("spec"); m_writer.WriteValue(pip.Provenance.Token.Path.ToString(context.PathTable)); } m_writer.WriteEndObject(); } m_writer.WritePropertyName("type"); m_writer.WriteValue(pip.PipType.ToString()); m_writer.WritePropertyName("description"); m_writer.WriteValue(pip.GetDescription(context)); var process = pip as Process; if (process != null) { m_writer.WritePropertyName("exe"); m_writer.WriteValue(process.GetToolName(context.PathTable).ToString(context.StringTable)); if (process.Semaphores != null && process.Semaphores.Length > 0) { m_writer.WritePropertyName("semaphores"); m_writer.WriteStartArray(); foreach (ProcessSemaphoreInfo semaphore in process.Semaphores) { m_writer.WriteStartObject(); m_writer.WritePropertyName("name"); m_writer.WriteValue(semaphore.Name.ToString(context.StringTable)); m_writer.WritePropertyName("value"); m_writer.WriteValue(semaphore.Value); m_writer.WritePropertyName("limit"); m_writer.WriteValue(semaphore.Limit); m_writer.WriteEndObject(); } m_writer.WriteEndArray(); } } }
private void WriteGraphNodeEntry( Pip pip, IPipScheduleTraversal graph, PipExecutionContext context, Dictionary <DirectoryArtifact, int> directoryIds, Dictionary <PipId, ProcessExecutionMonitoringReportedEventData> directoryInputContent, Dictionary <PipId, PipExecutionDirectoryOutputs> directoryOutputContent) { Contract.Requires(pip != null); m_writer.WriteWhitespace(Environment.NewLine); m_writer.WriteStartObject(); { WriteStaticPipDetails(pip, context); { // We get nice space savings by omitting dependsOn when it is empty (think HashSourceFile and WriteFile pips). bool writtenHeader = false; foreach (var dependency in graph.RetrievePipImmediateDependencies(pip)) { if (!writtenHeader) { m_writer.WritePropertyName("dependsOn"); m_writer.WriteStartArray(); writtenHeader = true; } if (IncludePip(dependency.PipType)) { m_writer.WriteValue(dependency.PipId.Value); } } if (writtenHeader) { m_writer.WriteEndArray(); } writtenHeader = false; PipArtifacts.ForEachInput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact.Path, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (dependency of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (input of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } if (!writtenHeader) { m_writer.WritePropertyName("consumes"); m_writer.WriteStartArray(); writtenHeader = true; } m_writer.WriteValue(dependencyId); return(true); }, includeLazyInputs: true); // Write reads from shared opaque directories if (directoryInputContent.TryGetValue(pip.PipId, out var pipInput)) { foreach (var input in pipInput.ReportedFileAccesses) { int dependencyId; if (!m_fileIds.TryGetValue(input.ManifestPath, out dependencyId)) { // Ignore unrecognized reads (these are usually directories / files that aren't produced, so we don't have their ID) continue; } m_writer.WriteValue(dependencyId); } } if (writtenHeader) { m_writer.WriteEndArray(); } } { m_writer.WritePropertyName("produces"); m_writer.WriteStartArray(); SortedSet <int> reads = new SortedSet <int>(); PipArtifacts.ForEachOutput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact.Path, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } reads.Add(dependencyId); return(true); }, includeUncacheable: true); // Write outputs into shared opaque directories if (directoryOutputContent.TryGetValue(pip.PipId, out var pipOutput)) { foreach (var output in pipOutput.DirectoryOutputs) { DirectoryArtifact dir = output.directoryArtifact; var content = output.fileArtifactArray; foreach (var file in content) { int dependencyId; if (!m_fileIds.TryGetValue(file.Path, out dependencyId)) { Contract.Assume(false, "Expected file artifact not found in fileId table " + file.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } reads.Add(dependencyId); } } } foreach (int dependencyId in reads) { m_writer.WriteValue(dependencyId); } m_writer.WriteEndArray(); } } m_writer.WriteEndObject(); }
private void WriteGraphNodeEntry( Pip pip, IPipScheduleTraversal graph, PipExecutionContext context, Dictionary <DirectoryArtifact, int> directoryIds) { Contract.Requires(pip != null); m_writer.WriteWhitespace(Environment.NewLine); m_writer.WriteStartObject(); { WriteStaticPipDetails(pip, context); { // We get nice space savings by omitting dependsOn when it is empty (think HashSourceFile and WriteFile pips). bool writtenHeader = false; foreach (var dependency in graph.RetrievePipImmediateDependencies(pip)) { if (!writtenHeader) { m_writer.WritePropertyName("dependsOn"); m_writer.WriteStartArray(); writtenHeader = true; } if (IncludePip(dependency.PipType)) { m_writer.WriteValue(dependency.PipId.Value); } } if (writtenHeader) { m_writer.WriteEndArray(); } writtenHeader = false; PipArtifacts.ForEachInput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (dependency of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (input of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } if (!writtenHeader) { m_writer.WritePropertyName("consumes"); m_writer.WriteStartArray(); writtenHeader = true; } m_writer.WriteValue(dependencyId); return(true); }, includeLazyInputs: true); if (writtenHeader) { m_writer.WriteEndArray(); } } { m_writer.WritePropertyName("produces"); m_writer.WriteStartArray(); PipArtifacts.ForEachOutput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } m_writer.WriteValue(dependencyId); return(true); }, includeUncacheable: true); m_writer.WriteEndArray(); } } m_writer.WriteEndObject(); }
public ObjectInfo GetObjectInfo(object context, object obj) { obj = obj is EvaluationResult evalResult ? evalResult.Value : obj; if (obj == null || IsInvalid(obj)) { return(s_nullObj); } if (obj.GetType().IsArray) { return(ArrayObjInfo(((IEnumerable)obj).Cast <object>().ToArray())); } var customResult = m_customRenderer?.Invoke(this, context, obj); if (customResult != null) { return(customResult); } return(obj switch { ScopeLocals scope => new ObjectInfo(LocalsScopeName, null, Lazy.Create(() => GetLocalsForStackEntry(scope.EvalState, scope.FrameIndex))), ScopePipGraph scope => PipGraphInfo(scope.Graph).WithPreview(PipGraphScopeName), ScopeAllModules scope => ArrayObjInfo(scope.EvaluatedModules.ToArray()).WithPreview(EvaluatedModulesScopeName), IModuleAndContext mc => GetObjectInfo(mc.Tree.RootContext, mc.Module), ObjectInfo objInf => objInf, IPipGraph graph => PipGraphInfo(graph), Pip pip => GenericObjectInfo(pip, $"<{pip.PipType}>").Build(), PipProvenance prov => ProvenanceInfo(prov), EnvironmentVariable envVar => EnvironmentVariableInfo(envVar), PipFragment pipFrag => PipFragmentInfo(context, pipFrag), Thunk thunk => thunk.Value != null?GetObjectInfo(context, thunk.Value) : new ObjectInfo("<not evaluated>"), FunctionLikeExpression lambda => LambdaInfo(lambda), Closure cls => LambdaInfo(cls.Function), SymbolAtom sym => new ObjectInfo(sym.ToString(StringTable)), StringId id => new ObjectInfo(id.ToString(StringTable)), PipId id => new ObjectInfo($"{id.Value}"), UndefinedLiteral _ => new ObjectInfo("undefined", UndefinedLiteral.Instance), UndefinedValue _ => new ObjectInfo("undefined", UndefinedValue.Instance), AbsolutePath path => new ObjectInfo($"p`{path.ToString(PathTable)}`", path), RelativePath path => new ObjectInfo($"r`{path.ToString(StringTable)}`", path), PathAtom atom => new ObjectInfo($"a`{atom.ToString(StringTable)}`", atom), FileArtifact file => new ObjectInfo($"f`{file.Path.ToString(PathTable)}`", file), DirectoryArtifact dir => new ObjectInfo($"d`{dir.Path.ToString(PathTable)}`", dir), int num => new ObjectInfo($"{num}"), uint num => new ObjectInfo($"{num}"), short num => new ObjectInfo($"{num}", (int)num), long num => new ObjectInfo($"{num}"), char ch => new ObjectInfo($"'{ch}'", ch.ToString()), string str => new ObjectInfo($"\"{str}\"", str), Enum e => new ObjectInfo($"{e.GetType().Name}.{e}", e), NumberLiteral numLit => new ObjectInfo(numLit.UnboxedValue.ToString(), numLit), Func <object> func => FuncObjInfo(func), ArraySegment <object> arrSeg => ArrayObjInfo(arrSeg), IEnumerable enu => new ObjectInfoBuilder().Preview("IEnumerable").Prop("Result", Lazy.Create <object>(() => enu.Cast <object>().ToArray())).Build(), ArrayLiteral arrLit => ArrayObjInfo(arrLit.Values.Select(v => v.Value).ToArray()).WithOriginal(arrLit), ModuleBinding binding => GetObjectInfo(context, binding.Body), ErrorValue error => ErrorValueInfo(), object o => GenericObjectInfo(o).Build(), _ => s_nullObj });
private void AssertCommon(bool success, Pip pip, PipGraph graph) { Assert.True(success); Assert.True(File.Exists(GetDumpFilePath(pip))); Assert.True(VerifyContentWrittenToFile(pip, graph)); }
private static async Task <bool> CreateAndRunPip( PipProgram program, string tempDirectory, string outFile, IEnumerable <string> restInstructions, bool is64Bit) { Contract.Requires(restInstructions != null); Contract.Requires(tempDirectory != null); Contract.Requires(!string.IsNullOrEmpty(outFile)); BuildXLContext context = BuildXLContext.CreateInstanceForTesting(); using (var fileAccessListener = new FileAccessListener(Events.Log)) { fileAccessListener.RegisterEventSource(BuildXL.Processes.ETWLogger.Log); var loggingContext = BuildXLTestBase.CreateLoggingContextForTest(); var fileContentTable = FileContentTable.CreateNew(loggingContext); var config = ConfigurationHelpers.GetDefaultForTesting(context.PathTable, AbsolutePath.Create(context.PathTable, Path.Combine(tempDirectory, "config.dc"))); config.Sandbox.LogObservedFileAccesses = true; Pip pip = null; var instructions = restInstructions as string[] ?? restInstructions.ToArray(); switch (program) { case PipProgram.Cmd: pip = CreateCmdPip(context, tempDirectory, outFile, is64Bit); break; case PipProgram.Self: pip = CreateSelfPip(context, tempDirectory, outFile, instructions, is64Bit); break; } Contract.Assume(pip != null); var isSubstUsed = FileUtilities.TryGetSubstSourceAndTarget(tempDirectory, out var substSource, out var substTarget, out var errorMessage); XAssert.IsFalse(!isSubstUsed && errorMessage != null, errorMessage); PipResult executeResult = await Execute( context, fileContentTable, config, pip, isSubstUsed ?(substSource, substTarget) : default((string, string)?)); bool valid = false; switch (program) { case PipProgram.Cmd: valid = ValidateCmd(fileAccessListener.FileAccesses, outFile, is64Bit); break; case PipProgram.Self: valid = ValidateSelf( fileAccessListener.FileAccesses, instructions.Length > 0 ? instructions[0] : string.Empty, outFile, is64Bit); break; } return(executeResult.Status == PipResultStatus.Succeeded && valid); } }
/// <summary> /// Gets the inputs consumed by a pip and calls an action /// </summary> public static bool ForEachInput( Pip pip, Func <FileOrDirectoryArtifact, bool> inputAction, bool includeLazyInputs, Func <FileOrDirectoryArtifact, bool> overrideLazyInputAction = null) { // NOTE: Lazy inputs must be processed AFTER regular inputs // This behavior is required by FileContentManager.PopulateDepdencies bool result = true; switch (pip.PipType) { case PipType.CopyFile: CopyFile copyFile = (CopyFile)pip; result = inputAction(FileOrDirectoryArtifact.Create(copyFile.Source)); break; case PipType.Process: Process process = (Process)pip; foreach (var input in process.Dependencies) { if (!inputAction(FileOrDirectoryArtifact.Create(input))) { return(false); } } foreach (var input in process.DirectoryDependencies) { if (!inputAction(FileOrDirectoryArtifact.Create(input))) { return(false); } } break; case PipType.SealDirectory: SealDirectory sealDirectory = (SealDirectory)pip; foreach (var input in sealDirectory.Contents) { if (!inputAction(FileOrDirectoryArtifact.Create(input))) { return(false); } } break; case PipType.Ipc: IpcPip ipcPip = (IpcPip)pip; foreach (var input in ipcPip.FileDependencies) { if (!inputAction(FileOrDirectoryArtifact.Create(input))) { return(false); } } foreach (var input in ipcPip.DirectoryDependencies) { if (!inputAction(FileOrDirectoryArtifact.Create(input))) { return(false); } } if (includeLazyInputs) { overrideLazyInputAction = overrideLazyInputAction ?? inputAction; foreach (var input in ipcPip.LazilyMaterializedDependencies) { if (!overrideLazyInputAction(input)) { return(false); } } } break; } return(result); }
public bool TryGetTempDirectoryAncestor(AbsolutePath path, out Pip pip, out AbsolutePath temPath) { temPath = AbsolutePath.Invalid; pip = null; return(false); }
/// <summary> /// Prepares a pip to be serialized. /// </summary> /// <param name="pip"></param> /// <param name="dynamicData"></param> /// <param name="pathTable"></param> /// <param name="stringTable"></param> /// <param name="symbolTable"></param> /// <param name="pipGraph"></param> /// <returns>Serialized Pip object.</returns> public static SerializedPip CreateObjectForSerialization(Pip pip, ProcessExecutionMonitoringReportedEventData?dynamicData, PathTable pathTable, StringTable stringTable, SymbolTable symbolTable, PipGraph pipGraph) { SerializedPip serializedPip = new SerializedPip { PipMetaData = CreatePipMetadata(pip, pathTable, stringTable, pipGraph, symbolTable) }; switch (pip.PipType) { case PipType.CopyFile: serializedPip.CopyFileSpecificDetails = CreateCopyFileSpecificDetails((CopyFile)pip, pathTable); break; case PipType.Process: serializedPip.ProcessSpecificDetails = CreateProcessSpecificDetails((Process)pip, pathTable, stringTable, pipGraph); break; case PipType.Ipc: serializedPip.IpcSpecificDetails = CreateIpcSpecificDetails((IpcPip)pip, pathTable, stringTable); break; case PipType.Value: serializedPip.ValueSpecificDetails = CreateValueSpecificDetails((ValuePip)pip, pathTable, symbolTable); break; case PipType.SpecFile: serializedPip.SpecFileSpecificDetails = CreateSpecFileSpecificDetails((SpecFilePip)pip, pathTable); break; case PipType.Module: serializedPip.ModuleSpecificDetails = CreateModuleSpecificDetails((ModulePip)pip, pathTable, stringTable); break; case PipType.HashSourceFile: serializedPip.HashSourceFileSpecificDetails = CreateHashSourceFileSpecificDetails((HashSourceFile)pip, pathTable); break; case PipType.SealDirectory: serializedPip.SealDirectorySpecificDetails = CreateSealDirectorySpecificDetails((SealDirectory)pip, pathTable); break; case PipType.WriteFile: serializedPip.WriteFileSpecificDetails = CreateWriteFileSpecificDetails((WriteFile)pip, pathTable); break; default: Contract.Assert(false, $"Specified pip type '{pip.PipType}' does not match any known pip types."); break; } if (dynamicData.HasValue) { if (dynamicData.Value.ReportedProcesses != null && dynamicData.Value.ReportedProcesses.Count > 0) { serializedPip.ReportedProcesses = new List <ReportedProcessData>(); foreach (var reportedProcess in dynamicData.Value.ReportedProcesses) { serializedPip.ReportedProcesses.Add(CreateReportedProcessData(reportedProcess)); } } if (dynamicData.Value.ReportedFileAccesses != null && dynamicData.Value.ReportedFileAccesses.Count > 0) { serializedPip.ReportedFileAccesses = new List <ReportedFileAccessData>(); foreach (var reportedFileAccess in dynamicData.Value.ReportedFileAccesses) { serializedPip.ReportedFileAccesses.Add(CreateReportedFileAccessData(reportedFileAccess, pathTable)); } } } return(serializedPip); }
protected static bool NotMetaPip(Pip arg) => !arg.PipType.IsMetaPip();
/// <summary> /// Dumps the specified Pip to a json file named {pip.SemiStableHash}.json. /// </summary> /// <param name="pip"> Pip to be dumped. </param> /// <param name="logPath"> Directory where the pip dump will be written. </param> /// <param name="pathTable"> Path table. </param> /// <param name="stringTable"> String table. </param> /// <param name="symbolTable"> Symbol table. </param> /// <param name="pipGraph"> Pip graph for resolving qualifier ids. </param> /// <param name="loggingContext"> Logging context for logging any potential errors (can be null for post build). </param> /// <returns> True if log file was written successfully. </returns> /// <remarks> An error will be logged if this function returns false. </remarks> public static bool DumpPip(Pip pip, string logPath, PathTable pathTable, StringTable stringTable, SymbolTable symbolTable, PipGraph pipGraph, LoggingContext loggingContext) { return(DumpPip(pip, dynamicData: null, logPath, pathTable, stringTable, symbolTable, pipGraph, loggingContext)); }
public PipRefWithDetails(PipExecutionContext context, Pip pip) { SetPipRefDetails(context, pip, this); }
/// <summary> /// Creates pip info. /// </summary> public PipInfo CreatePipInfo(Pip pip) { return(new PipInfo(pip, PipContext)); }
public bool TryGetTempDirectoryAncestor(AbsolutePath path, out Pip pip, out AbsolutePath temPath) { throw new NotImplementedException(); }
private void AddPip(Pip pip) { m_pips.Enqueue(pip); pip.PipId = new PipId((uint)Interlocked.Increment(ref m_nextPipId)); }
public string GetDescription(Pip pip) { return(pip.GetDescription(PipGraph.Context)); }
/// <inheritdoc /> protected bool AddPip(Pip pip) { m_pips.Enqueue(pip); pip.PipId = new PipId((uint)Interlocked.Increment(ref m_nextPipId)); return(true); }
public void MarkExecuted(Pip executed) { bool added = m_executed.TryAdd(executed, Unit.Void); XAssert.IsTrue(added, "Executed multiple times"); }
/// <summary> /// Completes pip's independent static weak fingerprint with the fingerprints of pip's dependencies when appropriate. /// </summary> private ContentFingerprint CompleteFingerprint(PipWithFingerprint pipWithFingerprint, out string completeFingerprintText) { ContentFingerprint completeFingerprint = pipWithFingerprint.Fingerprint; completeFingerprintText = pipWithFingerprint.FingerprintText ?? string.Empty; Pip pip = pipWithFingerprint.Pip; if (pip is Process process) { if (m_sealDirectoryFingerprintLookup != null) { using (var hasher = CreateHashingHelper(true)) { hasher.Add("IndependentFingerprint", completeFingerprint.Hash); hasher.AddOrderIndependentCollection( "DirectoryDependencyFingerprints", process.DirectoryDependencies, (fp, d) => fp.Add(d.Path, m_sealDirectoryFingerprintLookup(d).Hash), DirectoryComparer); completeFingerprint = new ContentFingerprint(hasher.GenerateHash()); completeFingerprintText = FingerprintTextEnabled ? completeFingerprintText + Environment.NewLine + hasher.FingerprintInputText : completeFingerprintText; } } } else if (pip is SealDirectory sealDirectory && sealDirectory.Kind == SealDirectoryKind.SharedOpaque) { if (!sealDirectory.IsComposite) { // For non-composite shared opaque directories, contents and composed directories are always empty, and therefore the static fingerprint // is not strong enough, i.e. multiple shared opaques can share the same directory root. So in this case we need to add the fingerprint of the producer if (m_directoryProducerFingerprintLookup != null) { DirectoryArtifact directory = sealDirectory.Directory; using (var hasher = CreateHashingHelper(true)) { hasher.Add("IndependentFingerprint", completeFingerprint.Hash); hasher.Add(directory, m_directoryProducerFingerprintLookup(directory).Hash); completeFingerprint = new ContentFingerprint(hasher.GenerateHash()); completeFingerprintText = FingerprintTextEnabled ? completeFingerprintText + Environment.NewLine + hasher.FingerprintInputText : completeFingerprintText; } } } else if (sealDirectory.ComposedDirectories != null) { using (var hasher = CreateHashingHelper(true)) { hasher.Add("IndependentFingerprint", completeFingerprint.Hash); hasher.AddCollection <DirectoryArtifact, IReadOnlyList <DirectoryArtifact> >( "ComposedDirectoryFingerprints", sealDirectory.ComposedDirectories, (fp, d) => fp.Add(d.Path, m_sealDirectoryFingerprintLookup(d).Hash)); hasher.Add("ContentFilter", sealDirectory.ContentFilter.HasValue ? $"{sealDirectory.ContentFilter.Value.Kind} {sealDirectory.ContentFilter.Value.Regex}" : ""); hasher.Add("ActionKind", sealDirectory.CompositionActionKind.ToString()); completeFingerprint = new ContentFingerprint(hasher.GenerateHash()); completeFingerprintText = FingerprintTextEnabled ? completeFingerprintText + Environment.NewLine + hasher.FingerprintInputText : completeFingerprintText; } } } return(completeFingerprint); }