protected override Task <IDocument <Stream> > Work(IDocument <string> input, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var output = input.With(() => new MemoryStream(System.Text.Encoding.UTF8.GetBytes(input.Value)), input.Hash); return(Task.FromResult <IDocument <Stream> >(output)); }
protected override async Task <ImmutableList <IDocument <GitRef> > > Work(IDocument <string> source, OptionToken options) { if (source is null) { throw new ArgumentNullException(nameof(source)); } if (options is null) { throw new ArgumentNullException(nameof(options)); } if (this.repo is null || source.Value != this.previousSource) { if (this.repo != null) { if (this.workingDir is null) { throw new InvalidOperationException("the working dir should exist if repo does."); } // TODO: Should we realy dispose this already? // I think we need to track who else has a reference to an object cretaed by this repo :/ this.repo.Dispose(); // this.workingDir.Delete(true); } this.workingDir = this.Context.TempDir(); this.previousSource = source.Value; this.repo = await Task.Run(() => new Repository(Repository.Clone(source.Value, this.workingDir.FullName, new CloneOptions() { IsBare = true }))).ConfigureAwait(false); }
protected override async Task <StageResultList <TOut, TInItemCache, WhereStageCache <TInCache> > > DoInternal([AllowNull] WhereStageCache <TInCache>?cache, OptionToken options) { var input = await this.input(cache?.ParentCache, options).ConfigureAwait(false); var task = LazyTask.Create(async() => { var inputList = await input.Perform; var list = (await Task.WhenAll(inputList.result.Select(async subInput => { bool pass; if (subInput.HasChanges) { var(result, itemCache) = await subInput.Perform; pass = await this.predicate(result).ConfigureAwait(false); } else { if (cache is null) { throw new InvalidOperationException("This shoudl not happen. if item has no changes, ther must be a child cache."); } // since HasChanges if false, it was present in the last invocation // if it is passed this it was added to thec cache otherwise not. pass = cache.OutputIdOrder.Contains(subInput.Id); } if (pass) { return(subInput); } else { return(null); } })).ConfigureAwait(false)).Where(x => x != null); var newCache = new WhereStageCache <TInCache>() { OutputIdOrder = list.Select(x => x.Id).ToArray(), ParentCache = inputList.cache }; return(result: list.ToImmutableList(), cache: newCache); }); bool hasChanges = input.HasChanges; var newCache = cache; if (input.HasChanges || newCache == null) { var(list, c) = await task; newCache = c; if (!hasChanges && list.Count != cache?.OutputIdOrder.Length) { hasChanges = true; } if (!hasChanges && cache != null) { for (int i = 0; i < cache.OutputIdOrder.Length && !hasChanges; i++) { if (list[i].Id != cache.OutputIdOrder[i]) { hasChanges = true; } if (list[i].HasChanges) { hasChanges = true; } } } } return(StageResultList.Create(task, hasChanges, newCache.OutputIdOrder.ToImmutableList())); }
protected override void Context() { Token = Scanner.GetNextToken(2); optionToken = (OptionToken)Token; }
protected override Task <ImmutableList <IDocument <Stream> > > Work(IDocument <GitRef> source, OptionToken options) { if (source is null) { throw new ArgumentNullException(nameof(source)); } var queue = new Queue <Tree>(); queue.Enqueue(source.Value.Tip.Tree); var blobs = ImmutableList <IDocument <Stream> > .Empty.ToBuilder(); while (queue.TryDequeue(out var tree)) { foreach (var entry in tree) { switch (entry.Target) { case Blob blob: var document = new GitFileDocument(entry.Path, blob, this.Context, null); blobs.Add(document); break; case Tree subTree: queue.Enqueue(subTree); break; case GitLink link: throw new NotSupportedException("Git link is not supported at the momtent"); default: throw new NotSupportedException($"The type {entry.Target?.GetType().FullName ?? "<NULL>"} is not supported as target"); } } } return(Task.FromResult(blobs.ToImmutable())); }
protected override Task <IDocument <MarkdownDocument> > Work(IDocument <MarkdownDocument> input, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var document = input.Value; var yamlHeader = document.Blocks.OfType <Microsoft.Toolkit.Parsers.Markdown.Blocks.YamlHeaderBlock>(); var newMarkdown = new MarkdownDocument { Blocks = document.Blocks.Where(x => !(x is Microsoft.Toolkit.Parsers.Markdown.Blocks.YamlHeaderBlock)).ToList() }; var newDocument = input.With(newMarkdown, this.Context.GetHashForString(newMarkdown.ToString())); var metadata = newDocument.Metadata; var metadataEntrys = yamlHeader.Select(x => { if (TryGetObjecFrom <TMetadata>(x.Children.ToDictionary(x => x.Key, x => x.Value as object), out var parsed)) { return(parsed); } return(null); }) !.Where <TMetadata>(x => !(x is null)); foreach (var entry in metadataEntrys) { if (this.update is null) { metadata = metadata.AddOrUpdate(entry); } else { metadata = metadata.AddOrUpdate(entry, this.update); } } newDocument.With(metadata); return(Task.FromResult(newDocument)); }
protected override Task <IDocument <MarkdownDocument> > Work(IDocument <string> input, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var document = new MarkdownDocument(); document.Parse(input.Value); var hash = this.Context.GetHashForString(document.ToString()); return(Task.FromResult(input.With(document, hash))); }
protected override async Task <IDocument <MarkdownDocument> > Work(IDocument <Stream> input, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var document = new MarkdownDocument(); string content; using (var stream = input.Value) using (var reader = new StreamReader(stream)) content = await reader.ReadToEndAsync().ConfigureAwait(false); document.Parse(content); var hash = this.Context.GetHashForString(document.ToString()); return(input.With(document, hash)); }
protected override async Task <StageResultList <TOut, string, TransformStageCache <TInCache> > > DoInternal([AllowNull] TransformStageCache <TInCache>?cache, OptionToken options) { var input = await this.input(cache?.ParentCache, options).ConfigureAwait(false); var task = LazyTask.Create(async() => { var inputList = await input.Perform; var list = await Task.WhenAll(inputList.result.Select(async subInput => { if (subInput.HasChanges) { var subResult = await subInput.Perform; var transformed = await this.transform(subResult.result).ConfigureAwait(false); bool hasChanges = true; if (cache != null && cache.Transformed.TryGetValue(transformed.Id, out var oldHash)) { hasChanges = oldHash == transformed.Hash; } return(result: StageResult.Create(transformed, transformed.Hash, hasChanges, transformed.Id), inputId: subInput.Id, outputHash: transformed.Hash); } else { if (cache == null || !cache.InputToOutputId.TryGetValue(subInput.Id, out var oldOutputId) || !cache.Transformed.TryGetValue(subInput.Id, out var oldOutputHash)) { throw this.Context.Exception("No changes, so old value should be there."); } return(result: StageResult.Create(LazyTask.Create(async() => { var newSource = await subInput.Perform; var transformed = await this.transform(newSource.result).ConfigureAwait(false); return (transformed, transformed.Hash); }), false, oldOutputId), inputId: subInput.Id, outputHash: oldOutputHash ); } })).ConfigureAwait(false); var newCache = new TransformStageCache <TInCache>() { InputToOutputId = list.ToDictionary(x => x.inputId, x => x.result.Id), OutputIdOrder = list.Select(x => x.result.Id).ToArray(), ParentCache = inputList.cache, Transformed = list.ToDictionary(x => x.result.Id, x => x.outputHash) }; return(result: list.Select(x => x.result).ToImmutableList(), cache: newCache); }); bool hasChanges = input.HasChanges; var newCache = cache; if (input.HasChanges || newCache == null) { var(list, c) = await task; newCache = c; if (!hasChanges && list.Count != cache?.OutputIdOrder.Length) { hasChanges = true; } if (!hasChanges && cache != null) { for (int i = 0; i < cache.OutputIdOrder.Length && !hasChanges; i++) { if (list[i].Id != cache.OutputIdOrder[i]) { hasChanges = true; } if (list[i].HasChanges) { hasChanges = true; } } } } return(StageResultList.Create(task, hasChanges, newCache.OutputIdOrder.ToImmutableList())); }
protected override Task <IDocument <TIn> > Work(ImmutableList <IDocument <TIn> > result, OptionToken options) { if (result is null) { throw new ArgumentNullException(nameof(result)); } if (result.Count != 1) { throw this.Context.Exception($"There should only be one Document but where {result.Count}"); } var element = result[0]; return(Task.FromResult(element)); }
protected override async Task <StageResultList <Stream, string, TransformStageCache <TInCache> > > DoInternal([AllowNull] TransformStageCache <TInCache>?cache, OptionToken options) { var input = await this.input(cache?.ParentCache, options).ConfigureAwait(false); var task = LazyTask.Create(async() => { var inputList = await input.Perform; var sidecarLookup = inputList.result.Where(x => Path.GetExtension(x.Id) == this.SidecarExtension) .ToDictionary(x => Path.Combine(Path.GetDirectoryName(x.Id) ?? string.Empty, Path.GetFileNameWithoutExtension(x.Id))); var files = inputList.result.Where(x => Path.GetExtension(x.Id) != this.SidecarExtension); var list = await Task.WhenAll(files.Select(async file => { if (sidecarLookup.TryGetValue(file.Id, out var sidecar) && (file.HasChanges || sidecar.HasChanges)) { var(fileResult, fileCache) = await file.Perform; var(sidecarResult, sidecarCache) = await sidecar.Perform; var deserializer = new YamlDotNet.Serialization.DeserializerBuilder() .WithNamingConvention(YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention.Instance) .Build(); var oldMetadata = fileResult.Metadata; MetadataContainer?newMetadata; try { using var stream = sidecarResult.Value; using var reader = new StreamReader(stream); var metadata = deserializer.Deserialize <TMetadata>(reader); if (metadata != null) { if (this.update != null) { newMetadata = oldMetadata.AddOrUpdate(metadata.GetType(), metadata, (oldValue, newValue) => this.update((TMetadata)oldValue !/*AllowNull is set, so why the warnign?*/, (TMetadata)newValue)); } else { newMetadata = oldMetadata.Add(metadata.GetType(), metadata); } } else { newMetadata = null; } } catch (YamlDotNet.Core.YamlException e) when(e.InnerException is null) // Hope that only happens when it does not match. { newMetadata = null; } if (newMetadata != null) { fileResult = fileResult.With(newMetadata); } var hasChanges = true; if (cache != null && cache.Transformed.TryGetValue(fileResult.Id, out var oldHash)) { hasChanges = oldHash != fileResult.Hash; } return(result: StageResult.Create <Stream, string>(fileResult, fileResult.Hash, hasChanges, fileResult.Id), inputId: file.Id, outputHash: fileResult.Hash); } else if (file.HasChanges) { var(fileResult, fileCache) = await file.Perform; var hasChanges = true; if (cache != null && cache.Transformed.TryGetValue(fileResult.Id, out var oldHash)) { hasChanges = oldHash != fileResult.Hash; } System.Diagnostics.Debug.Assert(hasChanges); // if the original file had changes so must this have. return(result: StageResult.Create <Stream, string>(fileResult, fileResult.Hash, hasChanges, fileResult.Id), inputId: file.Id, outputHash: fileResult.Hash); } else { if (cache == null || !cache.InputToOutputId.TryGetValue(file.Id, out var oldOutputId) || !cache.Transformed.TryGetValue(file.Id, out var oldOutputHash)) { throw this.Context.Exception("No changes, so old value should be there."); } var task = LazyTask.Create(async() => { var(fileResult, fileCache) = await file.Perform; return(fileResult, fileResult.Hash); }); return(result: StageResult.Create(task, false, oldOutputId), inputId: file.Id, outputHash: oldOutputHash); } })).ConfigureAwait(false); var newCache = new TransformStageCache <TInCache>() { InputToOutputId = list.ToDictionary(x => x.inputId, x => x.result.Id), OutputIdOrder = list.Select(x => x.result.Id).ToArray(), ParentCache = inputList.cache, Transformed = list.ToDictionary(x => x.result.Id, x => x.outputHash) }; return(result: list.Select(x => x.result).ToImmutableList(), cache: newCache); }); bool hasChanges = input.HasChanges; var newCache = cache; if (input.HasChanges || newCache == null) { var(list, c) = await task; newCache = c; if (!hasChanges && list.Count != cache?.OutputIdOrder.Length) { hasChanges = true; } if (!hasChanges && cache != null) { for (int i = 0; i < cache.OutputIdOrder.Length && !hasChanges; i++) { if (list[i].Id != cache.OutputIdOrder[i]) { hasChanges = true; } if (list[i].HasChanges) { hasChanges = true; } } } } return(StageResultList.Create(task, hasChanges, newCache.OutputIdOrder.ToImmutableList())); }
protected override async Task <IDocument <string> > Work(IDocument <T> input, IDocument <RazorProvider> rendererDocument, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } if (rendererDocument is null) { throw new ArgumentNullException(nameof(rendererDocument)); } var renderer = rendererDocument.Value.Renderer; var result = await renderer.RenderViewToStringAsync(input.Id, input.Metadata).ConfigureAwait(false); var output = input.With(result, this.Context.GetHashForString(result)); return(output); }
protected override Task <IDocument <RazorProvider> > Work(ImmutableList <IDocument <IFileProvider> > inputList0, OptionToken options) { var render = new RazorProvider(RazorViewToStringRenderer.GetRenderer(inputList0.Select(x => x.Value), this.ContentId)); var hash = this.Context.GetHashForString(string.Join(",", inputList0.Select(x => x.Hash))); return(Task.FromResult(this.Context.Create(render, hash, this.id))); }
protected override Task <IDocument <string> > Work(IDocument <MarkdownDocument> input, OptionToken options) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var builder = new StringBuilder(); this.Render(builder, input.Value.Blocks); var text = builder.ToString(); return(Task.FromResult(input.With(text, this.Context.GetHashForString(text)))); }
protected override Task <IDocument <IFileProvider> > Work(ImmutableList <IDocument <Stream> > inputList0, OptionToken options) { var provider = new FileProvider(inputList0, this.ProviderId); var hash = this.Context.GetHashForString(string.Join(",", inputList0.Select(x => x.Hash))); IDocument <IFileProvider> document = this.Context.Create(provider, hash, this.ProviderId); return(Task.FromResult(document)); }
protected override Task <StageResult <TResult, string> > DoInternal([AllowNull] string?cache, OptionToken options) { var contentHash = this.hashFunction(this.Value); return(Task.FromResult(StageResult.Create( result: this.Context.Create(this.Value, contentHash, this.id), cache: contentHash, hasChanges: cache != contentHash, documentId: this.id))); }