private static EvaluationResult Write(Context context, ModuleLiteral env, EvaluationStackFrame args) { var outputFilePath = Args.AsPath(args, 0); var obj = Args.AsObjectLiteral(args, 1); var quoteChar = Args.AsStringOptional(args, 2) ?? "\'"; var tags = Args.AsStringArrayOptional(args, 3); var description = Args.AsStringOptional(args, 4); var additionalOptions = GetAdditionalOptions(context.FrontEndContext, Args.AsObjectLiteralOptional(args, 5)); using (var pipDataBuilderWrapper = context.FrontEndContext.GetPipDataBuilder()) { var pipData = CreatePipData(context.StringTable, obj, quoteChar, pipDataBuilderWrapper.Instance); if (!pipData.IsValid) { return(EvaluationResult.Error); } FileArtifact result; if (!context.GetPipConstructionHelper().TryWriteFile(outputFilePath, pipData, WriteFileEncoding.Utf8, tags, description, out result, GetWriteFileOption(additionalOptions))) { // Error has been logged return(EvaluationResult.Error); } return(new EvaluationResult(result)); } }
private static EvaluationResult ReadGraphFragment(Context context, ModuleLiteral env, EvaluationStackFrame args) { var file = Args.AsFile(args, 0); var deps = Args.AsArrayLiteral(args, 1).Values.Select(v => (AbsolutePath)v.Value).ToArray(); var description = Args.AsStringOptional(args, 2) ?? file.Path.ToString(context.PathTable); if (!file.IsSourceFile) { // Do not read output file. throw new FileOperationException( new Exception( I($"Failed adding pip graph fragment file '{file.Path.ToString(context.PathTable)}' because the file is not a source file"))); } if (!context.FrontEndContext.FileSystem.Exists(file.Path)) { throw new FileOperationException(new FileNotFoundException(I($"File '{file.Path.ToString(context.PathTable)}' does not exist"))); } // Record the file, so that its content is tracked by input tracker. context.FrontEndHost.Engine.RecordFrontEndFile(file.Path, "DScript"); int id = Interlocked.Increment(ref s_uniqueFragmentId); var readFragmentResult = context.FrontEndHost.PipGraphFragmentManager.AddFragmentFileToGraph(file, description, deps); if (!readFragmentResult) { return(EvaluationResult.Error); } return(EvaluationResult.Create(file.Path)); }
private static EvaluationResult SealDirectoryHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, SealDirectoryKind sealDirectoryKind) { AbsolutePath path = Args.AsPath(args, 0, false); ArrayLiteral contents = Args.AsArrayLiteral(args, 1); var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); // Only do scrub for fully seal directory var scrub = sealDirectoryKind.IsFull() ? Args.AsBoolOptional(args, 4) : false; var fileContents = new FileArtifact[contents.Length]; for (int i = 0; i < contents.Length; ++i) { fileContents[i] = Converter.ExpectFile(contents[i], strict: false, context: new ConversionContext(pos: i, objectCtx: contents)); } var sortedFileContents = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(fileContents, OrdinalFileArtifactComparer.Instance); DirectoryArtifact sealedDirectoryArtifact; if (!context.GetPipConstructionHelper().TrySealDirectory(path, sortedFileContents, sealDirectoryKind, tags, description, null, out sealedDirectoryArtifact, scrub)) { // Error has been logged return(EvaluationResult.Error); } var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, sortedFileContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private static EvaluationResult Write(Context context, ModuleLiteral env, EvaluationStackFrame args) { var outputFilePath = Args.AsPath(args, 0); var obj = Args.AsObjectLiteral(args, 1); // Options don't have any settings yet, just here for future convenience var tags = Args.AsStringArrayOptional(args, 3); var description = Args.AsStringOptional(args, 4); using (var pipDataBuilderWrapper = context.FrontEndContext.GetPipDataBuilder()) { var pipData = CreatePipData(context.StringTable, obj, pipDataBuilderWrapper.Instance); if (!pipData.IsValid) { return(EvaluationResult.Error); } FileArtifact result; if (!context.GetPipConstructionHelper().TryWriteFile(outputFilePath, pipData, WriteFileEncoding.Utf8, tags, description, out result)) { // Error has been logged return(EvaluationResult.Error); } return(new EvaluationResult(result)); } }
private static EvaluationResult WriteFileHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, WriteFileMode mode) { var path = Args.AsPath(args, 0, false); var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); PipData pipData; switch (mode) { case WriteFileMode.WriteFile: var fileContent = Args.AsIs(args, 1); // WriteFile has a separator argument with default newline var separator = Args.AsStringOptional(args, 3) ?? Environment.NewLine; description = Args.AsStringOptional(args, 4); pipData = CreatePipDataForWriteFile(context, fileContent, separator); break; case WriteFileMode.WriteData: var data = Args.AsIs(args, 1); pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(data), new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllLines: var lines = Args.AsArrayLiteral(args, 1); var entry = context.TopStack; var newData = ObjectLiteral.Create( new List <Binding> { new Binding(context.Names.DataSeparator, Environment.NewLine, entry.InvocationLocation), new Binding(context.Names.DataContents, lines, entry.InvocationLocation), }, lines.Location, entry.Path); pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(newData), new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllText: var text = Args.AsString(args, 1); pipData = DataProcessor.ProcessData(context, context.FrontEndContext.PipDataBuilderPool, EvaluationResult.Create(text), new ConversionContext(pos: 1)); break; default: throw Contract.AssertFailure("Unknown WriteFileMode."); } FileArtifact result; if (!context.GetPipConstructionHelper().TryWriteFile(path, pipData, WriteFileEncoding.Utf8, tags, description, out result)) { // Error has been logged return(EvaluationResult.Error); } return(new EvaluationResult(result)); }
private static EvaluationResult DumpCallStack(Context context, ModuleLiteral env, EvaluationStackFrame args) { var message = Args.AsStringOptional(args, 0) ?? string.Empty; var location = context.TopStack.InvocationLocation.AsUniversalLocation(env, context); var stack = context.GetStackTraceAsString(location); context.Logger.DebugDumpCallStack(context.FrontEndContext.LoggingContext, location.AsLoggingLocation(), message, stack); return(EvaluationResult.Undefined); }
private static EvaluationResult IsFalse(Context context, ModuleLiteral env, EvaluationStackFrame args) { var condition = Args.AsBool(args, 0); var message = Args.AsStringOptional(args, 1); Assert.False(condition, message); return(EvaluationResult.Undefined); }
private EvaluationResult SealSourceDirectory(Context context, ModuleLiteral env, EvaluationStackFrame args) { AbsolutePath path; SealDirectoryKind sealDirectoryKind; string[] tags; string description; string[] patterns; if (args.Length > 0 && args[0].Value is ObjectLiteral) { var obj = Args.AsObjectLiteral(args, 0); var directory = Converter.ExtractDirectory(obj, m_sealRoot, allowUndefined: false); path = directory.Path; var include = Converter.ExtractStringLiteral(obj, m_sealInclude, s_includeMap.Keys, allowUndefined: true); sealDirectoryKind = include != null ? s_includeMap[include] : SealDirectoryKind.SourceTopDirectoryOnly; tags = Converter.ExtractStringArray(obj, m_sealTags, allowUndefined: true); description = Converter.ExtractString(obj, m_sealDescription, allowUndefined: true); patterns = Converter.ExtractStringArray(obj, m_sealPatterns, allowUndefined: true); } else { path = Args.AsPath(args, 0, false); var optionAsEnumValue = Args.AsNumberOrEnumValueOptional(args, 1); var option = optionAsEnumValue.HasValue ? (SealSourceDirectoryOption)optionAsEnumValue.Value : SealSourceDirectoryOption.TopDirectoryOnly; sealDirectoryKind = option == SealSourceDirectoryOption.AllDirectories ? SealDirectoryKind.SourceAllDirectories : SealDirectoryKind.SourceTopDirectoryOnly; tags = Args.AsStringArrayOptional(args, 2); description = Args.AsStringOptional(args, 3); patterns = Args.AsStringArrayOptional(args, 4); } DirectoryArtifact sealedDirectoryArtifact; if (!context.GetPipConstructionHelper().TrySealDirectory( directoryRoot: path, contents: s_emptySealContents, outputDirectorycontents: s_emptyOutputDirectoryContents, kind: sealDirectoryKind, tags: tags, description: description, patterns: patterns, sealedDirectory: out sealedDirectoryArtifact)) { // Error has been logged return(EvaluationResult.Error); } var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, s_emptySealContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private static EvaluationResult Assert(Context context, ModuleLiteral env, EvaluationStackFrame args) { bool predicate = Args.AsBool(args, 0); string message = Args.AsStringOptional(args, 1) ?? string.Empty; if (!predicate) { throw new ContractAssertException(message); } return(EvaluationResult.Undefined); }
private EvaluationResult SealDirectoryHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, SealDirectoryKind sealDirectoryKind) { AbsolutePath path; ArrayLiteral contents; string[] tags; string description; bool scrub; if (args.Length > 0 && args[0].Value is ObjectLiteral) { var obj = Args.AsObjectLiteral(args, 0); var directory = Converter.ExtractDirectory(obj, m_sealRoot, allowUndefined: false); path = directory.Path; contents = Converter.ExtractArrayLiteral(obj, m_sealFiles, allowUndefined: false); tags = Converter.ExtractStringArray(obj, m_sealTags, allowUndefined: true); description = Converter.ExtractString(obj, m_sealDescription, allowUndefined: true); scrub = sealDirectoryKind.IsFull() ? Converter.ExtractOptionalBoolean(obj, m_sealScrub) ?? false : false; } else { path = Args.AsPath(args, 0, false); contents = Args.AsArrayLiteral(args, 1); tags = Args.AsStringArrayOptional(args, 2); description = Args.AsStringOptional(args, 3); // Only do scrub for fully seal directory scrub = sealDirectoryKind.IsFull() ? Args.AsBoolOptional(args, 4) : false; } var fileContents = new FileArtifact[contents.Length]; for (int i = 0; i < contents.Length; ++i) { fileContents[i] = Converter.ExpectFile(contents[i], strict: false, context: new ConversionContext(pos: i, objectCtx: contents)); } var sortedFileContents = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(fileContents, OrdinalFileArtifactComparer.Instance); DirectoryArtifact sealedDirectoryArtifact; if (!context.GetPipConstructionHelper().TrySealDirectory(path, sortedFileContents, sealDirectoryKind, tags, description, null, out sealedDirectoryArtifact, scrub)) { // Error has been logged return(EvaluationResult.Error); } var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, sortedFileContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private EvaluationResult GlobFolders(Context context, ModuleLiteral env, EvaluationStackFrame args) { var dirPath = Args.AsPath(args, 0, false); var pathTable = context.FrontEndContext.PathTable; var path = dirPath.ToString(pathTable); // TODO:ST: add different set of function that will distinguish optional from required arguments! string pattern = Args.AsStringOptional(args, 1) ?? "*"; bool recursive = Args.AsBoolOptional(args, 2); var resultPaths = EnumerateFilesOrDirectories(context, path, pattern, directoriesToSkipRecursively: 0, isRecursive: recursive, enumerateDirectory: true); var entry = context.TopStack; return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(resultPaths, entry.InvocationLocation, entry.Path))); }
private static EvaluationResult ReadGraphFragment(Context context, ModuleLiteral env, EvaluationStackFrame args) { var file = Args.AsFile(args, 0); var deps = Args.AsArrayLiteral(args, 1).Values.Select(v => (int)v.Value).ToArray(); var description = Args.AsStringOptional(args, 2) ?? file.Path.ToString(context.PathTable); if (!file.IsSourceFile) { // Do not read output file. throw new FileOperationException( new Exception( I($"Failed adding pip graph fragment file '{file.Path.ToString(context.PathTable)}' because the file is not a source file"))); } Contract.Assert(context.FrontEndContext.FileSystem.Exists(file.Path), "Fragment file does not exist"); int id = Interlocked.Increment(ref s_uniqueFragmentId); var readFragmentTask = context.FrontEndHost.PipGraphFragmentManager.AddFragmentFileToGraph(id, file, deps, description); return(EvaluationResult.Create(id)); }
private static EvaluationResult SealSourceDirectory(Context context, ModuleLiteral env, EvaluationStackFrame args) { AbsolutePath path = Args.AsPath(args, 0, false); var optionAsEnumValue = Args.AsNumberOrEnumValueOptional(args, 1); var option = optionAsEnumValue.HasValue ? (SealSourceDirectoryOption)optionAsEnumValue.Value : SealSourceDirectoryOption.TopDirectoryOnly; var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); var patterns = Args.AsStringArrayOptional(args, 4); var sealDirectoryKind = option == SealSourceDirectoryOption.AllDirectories ? SealDirectoryKind.SourceAllDirectories : SealDirectoryKind.SourceTopDirectoryOnly; DirectoryArtifact sealedDirectoryArtifact; if (!context.GetPipConstructionHelper().TrySealDirectory(path, s_emptySealContents, sealDirectoryKind, tags, description, patterns, out sealedDirectoryArtifact)) { // Error has been logged return(EvaluationResult.Error); } var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, s_emptySealContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private EvaluationResult GlobImpl(Context context, EvaluationStackFrame args, SearchOption searchOption) { AbsolutePath dirPath = Args.AsPath(args, 0, false); var pathTable = context.FrontEndContext.PathTable; var path = dirPath.ToString(pathTable); string pattern = Args.AsStringOptional(args, 1) ?? "*"; uint directoriesToSkipRecursively = 0; if (pattern.Length > 2) { if (pattern[0] == '*' && pattern[1] == '/' || pattern[1] == '\\') { pattern = pattern.Substring(2); directoriesToSkipRecursively = 1; } } var sw = Stopwatch.StartNew(); var resultPaths = EnumerateFilesOrDirectories( context, path, pattern, directoriesToSkipRecursively, searchOption == SearchOption.AllDirectories, enumerateDirectory: false); sw.Stop(); Interlocked.Add(ref context.Statistics.TotalGlobTimeInTicks, sw.Elapsed.Ticks); var entry = context.TopStack; return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(resultPaths, entry.InvocationLocation, entry.Path))); }
private static EvaluationResult ComposeSharedOpaqueDirectories(Context context, ModuleLiteral env, EvaluationStackFrame args) { AbsolutePath root = Args.AsPath(args, 0, false); ArrayLiteral contents = Args.AsArrayLiteral(args, 1); var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); var directories = new DirectoryArtifact[contents.Length]; for (int i = 0; i < contents.Length; ++i) { directories[i] = Converter.ExpectSharedOpaqueDirectory(contents[i], context: new ConversionContext(pos: i, objectCtx: contents)).Root; } if (!context.GetPipConstructionHelper().TryComposeSharedOpaqueDirectory(root, directories, description, tags, out var compositeSharedOpaque)) { // Error should have been logged return(EvaluationResult.Error); } var result = new StaticDirectory(compositeSharedOpaque, SealDirectoryKind.SharedOpaque, s_emptySealContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private static EvaluationResult CopyFile(Context context, ModuleLiteral env, EvaluationStackFrame args) { var source = Args.AsFile(args, 0); var destination = Args.AsPath(args, 1); var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); var writable = Args.AsBoolOptional(args, 4); CopyFile.Options options = default; if (writable) { options = BuildXL.Pips.Operations.CopyFile.Options.OutputsMustRemainWritable; } FileArtifact result; if (!context.GetPipConstructionHelper().TryCopyFile(source, destination, options, tags, description, out result)) { // Error has been logged return(EvaluationResult.Error); } return(new EvaluationResult(result)); }
private EvaluationResult GetKeyForm(Context context, ModuleLiteral env, EvaluationStackFrame args) { var keyFormDll = Args.AsFile(args, 0); var arch = Args.AsString(args, 1); var name = Args.AsString(args, 2); var version = Args.AsString(args, 3); var publicKeyToken = Args.AsString(args, 4); var versionScope = Args.AsStringOptional(args, 5); var culture = Args.AsStringOptional(args, 6); var type = Args.AsStringOptional(args, 7); var handler = m_handlers.GetOrAdd( keyFormDll.Path, _ => { var keyFormDllPath = keyFormDll.Path.ToString(context.PathTable); var fileName = Path.GetFileName(keyFormDllPath); if (!string.Equals(KeyFormFileName, fileName, StringComparison.OrdinalIgnoreCase)) { throw new KeyFormDllWrongFileNameException(keyFormDllPath, KeyFormFileName, new ErrorContext(pos: 1)); } if (!File.Exists(keyFormDllPath)) { throw new KeyFormDllNotFoundException(keyFormDllPath, new ErrorContext(pos: 1)); } IntPtr moduleHandle = NativeMethods.LoadLibraryW(keyFormDllPath); if (moduleHandle == IntPtr.Zero) { var lasterror = Marshal.GetLastWin32Error(); var ex = new Win32Exception(lasterror); throw new KeyFormDllLoadException(keyFormDllPath, lasterror, ex.Message, new ErrorContext(pos: 1)); } IntPtr procHandle = NativeMethods.GetProcAddress(moduleHandle, KeyFormFunction); if (procHandle == IntPtr.Zero) { var lasterror = Marshal.GetLastWin32Error(); var ex = new Win32Exception(lasterror); throw new KeyFormDllLoadException(keyFormDllPath, lasterror, ex.Message, new ErrorContext(pos: 1)); } return(Marshal.GetDelegateForFunctionPointer <GetKeyFormHandler>(procHandle)); }); using (var pooledBuilder = m_stringBuilderCache.GetInstance()) { var builder = pooledBuilder.Instance; try { // Since this is native code hardening our process against threading issues // in the native code by ensuring we only access from single thread. // WIP: experimental. Removing locking for key form. // lock (m_keyFormLock) { handler(arch, name, version, publicKeyToken, versionScope, culture, type, builder, (uint)builder.Capacity); } } catch (Exception e) { // I know it is bad to catch all exceptions, but this is going into native code of which we // don't have control and this code doesn't handle weird input properly. var keyFormDllPath = keyFormDll.Path.ToString(context.PathTable); throw new KeyFormNativeFailureException(keyFormDllPath, e, new ErrorContext(pos: 1)); } return(EvaluationResult.Create(builder.ToString())); } }
private EvaluationResult WriteFileHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, WriteFileMode mode) { AbsolutePath path; string[] tags; string description; PipData pipData; if (args.Length > 0 && args[0].Value is ObjectLiteral) { var obj = Args.AsObjectLiteral(args, 0); path = Converter.ExtractPath(obj, m_writeOutputPath, allowUndefined: false); tags = Converter.ExtractStringArray(obj, m_writeTags, allowUndefined: true); description = Converter.ExtractString(obj, m_writeDescription, allowUndefined: true); switch (mode) { case WriteFileMode.WriteData: var data = obj[m_writeContents]; pipData = ProcessData(context, data, new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllLines: var lines = Converter.ExtractArrayLiteral(obj, m_writeLines); var entry = context.TopStack; var newData = ObjectLiteral.Create( new List <Binding> { new Binding(m_dataSeparator, Environment.NewLine, entry.InvocationLocation), new Binding(m_dataContents, lines, entry.InvocationLocation), }, lines.Location, entry.Path); pipData = ProcessData(context, EvaluationResult.Create(newData), new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllText: var text = Converter.ExtractString(obj, m_writeText); pipData = ProcessData(context, EvaluationResult.Create(text), new ConversionContext(pos: 1)); break; default: throw Contract.AssertFailure("Unknown WriteFileMode."); } } else { path = Args.AsPath(args, 0, false); tags = Args.AsStringArrayOptional(args, 2); description = Args.AsStringOptional(args, 3); switch (mode) { case WriteFileMode.WriteFile: var fileContent = Args.AsIs(args, 1); // WriteFile has a separator argument with default newline var separator = Args.AsStringOptional(args, 3) ?? Environment.NewLine; description = Args.AsStringOptional(args, 4); pipData = CreatePipDataForWriteFile(context, fileContent, separator); break; case WriteFileMode.WriteData: var data = Args.AsIs(args, 1); pipData = ProcessData(context, EvaluationResult.Create(data), new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllLines: var lines = Args.AsArrayLiteral(args, 1); var entry = context.TopStack; var newData = ObjectLiteral.Create( new List <Binding> { new Binding(m_dataSeparator, Environment.NewLine, entry.InvocationLocation), new Binding(m_dataContents, lines, entry.InvocationLocation), }, lines.Location, entry.Path); pipData = ProcessData(context, EvaluationResult.Create(newData), new ConversionContext(pos: 1)); break; case WriteFileMode.WriteAllText: var text = Args.AsString(args, 1); pipData = ProcessData(context, EvaluationResult.Create(text), new ConversionContext(pos: 1)); break; default: throw Contract.AssertFailure("Unknown WriteFileMode."); } } FileArtifact result; if (!context.GetPipConstructionHelper().TryWriteFile(path, pipData, WriteFileEncoding.Utf8, tags, description, out result)) { // Error has been logged return(EvaluationResult.Error); } return(new EvaluationResult(result)); }