Add Bundler.ComputeBundleContents API#127962
Open
elinor-fung wants to merge 1 commit intodotnet:mainfrom
Open
Conversation
Add a public ComputeBundleContents method to the Bundler class that allows callers to compute which files would be included in or excluded from a bundle without actually generating the bundle. This enables the SDK to properly support incrementality for bundle generation by knowing the included/excluded file lists ahead of time. - Add BundleContents class with Host, FilesToBundle, and ExcludedFromBundle - Add ComputeBundleContents method that reuses existing filtering logic - Add GenerateBundle(BundleContents) overload that skips filtering - Remove IsHost check from GetFilteredFileSpecs (callers pre-filter) - Add tests covering various BundleOptions, duplicates, error cases, and round-trip through GenerateBundle(BundleContents) Fixes dotnet#124051 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @agocke, @elinor-fung, @VSadov |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a new public API to the HostModel single-file bundler to precompute bundle membership (included vs. excluded files) without emitting a bundle, and refactors bundle generation to reuse that computation path.
Changes:
- Introduces
BundleContents(host + included/excluded file lists) as a new public type inMicrosoft.NET.HostModel.Bundle. - Adds
Bundler.ComputeBundleContents(IReadOnlyList<FileSpec>)and aBundler.GenerateBundle(BundleContents)overload, and refactorsGenerateBundle(IReadOnlyList<FileSpec>)to delegate through the new API. - Adds tests for
ComputeBundleContentsand a round-trip equivalence check between the old and new generation paths.
Show a summary per file
| File | Description |
|---|---|
| src/installer/tests/Microsoft.NET.HostModel.Tests/Bundle/BundlerConsistencyTests.cs | Adds coverage for the new precompute API and compares manifest output between direct vs. precomputed generation. |
| src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs | Adds the precompute API, new overload, and refactors generation to reuse the computed contents. |
| src/installer/managed/Microsoft.NET.HostModel/Bundle/BundleContents.cs | Adds the new public BundleContents type used to carry precomputed bundle membership. |
Copilot's findings
- Files reviewed: 3/3 changed files
- Comments generated: 5
Comment on lines
+11
to
+26
| public sealed class BundleContents | ||
| { | ||
| /// <summary> | ||
| /// The host binary that serves as the bundle container. | ||
| /// </summary> | ||
| public FileSpec Host { get; } | ||
|
|
||
| /// <summary> | ||
| /// Files that will be embedded in the bundle. | ||
| /// </summary> | ||
| public IReadOnlyList<FileSpec> IncludedFiles { get; } | ||
|
|
||
| /// <summary> | ||
| /// Files that are excluded from the bundle and should be published alongside the host. | ||
| /// </summary> | ||
| public IReadOnlyList<FileSpec> ExcludedFiles { get; } |
Comment on lines
+467
to
+472
| FileSpec? hostSpec = fileSpecs.FirstOrDefault(x => IsHost(x.BundleRelativePath)); | ||
| if (hostSpec is null) | ||
| { | ||
| throw new ArgumentException("Invalid input specification: Must specify the host binary"); | ||
| } | ||
|
|
Comment on lines
+460
to
+478
| public BundleContents ComputeBundleContents(IReadOnlyList<FileSpec> fileSpecs) | ||
| { | ||
| if (fileSpecs.Any(x => !x.IsValid())) | ||
| { | ||
| throw new ArgumentException("Invalid input specification: Found entry with empty source-path or bundle-relative-path."); | ||
| } | ||
|
|
||
| FileSpec? hostSpec = fileSpecs.FirstOrDefault(x => IsHost(x.BundleRelativePath)); | ||
| if (hostSpec is null) | ||
| { | ||
| throw new ArgumentException("Invalid input specification: Must specify the host binary"); | ||
| } | ||
|
|
||
| var included = GetFilteredFileSpecs(fileSpecs.Where(x => !IsHost(x.BundleRelativePath))); | ||
| return new BundleContents( | ||
| hostSpec, | ||
| included, | ||
| fileSpecs.Where(x => x.Excluded).ToArray()); | ||
| } |
Comment on lines
+269
to
+287
| /// <summary> | ||
| /// Generate a bundle from the given <see cref="BundleContents"/>, | ||
| /// as computed by <see cref="ComputeBundleContents"/>. | ||
| /// </summary> | ||
| /// <param name="bundleContents"> | ||
| /// The bundle contents from <see cref="ComputeBundleContents"/>. | ||
| /// </param> | ||
| /// <returns> | ||
| /// The full path of the generated bundle file. | ||
| /// </returns> | ||
| public string GenerateBundle(BundleContents bundleContents) | ||
| { | ||
| _tracer.Log($"Bundler Version: {BundlerMajorVersion}.{BundlerMinorVersion}"); | ||
| _tracer.Log($"Bundle Version: {BundleManifest.BundleVersion}"); | ||
| _tracer.Log($"Target Runtime: {_target}"); | ||
| _tracer.Log($"Bundler Options: {_options}"); | ||
| if (fileSpecs.Any(x => !x.IsValid())) | ||
| { | ||
| throw new ArgumentException("Invalid input specification: Found entry with empty source-path or bundle-relative-path."); | ||
| } | ||
| string hostSource; | ||
| try | ||
| { | ||
| hostSource = fileSpecs.Where(x => x.BundleRelativePath.Equals(_hostName)).Single().SourcePath; | ||
| } | ||
| catch (InvalidOperationException) | ||
| { | ||
| throw new ArgumentException("Invalid input specification: Must specify the host binary"); | ||
| } | ||
|
|
||
| (FileSpec Spec, FileType Type)[] relativePathToSpec = GetFilteredFileSpecs(fileSpecs); | ||
| string hostSource = bundleContents.Host.SourcePath; | ||
| (FileSpec Spec, FileType Type)[] relativePathToSpec = bundleContents.TypedIncludedFiles; |
Comment on lines
+412
to
+417
| string directBundlePath = directBundler.GenerateBundle(fileSpecs); | ||
|
|
||
| // Generate bundle via ComputeBundleContents + GenerateBundle(BundleContents) | ||
| Bundler computedBundler = CreateBundlerInstance(); | ||
| BundleContents contents = computedBundler.ComputeBundleContents(fileSpecs); | ||
| string computedBundlePath = computedBundler.GenerateBundle(contents); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This PR description was generated with assistance from GitHub Copilot.
Addresses #124051
Adds an API to compute which files would be included in or excluded from a single-file bundle without actually generating the bundle. This enables the SDK to properly support build incrementality by determining bundle membership ahead of time.
New API
Changes
BundleContentsclass withHost,IncludedFiles, andExcludedFilespropertiesBundler.ComputeBundleContents()to determine bundle membership without generating the bundleBundler.GenerateBundle(BundleContents)overload to generate a bundle from pre-computed contents (skipping re-filtering and type inference)GenerateBundle(IReadOnlyList<FileSpec>)to delegate throughComputeBundleContentsGetFilteredFileSpecsinto both callers for clarityComputeBundleContentscovering allBundleOptionsvariants and round-trip equivalence withGenerateBundle